前提
Railsの処理の流れでルータからコントローラへの流れは以下のように説明することが多い。
URLが/blogsでHTTPメソッドがGETの時、rake routesよりblogsコントローラのindexアクションに誘導される
理にはかなってる。
ただ具体的にどんな処理が行われているかは想像しにくいので、少し踏み込んで説明する。
コントローラのアクションに誘導する具体的な処理とは
結論から先に言うと BlogsController
というクラスの インスタンス
を生成し、BlogsControllerのインスタンスメソッドである index
を実行している。
つまり以下のようになる。
BlogsController.new.index
コントローラもインスタンスを生成する?
ちょっとイメージしづらいので、モデルを例に説明していこう。
class Blog < ActiveRecord::Base
end
こちらは Blogクラス
からインスタンスが生成され、saveメソッドやcreateメソッドでblogsテーブルにレコードとなって保存される。
irb(main):008:0> blog = Blog.new(title: 'aaa', content: 'bbb')
=> #<Blog id: nil, title: "aaa", content: "bbb", created_at: nil, updated_at: nil>
irb(main):009:0> blog.save
(1.5ms) begin transaction
SQL (4.5ms) INSERT INTO "blogs" ("title", "content", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["title", "aaa"], ["content", "bbb"], ["created_at", "2017-06-27 16:38:13.612348"], ["updated_at", "2017-06-27 16:38:13.612348"]]
(1.1ms) commit transaction
=> true
イメージは確かにこちらのがしやすいのは事実。
一方でコントローラはどうか?
class BlogsController < ApplicationController
def index
@blogs = Blog.all
end
def show
# 省略
end
def new
@blogs = Blog.new
end
# 省略
end
コントローラも BlogsController
という クラス
で構成されている。
こちらも同様にインスタンスを生成することは普通に可能なのだ。
railsコンソールでコントローラをインスタンス化してみる
試しにrailsコンソールで実行してみると良い。
ここではblogsコントローラのindexアクションを実行させてみよう。
irb(main):001:0> blogs_controller = BlogsController.new
=> #<BlogsController:0x007fe748b92580 @_action_has_layout=true, @_routes=nil, @_request=nil, @_response=nil>
irb(main):001:0> blogs_controller.index
Blog Load (3.5ms) SELECT "blogs".* FROM "blogs"
=> #<ActiveRecord::Relation [#<Blog id: 1, title: "タイトルA", content: "内容A", created_at: "2016-12-14 11:10:31", updated_at: "2016-12-14 11:10:31">, #<Blog id: 2, title: "タイトルB", content: "内容B", created_at: "2017-06-11 04:19:43", updated_at: "2017-06-11 04:19:43">, #<Blog id: 3, title: "タイトルB", content: "内容B", created_at: "2017-06-11 04:19:43", updated_at: "2017-06-11 04:19:43">]
これを見ると @blogs = Blog.all
と同じ結果が返ってきてるのが確認できる。
なぜなら BlogsController
というクラスのインスタンスを生成し、BlogsControllerのインスタンスメソッドである index
を実行させることで、 index内に記述されている処理が実行される
からだ。
つまりコントローラの処理も、オブジェクト指向に則って実行されていることがわかる。
newアクションの実行も同様。
今度は変数に入れず、イッパツで実行させてみる。
irb(main):001:0> BlogsController.new.new
=> #<Blog id: nil, title: nil, content: nil, created_at: nil, updated_at: nil>
1つ目の new
はRubyが用意している 特異メソッド
。
2つ目の new
は BlogsController
クラス内に定義してある インスタンスメソッド
。
両者は全くの別物ということも気をつけなければならない。
ちなみに他のアクションはブラウザからの情報(パラメータ)が必要なため、railsコンソール上では実行できない。
まとめ
- URLが/blogsでHTTPメソッドがGETの時、rake routesよりコントローラとアクションが
blogs#index
に定まる。 - BlogsControllerクラスのインスタンスが生成される
- BlogsControllerクラスのインスタンスメソッドであるindexを実行する
- indexの中に記述されている
@blogs = Blog.all
が実行される