Scaffold をそらで写経できない Rails プログラマーは中2からやり直せ。と、心温まるお言葉が表明されていました。
Ruby の if 文すら怪しい自分は小学生以下決定なわけですが、少しでも学年を上げるべく scaffold の写経をしたいと思います。この前、"rails g scaffold post ..."で作った足場を元に中身を見ていきます。
一通り書いてみて思った感想としては、 RailsGuide の getting started の中身を模写しただけみたいなブログになっちゃいました…。
app/models/post.rb
ソースコード:class Post < ActiveRecord::Base"rails g scaffold modelname" で作成されるモデルの中身は、ActiveRecord::Base クラスを extend しているだけの空のクラスであることがわかります。
end
app/helpers/posts_helpers.rb
ソースコード:module PostsHelpermodelname_helpers.rb についてもほぼ同様に空の定義が与えられます(こちらは module ですが)。
end
config/routes.rb
このファイルは元々存在するファイルですが、generate scaffold で行が追加されます:resource :posts# post なんていう紛らわしいモデル名で作ってしまったのは失敗だったかなあ…。
routes.rb では URL → controller のマッピングを行っているようです。
http://guides.rubyonrails.org/routing.html の 2.2節 "CRUD, Verbs, and Actions" を見てみると、"resource :posts" ではデフォルトの7つの挙動が追加されるそうです。
- get /posts => index : post の一覧を表示
- get /posts/new => new : 新規作成のためのフォームを表示
- post /posts => create : 新規作成
- get /posts/:id => show : #{:id} 番目の post を表示
- get /posts/:id/edit => edit : #{:id} 番目の post を編集するフォームを表示
- put /posts/:id => update : #{:id} 番目の post を更新
- delete /posts/:id => destroy : #{:id} 番目の post を削除
ただ、routes.rb の詳しい内容は上記のガイドだけでもブログ一回分以上の内容がありそうなので別記事にします。
おまけ:rake routes と rails-sh
routes.rb をググってた時、@ITの記事を見つけ、その中で rake routes コマンドと rails-sh を紹介していました。rake routes コマンドは routes.rb で指定されたマッピングについての情報を表示するためのコマンドです。試しに実行してみたら、先ほど列挙した7つの動作が post について表示されました。resource :posts の効果が確認できた形です。
また、「rails コマンドとか rake コマンドは何かやたらと時間がかかるなあ。仮想マシンなのがいけないのかなあ」と思っていたんですが、@ITの記事を読んでて
以上のように、railsコマンドやrakeはRailsアプリケーションを実装する上で欠かせない便利なツール群です。という記述を見つけ、時間のかかる理由が納得できました。
しかし、コマンドの実行のたびにRailsアプリケーションをロードするので、毎回少し時間がかかってしまいます。
それを解消するために本記事の筆者の1人である@jugyoが作ったツールが「rails-sh」です。
rails-shは、あらかじめRailsアプリケーションをロードした状態で起動するコマンドラインシェルのようなものです。
rails-sh を使うかどうかは後々考えます…。
app/controllers/posts_controller.rb
おそらく scaffold で生成される Ruby プログラムはここが全てなんだろうと思います。…こういう書き方をすると、「TDDだから TestUnit の部分を重要視しないなんて、やっぱり初心者だな」と思われるんでしょうか。「メインの関心事(= システムの挙動)に関する部分で」っていう前置きがあれば正しい表現になるのかなあ…。
さて。
class PostsController < ApplicationControllerまず分かることは、ApplicationController のサブクラスであることです。
...
end
ApplicationController は ActionController (ActionPack gemsの一部?)を extends しているクラスです。ApplicationController クラスの中身はほぼ空なので、その親クラスである ActionController クラスの中身に意味があるはずです…が、ActionController はちょと巨大なのでブラックボックスにしておきます。
# ほぼ空 = protect_from_forgery のみ = CSRF対策のためのコードが定義されている
PostsContoller クラスでは "resource :posts" で定義される7つの挙動に対応するメソッドが定義されています。
一番シンプルな形のメソッドは
def indexというものです。
@posts = Post.all
respond_to do |format|
format.html
format.json { rendor json: @posts }
end
end
最初の @posts 変数への代入では Post クラス(モデルクラス)が使われています。この場合は .all なので、「全ての Post」となります。他のメソッドでの @post の代入では、
- find メソッドを使って、モデルクラスのデータを検索している
- new メソッドを使って、モデルクラスのデータを新規作成している
あと、Rubyベストプラクティスを読んでいるおかげか、respond_to が「特別なメソッドを使ってDSLっぽく仕上げる」仕組みなのが想像できます。どうやら actoinpack/lib/action_controller/metal/mime_responds.rb で定義されているようですが、追いきれませんでした…。
exampleを見る限りだと、respond_to に渡されているブロックの引数 format (Webクライアントからのリクエストによって決まるらしい)によってどんな仕事をするのかを記述するようです。
また、(この部分はまったくプログラムを追っていませんが挙動から予想するに)html フォーマットの場合のデフォルトの挙動は methodname.html.erb に処理が移るようです。
その他の scaffold の生成物
きょうのところは勘弁create db/migrate/20111030125941_create_posts.rb大まかに把握しておくと、db の部分、view の部分(erb および assets/coffee,scss)、テストの部分が手つかず。
invoke test_unit
create test/unit/post_test.rb
create test/fixtures/posts.yml
invoke erb
create app/views/posts
create app/views/posts/index.html.erb
create app/views/posts/edit.html.erb
create app/views/posts/show.html.erb
create app/views/posts/new.html.erb
create app/views/posts/_form.html.erb
invoke test_unit
create test/functional/posts_controller_test.rb
invoke helper
invoke test_unit
create test/unit/helpers/posts_helper_test.rb
invoke assets
invoke coffee
create app/assets/javascripts/posts.js.coffee
invoke scss
create app/assets/stylesheets/posts.css.scss
invoke scss
identical app/assets/stylesheets/scaffolds.css.scss
0 件のコメント:
コメントを投稿