Ruby on Rails
Rails作者
参考
Railsガイド
RailsとClean Architectureに関する考察
【Rails】hashid-railsを用いてIDを難読化・暗号化させる方法
Rails処理概要
Rails APIモード
Ruby on Rails
をバックエンドサーバーとして使用する場合、通常はアプリをAPIとして設定するだけで、セッション、Cookie、レンダリングビューなどの一部の機能がデフォルトで無効になります。
Rails APIモードでactive adminを導入する方法
Rails 名前空間について
参考URL
入れ子とショートシンタックスの違い
Railsでの名前空間について(わかりやすい)
Ruby自体には「名前空間」という名前の機能がありません。しかし、「名前空間」を実現出来ないというわけではありません。モジュールが「名前空間」の機能を提供するとなっています。 まず、勘違いしてはいけないのは、モジュールは「名前空間」のためだけの機能ではないことです。他のクラスやモジュールにMix-inしたり、オブジェクトそのものの拡張(extend)したり、再定義(refine)の機能を使うためにusingしたりします。それら多くの機能の一つとして、「名前空間」の機能があると言うことです。なお、クラスもモジュールを拡張しているため、同じように「名前空間」に使用することができます。
Rubyにおいて、モジュールを定義する方法には2つの異なるスタイルがある
それぞれが異なる文脈で使用される。
1. ネストされたモジュールの定義:
module Infrastructures
module Nid
end
end
この方法は、モジュールをネスト(入れ子)する形で定義しています。ここでは、Infrastructures
モジュールの内部に Nid
モジュールを定義しています。このスタイルは、親モジュール(この場合は Infrastructures
)がすでに定義されているか、同じスコープ内で定義される場合に使われます。
2. 修飾されたモジュール名を使用した定義:
module Infrastructures::Nid
end
こちらの定義方法では、修飾されたモジュール名(Infrastructures::Nid
)を使用して、モジュールを一行で定義しています。この方法は、親モジュールがすでに定義されている、またはその定義が不要な場合に便利です。ただし、 このスタイルを使用する際には、親モジュール(Infrastructures
)がすでに定義されていることが前提となります。
主な違い
- 前提条件: 修飾されたモジュール名を使用する方法では、親モジュールがすでに存在している必要があります。ネストされた定義では、親モジュールが存在しない場合でも、その場で定義できます。
- コンテキストの明確化: ネストされた定義の方が、モジュールの階層が明確になります。これは、特に大きなアプリケーションや複雑な名前空間の構造を持つ場合に役立ちます。
どちらのスタイルを使用するかは、そのモジュールがどのような文脈で使用されるか、およびコードの可読性や整理のしやすさによって決まります。ただし、両者の間には機能的な違いはありません。モジュールの振る舞いやアクセス可能性に影響を与えることはありません。
Railsオートロードするファイル(autoload_paths)
# Railsが自動で読み込むファイルは、以下のディレクトリ内にあるファイルです。
app/assets
app/channels
app/controllers
app/helpers
app/jobs
app/mailers
app/models
app/views
また、Railsの命名規則にしたがっているファイルも自動的に読み込まれます。具体的には、以下のようなファイル名に対応しています。
- モデル名の単数形.rb
- コントローラー名の複数形_controller.rb
- ヘルパー名の複数形_helper.rb
- ビュー名の複数形.erb、haml、slimなどのテンプレートエンジンの拡張子を持つファイル
- ジョブ名の複数形_job.rb
- メーラー名の複数形_mailer.rb
以上の命名規則にしたがって、自動的にファイルを読み込むことができます。ただし、ディレクトリ構造やファイル名が命名規則に従っていない場合は、明示的にrequireする必要があります。
autoload_pathsの仕様
autoload_paths
はディレクトリを自動で読み込むための設定であり、その中にあるファイルやモジュールまでは自動的に読み込むわけではありません。
ただし、モジュール名やファイル名がRailsの命名規則に沿っている場合は、明示的にrequireする必要はありません。ただし、独自の命名規則を採用している場合は、明示的にrequireする必要があります。
.ruと.rbの違い
.rbファイル
は、Rubyのソースコードが含まれるファイル
.ruファイル
は、Rackアプリケーションのエントリーポイントとして機能するRack upファイル
具体的には .rbファイル
はRubyスクリプトを作成するために使用 され、Rubyコードを実行するために、Rubyインタープリターまたはコンパイラによって読み込まれます。
一方 .ruファイル
は、Rackアプリケーションのエントリーポイントであり、Webサーバーによって読み込まれ、Rackアプリケーションを起動します。
Rackは、Webアプリケーションのインターフェースとして機能する仕組みで、.ruファイルにはRackアプリケーションの情報が含まれています。.rbファイルとは異なり、.ruファイルには実際のアプリケーションコードが含まれていない場合があります。
RackとRakeの違い
RackとRakeは、Rubyのウェブ開発において異なる目的と役割を持つ2つの異なるコンポーネント。
Rack
Rackは、Rubyのウェブアプリケーションフレームワークとウェブサーバーの間のインターフェースを提供するライブラリです。
Rackは、ウェブリクエストとレスポンスの処理を抽象化し、ウェブアプリケーションがさまざまなウェブサーバー上で動作することを可能にします。Rackは、ウェブアプリケーションのミドルウェアを管理し、リクエストの受信からレスポンスの生成までのプロセスを制御します。
Rake
Rakeは、Rubyのビルドツールおよびタスクランナーです。Rakeは、プロジェクトのビルド、テスト、デプロイメントなどの一連のタスクを定義し、実行するための機能を提供します。Rakeは、RubyのDSL(Domain-Specific Language)を使用してタスクを記述し、依存関係 や実行順序などを指定できます。Rakeは特に、Ruby on Railsなどのフレームワークで頻繁に使用され、開発者が独自のカスタムタスクを作成してプロジェクトの自動化を行うための強力なツールとなっています。
要約すると、Rackはウェブアプリケーションとウェブサーバーのインターフェースを提供するライブラリであり、Rakeはビルドやタスクの自動化のためのツールです。両者は異なる目的を持ち、ウェブ開発においてそれぞれ重要な役割を果たしています。
最新Railsについて
Rails apiモード
以下の3つが行われる。
-
利用するミドルウェアを通常よりも絞り込んでアプリケーションを起動するよう設定する。特に、ブラウザ向けアプリケーションで有用なミドルウェア(cookiesのサポートなど)はデフォルトでは利用しません。
-
ApplicationControllerが通常のActionController::BaseではなくActionController::APIを継承します。ミドルウェアと同様、Action Controllerモジュールのうち、ブラウザ向けアプリケーションでしか使われないモジュールをすべて除外します。
-
ビュー、ヘルパー、アセットを生成しないようジェネレーターを設定します。
Rails 7.0 Node
importmap
Rails 7といえば、Node.jsを裏で使う必要がなくなった。
importmap-rails
が目玉のリリース。
importmap-rails
を使うことで、フロントエンドのJavaScriptのライブラリを管理してくれるようになる。
importmap-rails
これで初期化した Rails アプリには なんと、package.json, yarn.lock が存在しない! その代わりに、config/importmap.rb にて以下の記載がある。
初期化
$ vim Gemfile
gem 'importmap-rails'
$ bundle install
$ bundle exec rails importmap:install
Rails 7.0 assetsまわり
webpackerはなくなっている!
参考URL JavaScript BundlingとCSS Bundlingのしくみ
railsではJS/CSSなどを総称してassetsと呼んでいる
Rails 5-6時代に使われたwebpackerは、公式に「has been retired」とされ、Rails 7では
importmap
が標準となりました。 Rails7はimportmapとは別に、JavaScriptのバンドラやCSSのフレームワークを導入するしくみを用意している。
Rails7.0でのアセット管理
Rails 7.0 では、新たに4つのGemが登場します。これまでとは異なり、開発者はこれらのGemを自分のプロジェクトに合う組み合わせで採用することになります。
Rails7にあとからフロントエンドに入れる
2つのgem
- JavaScript Bundling(jsbundling-rails)
- CSS Bundling(cssbundling-rails)
JavaScript Bundling(jsbundling-rails)
JSファイルを app/assets
の下に出力するもの。
CSS Bundling(cssbundling-rails)
CSSフレームワーク(Bootstrapやbulma)をsassコマンドでapp/assetsの下に出力する。 バンドラやCSSフレームワークはyarnコマンドでnode_modules下にインストールされる
後から入れる
各コマンドは、package.jsonの中で指定されます。 開発環境では、foreman(bin/dev)を使ってRailsサーバー、JSの変更監視、CSSの変更監視、の3つを動かす。
# 後からbootstrapを入れる
bin/rails css:install:bootstrap
# Procfile.dev
# package.json
# bin/dev
# 3つができる
Procfile.dev
アプリケーションのルートにできる Procfile.dev
では、一度に3つのプログラム(rails、JSバンドラ、sass)が常駐するように設定してある。
--watch
オプションによってファイルを監視し、変更があれば自動的に変換する。
binディレク トリの下のdevコマンドでは、foremanを使って Procfile.dev
のコマンドを動かしている。
foremanがないときは自動的にインストールされる。
Railsスタイルガイド
シンボル名、メソッド名、変数名はスネークケースにする
Rails generateコマンド
# formオブジェクトを作成する
$ rails generate form signUpForm
フォームオブジェクト(Form Object)
app/forms
ディレクトリは、Railsアプリケーション内でフォームオブジェクトを作成するためのディレクトリ。
フォームオブジェクトは、モデルとは異なり、DBに保存されないデータの処理やバリデーションを行うために使われる。
フォームオブジェクトは、ActiveModelをincludeして作成されるため、ActiveModelの機能やバリデーションを使うことができます。
フォームオブジェクトを利用することで、ビジネスロジックをモデルから分離して、コントローラーからも処理を分離できます。
たとえば、複数のモデルをまたいで1つのフォームに入力したり、モデルには関係ない入力項目に対してバリデーションを設定する場合などに、フォームオブジェクトを使用できる。
Railsにおけるフォームオブジェクト(Form Object)は、アプリケーションでフォームの入力データを処理するためのオブジェクトです。 Railsでは、主にActiveModelを拡張してフォームオブジェクトを作成する。
フォームオブジェクトは、以下のような目的で使用されます:
- フォームの入力データのバリデーションや処理を行う
- 複数のモデル間でのデータの受け渡しを行う
- 複雑なフォームのロジックや操作をカプセル化する
- フォームの表示や操作に関連するビジネスロジックを実装する
フォームオブジェクトは、通常、ActiveModelを継承し、必要な属性やバリデーションルールを定義します。これにより、フォームの入力データを扱うためのモデルのような振る舞いを持たせることができます。
例えば、以下のようなケースでフォームオブジェクトが有用です:
- 複数のモデルにまたがるフォームを扱う場合(例: ユーザー登録フォームでユーザーモデルとプロフィールモデルのデータを扱う)
- フォームの入力データをバリデーションしたり、特定のルールに従って処理したりする場合
- ビジネスロジックが複雑なフォームを扱う場合(例: 商品購入フォームで在庫の確認や決済処理を行う)
フォームオブジェクトは、コントローラー内でインスタンス化され、ビューに渡されます。ビューでは、フォームオブジェクトの属性やエラーメッセージを使用してフォームを表示し、ユーザーからの入力を受け取ります。コントローラーは、フォームオブジェクトから入力データを取得し、適切な処理を行います(データ保存、他のモデルへのデータの伝達など)。
フォームオブジェクトを使用することで、フォームのロジックやバリデーションルールがコントローラーやモデルから分離され、コードの再利用性や保守性が向上します。また、フォームごとに独立したテストを作成することも容易になり
Rails欠点
RailsはDBのテーブルをそのまま読み書きするような単純なアプリケーションは簡単にできるが、より複雑なアプリケーションではそのぶん慎重な設計が必用になるため、Trailblazerのような複雑なWebアプリケーション構築を支援するライブラリが注目を集めている。
Railsの設計哲学
- DRY(Don't Repeat Yourself): 繰り返しを避けよ
DRYはDRY原則とも呼ばれる。Railsを使ったWebアプリケーションでは同じことを繰り返し記述するのは避けなければならない。 同じことをソースコードや設定ファイルの中で繰り返し記述するのはムダ。 仕様変更やバグフィックスのときに一部を変更し忘れる可能性が高くなる。 DRYを意識することで効率よく、品質のよいアプリケーションが作成できる。
- 設定より規約(Conventition over Configurations)
「規約」とは、言い換えれば「デフォルトの設定」です。あらかじめ用意された規約にしたがってアプリケーションを開発することで、記述量を大幅に減らせる。 たとえば、モデルには命名規約がありテーブル名をmembersのように複数形にすると、モデルのクラス名は単数形のMember、クラスを記述するファイル名はmember.rbとなります。決まりきった手順に従うことで余計な設定を記述する必要がなくなり、プログラマはコードへ集中できるようになります。
Railsで採用されているルール(規約)にしたがっていれば、Active Recordモデルの作成時に書かなければならない設定用コードは最小限で済みますし、設定用コードが完全に不要になることすらあります。これは「設定がほとんどの場合で共通ならば、その設定をアプリケーションのデフォルトにすべきである」という考えに基づいてる。
Rails でのアーキテクチャー
MVCへの対応
RailsではMVCでの役割をフォルダーごとに分けることで開発もスムーズに行えるような仕組みになっている。
Rails model
モデルとDBは1対1の相互関係で成り立っている。 ※開発現場でもモデルが一番最初に作られる。 ※モデルはただのクラスだがDBと連携するクラスをRailsではモデルと呼ぶ。
Rails ディレクトリ詳細
Rails 便利コマンド
Railsでは rails generate controller
などのコマンドでcontrollerやmodelをコマンドラインから生成できる。
※設定で生成するファイルを絞ることができる。
bin/railsとbundle exec railsの違い
bin/rails読むと config/bootを読み込んでいる事が分かると思います。 config/boot.rbを読むとbundler/setupを読んでいます。 bundler/setupが実行されるとbundle execと同じ事が行われるので 結論としては違いはありません。
Rails タイムゾーン
デフォルトではUTC
そのため created_at
や update_at
は日本時刻の9時間前になる。
Railsで新規タグ
Railsでクラスを作るには、直接ファイルを作成するのではなく専用のコマンドをつかうことが多い。
Rails 3つのモード(environment)
Railsには3種類ある
開発 : develop : コードを書きながらブラウザで確認するための環境 テスト : test : 自動テストのための環境 本番 : production : ウェブサイトを一般に公開する時の環境
Dockerを使わない場合のRails
Dockerを使わないRailsデプロイでは、以下の環境変数が自動で設定される。 Docker経由の場合は、自分で本番用の環境変数を設定する必要がある。
-
LANG
: en_US.UTF-8 -
RACK_ENV
: production Rackへ現在の環境を示す変数 Rackとは … http送受信処理を担当するモジュールのこと。 -
RAILS_ENV
: production Railsへ現在の環境を示す変数 -
RAILS_LOG_TO_STDOUT
: enabled logを標準で出力するか否かのフラグ。enabled = 出力する。 -
RAILS_SERVE_STATIC_FILES
: enabled publicディレクトリからの静的ファイルを提供してもらう(apiモードではあんま意味ないかも)
Railsで使われているMVCのデザインパターン
APIモードではViewは存在しない。
-
モデル モデルはデータとビジネスロジックを表す。ビジネスロジックとはたとえば給与計算ロジックのようなアプリケーションドメイン特有の処理のこと(localhost/api/users)→userの一覧を出すみたいな Railsではモデル層はActiveModelという概念に抽象化され、デフォルトではActiveRecordというO/Rマッピングの機能を提供するライブラリが使われる。 ActiveRecordでは、リレーショナルデータベースのテーブルに対応するモデルクラスにアプリケーションのデータとロジックを実装していきます。データの永続化に関する処理の多くはActiveRecordが担当してくれるので、単純なモデルであれば、プログラマが書かなければならないコードの量は、ごくわずかです。一般的にプログラマがモデルに追加することの多いコードとしては、クラスの持つ値の検証や、他モデルとの連携が挙げられます。
-
コントローラ ユーザのリクエストを受けて、モデルに適切な動作を要求する。 またどのビューをどの組み合わせで利用するかを決定する。 Webアプリケーションにおける コントローラーには、このほかWebに関する一般的な仕事を受け持つという側面があります。たとえばセッション管理や、URLの解釈、HTTPリクエスト・レスポンスの処理、クッキーの管理などを担当します Railsでは、コントローラーはAbstractControllerとして抽象化された上で、Webアプリケーション用の機能がActionControllerとして実現されています。プログラマは、これを継承したApplicationController(アプリケーションごとに1つ用意されます)に共通機能を追加したり、さらにこのApplicationControllerを継承した各種のコントローラークラスを追加していくことで開発を進めます。なお、個々のリクエストに直接的に対応する機能を実装した部分はアクションと呼ばれ、コントローラークラスのpublicなインスタンスメソッドとして実装されます。
Railsの構成と機能
Railsは復数のコンポーネントで構成されている。 Railsの実体はコンポーネント(Rubyで書かれたライブラリ)の集合体 基本とある3つのコンポーネントの名前を覚える
- Active Record : モデル
- Active View : ビュー
- Active Controller : コントローラー
Rails APIモードとは
Rails APIモードとは、API作成 に特化したモード APIモードではMVCのV(ビュー)が存在しないため、rails newを実行した際にビューに関するファイルやGemが生成されません。 API作成に特化したモードのことで、Rails5で実装された機能らしいです。 簡単に今までのRailsとの違いを説明すると、MVCでいう、Viewの部分が存在しません。 変わりにそのURLにアクセスするとerbを返さず、jsonを返す仕様になっています。 また、標準で入っているGemもViewの分が必要なくなっているので、普通に立ち上げたRailsのプロジェクトよりも少なくなっています。 詳しくは各々で調べてみてください。
- APIモードの違い 参考URL
gemとは
gemはRubyGemsと呼ばれるRuby用のパッケージ管理システムによって管理されたライブラリ RubyGemsが提供するgemコマンドを通じてインストール等ができます。
インストールしたgemを削除する
Gemfileから記述を消し bundle install
する。
gem version up 作成
Railsアプリケーションの開発現場で、いつどのようにgemをバージョンアップしたらよいかは悩ましい問題です。こまめにバージョンアップしていくのが一番ですが、テストコードが書かれておらず確 認のコストが高いなどの理由で、リリース後にまったくバージョンを上げられないようなプロジェクトも少なくありません。しかし、Railsアプリケーションの開発でgemのバージョンをまったく上げずにすませることはほぼ不可能です。もし利用しているgemに脆弱性が発見されたらどうしたらよいでしょうか?バージョンが上げられないと、そのまま脆弱性のあるコードを使い続けるか、自分たちでパッチを当てる必要があります。ただ、gemのバージョンを固定している環境であれば、脆弱性対策は何もしない、となる可能性が高そうです。これはビジネスにおける大きなリスクになるでしょう。
上記にもあるように gemのバージョンを上げていくにはまずテストを書き、その上でバージョンアップを続けられる仕組みを作ることが重要。 自動でgemバージョンアップ用のプルリクエストを作成してくれるサービスを使ったりする(GitHub Dependabotなど)
bundler、Gemfile、Gemfile.lockの関係性について
Ruby on RailsでWebアプリケーション(以降ではRailsアプリと略します)を開発をするにあたり、gemの活用は開発効率をあげるために重要
bundler(yarn, npmと同一)
bundlerは依存関係にあるgemの依存関係やバージョンを管理してくれるgem
bundlerを利用することで依存関係にあるgemの一括インストール。gemのバージョン管理ができるようになる
$ bundle install
を使って、Gemfileに記載されたgemをインストールする。
※--without
なしに bundle install
した場合は、すべてのgemがインストールされる。
bundle configとは 参考URL Bundlerの設定システムと対話をできるもの。
Bundlerは設定を下記の優先順位にしたがって取得する。
- ローカルアプリケーション(app/.bundle/configp)
- 環境変数
- ユーザのホームディレクトリ(~/.bundle/config)
bundle list
プラグインが入っているか確認ができる。
bundle install時に --path vendor/bundleをつける必要性
bundle install時に--path vendor/bundleを付ける必要性は本当にあるのか、もう一度よく考えてみよう
bundle install
コマンドを実行するときRuby界には大きく分けて2つの流派がある。
それは「--path vendor/bundleを付ける派」と「付けない派」
Gemfile(package.jsonみたいな)
GemfileとはRailesアプリで利用されるgemの一覧を管理するファイル bundlerによってインストールされるgemはどこで管理されているのか。
Rails 開発モードと本番モード
Railsには開発モードと本番モードという2つのモードがあり、それぞれ役割ごとにデータベースを切り替えて使う機能が備わっている。
本番環境への切り替え方は以下の用にする
- 環境変数の設定
# Linuxの場合
export RAILS_ENV=production
# windowsの場合は
set RAILS_ENV=production
- モードが変わったかどうかは以下のコマンドで確認
rails console
でコンソールを開く。
Rails.env
とコマンドを叩く、これで現在の開発モードが出てくる。
3.precompileをする。 assetsの圧縮ファイルを作成する事が目的?SASSのbuild、JSファイルの圧縮などを行っておくのだと思われる。これを行う事により高速に動作する。 確認したところ圧縮しているわけではなさそう。キャッシュファイルの生成と書いてはいる。
- 本番モードに切り替えた場合データベースをシードから作っていないので 作成する。 rake db:create rake db:migrate
Rails フォルダー構成
store … アプリケーションのルートディレクトリ
app … MVCに関わるアプリケーションの中心的なコード(モデル・ビュー・コントローラ・ヘルパー)
controllers … コントローラークラス
helpers … ヘルパーモジュール(ビュー用のヘルパーメソッド)
mailers … メール用のコントローラー
models … モデルクラス
views … テンプレート類
layouts … テンプレートに適用するレイアウト
config … 設定ファイル類
environments … 開発、テスト、本番運用といった環境ごとの設定
initializers … アプリケーション起動時に実行したいファイル
locales … 国際化に関するリソース
db … データベースに関するファイル
doc … rdocなどのドキュメント
lib … アプリケーションが使うライブラリコード全般(taskは`lib/tasks/*`に配置する)
log … アプリケーションが出力 するログ
public … Webの静的なコンテンツ
script … ユーティリティースクリプト
test … Railsのデフォルトの自動テストに関するファイル
tmp … 一時ファイル
vendor … アプリケーション外部に由来するコード
plugin … Railsプラグイン
app
にはモデル、コントローラー、ヘルパー等の決まった物以外は置かない方がいい。
app
内のパス構成は、Railsで決められた通りであることが前提となっているため、将来のバージョンアップで予期せぬ衝突が発生する可能性。
それらではない自作のクラスやモジュールは"lib"内に置く方が良いでしょう。
initializers
initializers以下においたファイルはサーバ起動時にのみ読み込まれるため、追加や編集をした場合はサーバを再起動する必要がある。
Rails url
resources :users 6つのアクションが自動生成されますね。 これはREST設計になっています。
GET /users users#index POST /users users#create GET /users/:id users#show PATCH /users/:id users#update PUT /users/:id users#update DELETE /users/:id users#destroy
リソースベースのルーティング(Rails default)
リソースベースのルーティング(以下リソースルーティング)を使うことで以下が勝手に定義される。
ルーテ ィング リソースベースで構成されたコントローラーに対応する共通のルーティングを手軽に宣言できます。resourcesを宣言するだけで、コントローラーのindex、show、new、edit、create、update、destroyアクションを個別に宣言しなくても1行で宣言が完了します。
ヘルパーメソッド リソースフルなルーティングを作成すると、アプリケーションのコントローラで多くのヘルパーが利用できるようになります。resources :photosというルーティングを例に取ってみましょう。
photos_pathは/photosを返します new_photo_pathは/photos/newを返します edit_photo_path(:id)は/photos/:id/editを返します(edit_photo_path(10)であれば/photos/10/editを返します) photo_path(:id)は/photos/:idを返します(photo_path(10)であれば/photos/10を返します)
Rails ルーティングを確認する方法
ファイルで確認する方法は config/routes.rb
でみる
Railsの流れとしては URLにアクセス(+アクションメソッド)すれば、どのコントローラーアクションが実行されるかを示したもの。
CLI上
$ rails routes
config/routes.rb
の中身がCLIで見られる。
ブラウザで確認
Puma
Pumaとは、複数のリクエストを並行しうて処理できる高速化を目的としたWebサーバ Rails5以降はデフォルトでpumaが導入されており、自ら導入する必要はありません。
docker rails
rails debug
puts ps
puts current_external_id
puts new_external_id
# get fire again22
# <PaymentSetting:0x0000ffff50fbe668>
# price_1GwjUCI8OazorEAhkvB0EXBI
# price_1GwjUCI8OazorEAhtLlr784x
# get fire again2
# inspectを使えば、メモリ値の中身を見れる。
puts ps.inspect
puts current_external_id
puts new_external_id
# get fire again22
#<PaymentSetting id: 1, service_type: "stripe", payment_type: "card", is_subscription: true, period: 1, status: "active", created_at: "2022-02-03 07:29:41", updated_at: "2022-02-03 07:29:41", visible: true>
# price_1GwjUCI8OazorEAhkvB0EXBI
# price_1GwjUCI8OazorEAhtLlr784x
# get fire again2
Rails logger
参考URL
puts
or logger
がある。
puts
はどの環境(ENV)でも標準出力に吐かれる。
logger
はdevelopmentのみが標準出力される。
-b 0.0.0.0
実は、rails のプロジェクトのポカです。 危ないので、デフォルトを、ローカルからしか接続できない様に変更したのに マニュアルを変更するのを忘れているのです。 と、表示されているので、実は、分かりますけどもね。 と表示されていないと、グローバルアドレスからは、接続できません。 起動時に rails server -b 0.0.0.0 とやらないといけなくなったようです。 今まで、何も指定しなくても接続できたものを、 -b 0.0.0.0 を指定しないと、localhost からしか接続できない仕様変更をして、説明をするのを怠っているのです。
rails serverのコマンドオプションとなります。 railsのプロセスをどのipアドレスにバインドするかを指定する。 ここではlocalhostのipアドレス「127.0.0.1」を「0.0.0.0」にバインドしています。 なぜこんな事をするのか 仮想環境で起動したRailsは、localhostのipアドレス「127.0.0.1」でアクセスできない そこで仮想外部からアクセスできるように、ip「0.0.0.0」に紐付けをする必要がある。 これにより自分のPC上ブラウザからRailsへアクセスできるようになる。
Tips
# ルーティング確認(api起動をしている際)
$ rails routes
# rails内の環境変数を確認したい場合(コンソールを出す : console の略)
$ rails c
DBの読み書きに使用するタイムゾーン
Railsにはアプリのタイムゾーンとは別に、DBの読み書きに使用するタイムゾーンがある。 ※これはどのバックエンドでも言えることだろう
定数管理
自分で作るパターンもあればgemを使うパターンもある。 gemを使わないパターンがあるとしたら以下がオーソドックス
application_controller.rb
で定数を管理する方法config/initializers/constants.rb
のようなファイルを用意して、そこで定数を管理する方法
application_controller.rb
はアプリケーション共通の処理を管理する場所なので、ここで定数を管理するのはあまり相応しくない。
config/initializers/constants.rb
のようにファイルを用意して、そこで定数を管理する方法のがいい。
- gemを使うパターン 参考URL
config
が一番定番。
Settingslogic→あまり使われていない。
Rails6でのZeitwerk(ツァイトベルク)
- そもそもなぜRailsではrequireなしにファイルを読み込むのか
他の言語などにおいて、他のファイルを読み込むとなればimportするなどして明示的に読み込む必要があるが、Railsではそれをよしなにやってくれる。 Zeitwerkという仕組みがRailsには組み込まれているから
Rails6から自動読み込みモードZeitwerkが追加された。
プロジェクト構造
Railsアプリケーションではファイル名はそれらが定義する定数と一致する必要があり、ディレクトリは名前空間として機能する Zeitwerkは例として、app/controllers/users_controller.rb定数を定義するUsersController(クラス)のことを期待しています。
Rails6からのlibディレクトリ以下のファイル読み込み
Rails6のデフォルトではlibディレクトリ以下のファイルは読み込まれない
読み込む方法は2つある
- requireで呼び出し
読み込みたい場所でrequireで宣言する方法 Railsがデフォルトで読み込むパスにはapp/libまで設定されている。それ以下のファイルパスを渡す。
api/lib/validator/email_validator.rbの場合 => "validator/email_validator.rb"のパスを渡す
- application.rbで呼び出し
Rails6のオートロードシステム(Zeitwerk)に読み込むパスを追加する方法
rails での test
Railsのデフォルトではfixture(フィクスチャー)を使ってテストデータを生成する。
- fixtureとは fixtureとは、Railsが用意しているテストデータを生成するための方法です。 この方法を使う場合、テストデータはymlファイルで生成する。
Pundit
Rubyのgemライブラリ 認可の仕組みを提供してくれる ユーザによってページ表示の許可・拒否をしたり表示情報の範囲を変えたりできるgem
module
moduleには部品の集まりや区分という意味になる。 Rubyの**moduleはclassと同じようにmodule内に関数の定義ができること、**プログラム上での役割や振る舞いをまとめることができる。
classとの違いは?
- moduleからインスタンスが生成できないこと
- moduleは継承ができない
- moduleを使うメリット
module Car
class SuperCar
def self.introduce
puts "This is SuperCar"
end
end
end
class SuperCar
def self.introduce
puts "これはスーパーカーです"
end
end
Car::SuperCar.introduce # module呼び出し
SuperCar.introduce # class呼び出し
module名とclass名は同名であるが、moduleには名前空間としての役割を持っているためコンパイル上では別のものとなっている。
ruby独自の機能にMix-in
Mix-inすることでmodule内のメソッドをインスタンスメソッドとして利用することがができる。 ※includeでの拡張は静的となる。
module Lion
def cryLion
puts "ガオー!"
end
end
module Cat
def cryCat
puts "ニャー"
end
end
class Animal
include Lion, Cat # moduleの機能をincludeしている
end
obj = Animal.new
obj.cryLion # Lionクラスのmethodを利用
obj.cryCat # Catクラスのmethodを利用
ここから本
Rails処理順序(基本)
- ブラウザからのリクエストを受け取ると、Railsはパスを調べroutes.rbにしたがってどのコントローラのどのアクションを選べば良いかを決める(Controllerの中にアクションは複数ある)
- Railsは選ばれたアクション(メソッド)を実行する(アクションにはモデルとの間で情報のやり取りをするプログラム)を書く
- モデルはDBのテーブルと対応している、アクションはモデルから取得した情報のうち、表示に必要なものをインスタンス変 数に保存し返す
route
RailsアプリケーションではRESTの原則にしたがってデータをリソースとして扱う
RailsにはRESTに基づいた作法でウェブアプリケーションを作成する機能がある。
Railsにおけるリソースとは
コントローラーが扱う対象に名前をつけたもの。
リソース名を設定するには config/routes.rb
にresourcesメソッドを追加するだけ
resources: リソース名の複数形で記述する
上記で7つのアクションのルーティングが設定できる。
これをRESTフルなルーティング、またはリソースベースのルーティングと呼ぶ
controllers コントローラー
コントローラーは複数系で定義する。 ※リソースを扱うコントローラーはMembersControllerの様に、リソース名+Controllerという名前が一般的
DHH(railsを作った人)が述べているコントローラーの作りかた 参考URL
config/routes.rb
resources :orders, only: [:index]
必ずorderのモデルが必要ではない。 リソース名に対応したコントローラーに対して、7つのアクションのルーティングを自動的に設定するだ け
strong parameter
参考URL ストロングパラメーターはWeb上から受けつけたパラメーターが本当に安全なデータかどうかを検証した上で、取得するための仕組み。Rails4から実装されている。 フォームから送信されてきたparameterでどのparameterを許可するかホワイトリストを実装する。
命名規則慣例
メソッド名に命名規則はないようですが モデル名_params
とするのが一般的。
また実行結果として、許可されたカラムの値だけを抽出しハッシュ形式で呼び出し元に値を返す。
permit permitメソッドを使用する事で許可された値のみを取得できる。 そのため、permitメソッドの引数には登録を許可するすべてのカラム名を指定しておく必要があります。もし、許可されいないカラムがparams内に存在した場合、そのデータは取得されず無視されます。
リソースを扱うコントローラー
コントローラーでは7つのアクションを用意する この7つは原則としてデータベースの基本操作であるCRUDを実装したもの
api/app/controllers
module User::Apis::V1::User
class PaymentHistoriesController < ApiController
def index
params = index_params
offset = params[:offset] || 0
authorize(nil, policy_class: PaymentHistoryPolicy)
common_query = policy_scope(nil, policy_scope_class: PaymentHistoryPolicy::Scope).ransack(params[:q]).result
payment_histories = common_query.
order(captured_at: :desc).
limit(limit).
offset(offset)
total_count = common_query.count
render json: payment_histories, root: "payment_histories", meta: total_count, meta_key: "total_count",
include: SERIALIZER_INCLUDE, adapter: :json
end
end
end
7つのアクション
7つのアクションを呼び出すには以下画像をみる。 HTTPメソッドの組み合わせを使う。
- index リソースの一覧を表示する
- new リソースを追加する(テーブルに新しいレコードを作成する)ためのフォームを表示する
- create リソースを作成する(テーブルに新しいレコードを作成する)
- show リソースの属性を表示する(レコードの内容を表示する)
- edit リソースを更新する(既存のレコードのカラムを更新する)ためのフォームを表示する
- update リソースを更新する(既存のレコードのカラムを更新する)
- destroy リソースを削除する(テーブルからレコードを削除する)
7つのアクション以外の追加
任意のアクションを追加するにはresourcesメソッドにブロックを渡しブロックの中でもHTTPメソっドを表すメソッド アクション名を記述
パスを返すメソッドが使える(resource)
リソースを指定すると、コントローラーのアクションを表すパスを取得できる
特定のアクションを使わない場合
resources :contents, only: [:index, :show, :create, :update]
onlyオプションに渡す 上記だと:index, :show, :create, :updateアクションのルーティングだけ設定する。
Rails起動ガイド
- bin/railsが読み込まれる
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../config/application', __dir__)
require_relative "../config/boot"
require "rails/commands" # ここでAPP_PATH定数が使われる
- /config/boot.rbが読み込まれる
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
require 'bundler/setup' # Gemfileが存在する場合は、bundler/setupをrequireする
require 'bootsnap/setup' # Speed up boot time by caching expensive operations.
- rails/commmands.rbを実行する
2が終わると、次にコマンドの別名を拡張するrails/commandsをrequireする 拡張されたのは以下
require "rails/command"
aliases = {
"g" => "generate",
"d" => "destroy",
"c" => "console",
"s" => "server",
"db" => "dbconsole",
"r" => "runner",
"t" => "test"
}
command = ARGV.shift
command = aliases[command] || command
Rails::Command.invoke command, ARGV
/initializers以下のrbファイル
アプリケーション起動時にロードされるもので、初期化処理で使われる 自分でrbファイルを追加して使うことも可能
国際化 internationalization 略してi18nと呼ばれる
単数リソース
membersリソースの重要な特徴は、それが集合的な概念であるということ。 0人以上のメンバーからなる集まりを表現している。 しかしウェブアプリケーションを構成する要素の中には、多くとも1個しか存在しないものがある。 この種のリソースを単数リソースと呼ぶ
単数リソ ースの例として セッション・自分のアカウント情報・自分のパスワード
単数リソースのルーティング
単数リソースのルーティングを設定するには、config/routes.rbの中でresourcesメソッドではなく、単数系のresourceメソッドを使う。
resource :account
上記のように書いてもこのリソースを扱うコントローラーの名前は AccountsController(複数形のs)に注意
単数リソースのため集合を扱うindexアクションはない