今さらRails3メモ - その2 : C, V を中心に -
とりあえず scaffold する
最初は様子がよく分からないので
r g scaffold
しちゃう。
scaffold は一躍 Rails を有名にしたものなんだけど、これは何より様子を掴むのに向いている。例えば
r g scaffold example name:text
とすると
- カラムを1つ ( name ) 持つテーブル1つ ( example ) に対応するモロモロ
を作ることができる。
実際に実行するとファイルでこれだけのものができる1。(routes はファイルができたんじゃなくて routes.rb を書き換えたよの意味。)
invoke active_record
create db/migrate/#{SERIAL}_create_examples.rb
create app/models/example.rb
invoke rspec
create spec/models/example_spec.rb
route resources :examples
invoke scaffold_controller
create app/controllers/examples_controller.rb
invoke erb
create app/views/examples
create app/views/examples/index.html.erb
create app/views/examples/edit.html.erb
create app/views/examples/show.html.erb
create app/views/examples/new.html.erb
create app/views/examples/_form.html.erb
invoke rspec
create spec/controllers/examples_controller_spec.rb
create spec/views/examples/edit.html.erb_spec.rb
create spec/views/examples/index.html.erb_spec.rb
create spec/views/examples/new.html.erb_spec.rb
create spec/views/examples/show.html.erb_spec.rb
invoke helper
create spec/helpers/examples_helper_spec.rb
create spec/routing/examples_routing_spec.rb
invoke rspec
create spec/requests/examples_spec.rb
invoke helper
create app/helpers/examples_helper.rb
invoke rspec
invoke stylesheets
create public/stylesheets/scaffold.css
上から
- db の migration
- model
- model の spec
- routing ( 一通り CRUD できるように resources になっている )
- controller
- controller の各メソッドに対応する view
- controller の spec
- view の spec
- helper の spec
- routing の spec
- requst の spec
- helper
- stylesheet
となっている。このまま
rake db:migrate
r s
すると
http://localhost:3000/examples
にアクセスして実際に使える。
Controller
layout
layout "NAME"
layout ファイルを指定できる。何も指定しなければ
app/views/layouts/application.html.erb
が選択される。
※ jpmobile が有効で mobile な user agent だったら
app/views/layouts/application_mobile.html.erb
などになる。
さっき scaffold したコードを読む
Controller には index, show, new, edit, create, update, destroy のメソッドがある。それぞれ
index | 一覧表示 |
show | 個別表示 |
new | 新規追加form表示 |
edit | 既存レコードの編集form表示 |
create | 新規追加送信先 |
update | 既存レコードの編集結果送信先 |
destroy | 既存レコードの削除 |
となっている。やってることは
- Model インスタンスを作る(.all(), .find(), .new())
- 必要な処理を加えて
- 結果を返す(render(), redirect_to(), head( :ok ))
以上。
Skinny Controller !
respond_to と format.xml の部分はとりあえず気にしなくていいと思う。たぶん。
View
Controller を読むと分かるけど View ってオブジェクトを明示的に作ることはない。
※ erb 以外のテンプレートは使ったことがないので知らない。
基本的なテンプレートの配置
app/controllers/#{controller}_controller.rb
app/views/#{controller}/#{action}.html.erb
controller のメソッド名に対応した view が勝手に呼ばれる。
見ると分かるけど先ほどの scaffold で指定した field ( name ) がちゃんと index, show, _form にハマっている。
ここでもう一度 Controller と見比べると
- params[:example]
- @example
- @examples
- example.name
などの意味するところが見えてくると思う。
partial の扱い
(主に V や Helper で)
render 'NAME'[, { 渡すオブジェクトのマップ }]
と指定するとこれを呼んだ View と同じディレクトリの
File.dirname( __FILE__ ) + "/_#{NAME}.html.FORMAT"
を探しにいく。例えば上で scaffold した例だと
app/views/examples/edit.html.erb
app/views/examples/new.html.erb
に
<%= render 'form' %>
と書かれている。実際に呼び出されるのは同じディレクトリにある
app/views/examples/_form.html.erb
になる。
※ オブジェクトのマップについては後述。partial の呼び出しは Rails 3 で簡略化されたので 2 以前の知識のある人、2 以前を対象にした本を参考にしている人は注意。
partial を別なディレクトリに置く
partialの名前に / が入ると app/views/ 以下のどこかのパスのpartialを探しにいく。
View から見えるもの
View から Controller の持っているものは基本的にすべて見える。request, params, cookies, response, session, headers など。Controller で Model のインスタンスをインスタンス変数に持っているなら、V からもそれが見える。
だから index.html.erb で @examples.each と書いてすべてのレコードの一覧を表示することができるし、_form.html.erb でいきなり @example を参照して form を組み立てることができる。
というか `controller' で Controller そのものにもアクセスできる。つまり全部見える。テンプレートで
<%= debug( controller ) %>
として見れば分かる。
partial に渡るオブジェクトと partial の動き
partial の書き方はいろいろあるので、本当に細かいところは
Ruby on Rails Guides: Layouts and Rendering in Rails
に譲るとして、とりあえず
- インスタンス変数は何もせずにアクセスできる
- ローカル変数へのマップは :locals で明示する
- :collection を使うとループの処理書かなくてもいい具合に動く
- :action で他の action 呼び出して結果を返せる
くらいは分かっておくとよい。
HTML は helper で書くより partial の方が楽かも?
ActionView::Helpers::TagHelper
に
- content_tag
- tag
という便利メソッドがあって HTML の組み立てもラクチンにできそうだけど、デフォルトでエスケープされるし
<%= %>
は Rails 3 以降デフォルトでエスケープされるので注意が必要。とは言え動的に何か組み立てようと思ったら Helper に書いた方が見通しはよくなるので、
<%= raw helper_method %>
みたいな形に落ち着くのかな。でもこの代わりにも partial が使えるような。
<%= yield :NAME %>
<%= render 'name' %>
とやって partial の方で
<%
content_for :NAME do
...
end
%>
とか。
jpmobile が有効な場合、partial に対してもテンプレートの切り替えが有効なので、Controller や Helper で分岐を書く必要がなくなって嬉しい気がする。
form
この辺を見る。
- ri ActionView::Base
- ri ActionView::Helpers
- ri ActionView::Helpers::FormBuilder
- ri ActionView::Helpers::FormHelper
- ri ActionView::Helpers::FormOptionsHelper
- ri ActionView::Helpers::FormTagHelper
form_for が form_builder を作るメソッド。
form_for( @model ) do |f|
f は FormBuilder が渡ってきている
end
Model.columns を使うと column 情報は取れるので、手動で作る分にも雑な form ならすぐに作れそう。
二つの Model にまたがる場合はどうするんだろう? 宿題。
Test::Unit ではなく RSpec を使う設定になっているものとする。 ↩