Rails初心者です。頑張ってます。Ruby on Railsのscaffoldで生成されたコードを全て説明できるようになるようにと言われたので、説明してみます。
bundle exec rails g scaffold Entry title:string body:text
ファイル構成
scaffoldを実行すると以下のファイルが生成されます。その他に生成されるテストコードとかマイグレーションファイルは無視しています。
PROJECT_ROOT
|- controllers
| |- entries_controller.rb
|- helpers
| |- entries_helper.rb
|- models
| |- entry.rb
|- views
| |- _form.html.erb
| |- edit.html.erb
| |- index.html.erb
| |- index.json.jbuilder
| |- new.html.erb
| |- show.html.erb
| |- show.json.jbuilder
コントローラ
まずはコントローラからです。コントローラは空のクラスであるApplicationControllerを継承してます。コントローラの共通処理を定義するためにこのクラスは存在しています。ApplicationControllerは、さらにその親クラスであるActionController::Baseを継承しています。このコードはprotect_from_forgeryメソッドによりCSRF対策をデフォルトで有効にしています。
1 2 3 |
|
Entryコントローラにはindex, show, new, edit, create, update, destroyアクションが定義されます。規約によりアクション、URL、HTTPメソッドの対応関係が決まっています。これはRestからの設計思想で以下のようになっています。
アクション | URLパス | HTTP METHOD |
---|---|---|
index | /entries/ | GET |
show | /entries/1 | GET |
new | /entries/new | GET |
edit | /entries/1/edit | GET |
create | /entries | POST |
update | /entries/1 | PATCH |
destroy | /entries/1 | DELETE |
そしてこの仕組みを作っているのがルーティングになります。ブロック内でresourcesメソッドにシンボルを渡すことでRailsがRESTアクセスを許可します。exceptや、onlyなどのオプションでアクセスを制御することもできます。
1 2 3 |
|
通常はHTTPメソッド 'URLパス', 'コントローラ#アクション'
の形式で定義していきますが、scaffoldが追記したルーティングはリソースベースのルーティングになります。これは以下のルーティング定義と同じになります。
1 2 3 4 5 6 7 8 9 |
|
ビューで使用されるルーティング名もここで定義されます。
URLパス | ルーティング名 |
---|---|
/entries | :entries |
/entries/1 | :entry |
/entries/new | :new_entry |
/entries/1/edit | :edit_entry |
あとコントローラのソースをざっと見て感じたことは、scaffoldで生成したコントローラのprivateメソッドは1つインデントを下げているのでコーディング規約的にはこれを覚えた方がいいかなと思います。
1 2 3 4 |
|
beforeアクション
各アクションが実行される前に必ず処理されます。アクションで処理を共通化したい場合はここに書きます。これらはshow, edit, update, destroyアクションの前にset_entryというメソッドを実行するよう定義しています。
1
|
|
indexアクション
Entryモデルから全件取得し、@entriesというインスタンス変数に代入しているだけです。
1 2 3 |
|
showアクション
メソッドを定義しているだけで処理内容がありませんが、before_actionが実行されるため処理内容がアクション内になくてもビューにEntryオブジェクトの値が渡ります。
newアクション
Entryモデルのインスタンスを生成して@entryインスタンス変数に渡しています。
editアクション
こちらもメソッドを定義しているだけで実装がありませんが、showアクションと同様、before_actionで処理を任せています。
createアクション
POSTされた値を受け取ってentry_paramsプライベートメソッドに処理をさせます。これは何をやっているかというとStrong Parameterという機能です。たとえばこのentitiesというテーブルにはtitleとbodyといったカラム以外に、created_atなどユーザには表示しないシステムの都合上のカラムなどもあります。不正なアクセスで改ざんされる危険性がありますので、titleとbodyのみを許可するようこのメソッドで処理しています。
1 2 3 |
|
こうして許可されたパラメータだけが返ってくるので、そのパラメータを使ってEntryモデルを初期化します。respond_toメソッドのブロックでHTTPレスポンスの処理を行います。formatオブジェクトのhtmlメソッドにはHTMLを返すための処理を定義します、jsonメソッドはJSONを返すための処理を定義します。
問題無くエントリーが保存された場合は、HTMLを取得するためのアクセスならばリダイレクトします。JSONを取得するためのアクセスならばJSONを返します。保存に失敗した場合は、HTMLを取得するためのアクセスならばnewアクションに戻して再入力を施します。JSONを取得するためのアクセスならば、クライアントにJSONでエラー状態のJSONを返します。 saveメソッドは、if文の条件に使われているので成功したらtrue, 失敗したらfalseを返しますが、save!と破壊的メソッドにすれば失敗した場合は例外がraiseされます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
updateアクション
モデルのupdateメソッドを呼ぶところとメッセージ以外、ほぼcreateアクションと同じです。
destroyアクション
モデルのdestroyメソッドを呼び出し、リダイレクトします。ここでredirect_toメソッドの引数でentries_urlというメソッドが呼び出されていますが、このようにルーティングで定義されたルーティング名である:entriesに_urlというサフィックスを付けたメソッドを呼び出すことで/entriesへのURLを生成してくれます。
1 2 3 4 5 6 7 |
|
モデル
モデルはバリデーションも定義してませんので2行だけです。これだけで多くの機能を使うことができます。
1 2 |
|
ビュー
ビューはRailsのデフォルトではERBが使われます。拡張子が.jbuilderはJSONのビューになりますが、ここでは取り扱わず、erbのみ説明します。
index.html.erb
重要なところは以下の箇所です。コントローラから渡されたエントリー一覧をeachメソッドで繰り返しています。モデルのプロパティを呼び出しながら値を表示します。link_toメソッドはビューのヘルパーメソッドで、第1引数にリンクの文字列、第2引数にURLパスを指定します。showやdestroyの場合はentryオブジェクトを渡すだけでURLパスにしてくれます。editやnewに関してはルーティング名に_pathをつけたヘルパーメソッドがURLパスを出力してくれます。
1 2 3 4 5 6 7 8 9 10 11 |
|
削除のlink_toはちょっと複雑です、第2引数にentryオブジェクトを渡すのはshowアクションへのリンクと同じですが、第3引数にハッシュを渡しています。method: :delete
と定義することでdata-method="delete"
という属性を出力します。この指定をすることでRailsはリンクをGETではなくDELETEでアクセスします。data: { conform: 'Are you sure?' }
と定義することでdata-confirm="Are you sure?"
という属性を出力します。これにより削除のリンクをクリックするとconfirmダイアログが出力されます。
show.html.erb
このビューも重要なのは以下の箇所です。ルーティング名である:entries, :edit_entryに_pathをつけたヘルパーメソッドによりURLパスを指定しています。
1 2 |
|
new.html.erb
ビューでのrenderヘルパーメソッドは引数に文字列を指定すると、_指定した文字列.html.erb
のファイルを読み込みます。フォームの内容は_form.html.erb
に記述されています。
1 2 3 |
|
edit.html.erb
new.html.erb
とほぼ一緒です。
1 2 3 4 |
|
_form.html.erb
フォームヘルパーにエントリーオブジェクトを渡してブロックでフォーム内容を定義していきます。最初にあるのはエラー処理になります。フォームを作成するには、フォームオブジェクトのヘルパーメソッドにモデルの属性をシンボルを渡していけばHTMLでフォームを出力します。フォームヘルパーはひとつずつ覚えていくしかないと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
まとめ
1行1行説明することで理解ができました。基本をやりなさいと言われた時、「それぐらい分かる」と思いがちで実際に素直にやらない場合もあるかもしれませんが、経験的にこの辺の基礎的なことは、もうバカみたいに実直にやった方がいいと思います。仕組みが分かったので、後はscaffoldを何度か写経したら完璧です。