LoginSignup
24
12

More than 5 years have passed since last update.

Railsのコントローラも通信ごとにインスタンス化されている

Last updated at Posted at 2017-06-27

前提

Railsの処理の流れでルータからコントローラへの流れは以下のように説明することが多い。

URLが/blogsでHTTPメソッドがGETの時、rake routesよりblogsコントローラのindexアクションに誘導される

理にはかなってる。
ただ具体的にどんな処理が行われているかは想像しにくいので、少し踏み込んで説明する。

コントローラのアクションに誘導する具体的な処理とは

結論から先に言うと BlogsController というクラスの インスタンス を生成し、BlogsControllerのインスタンスメソッドである index を実行している。
つまり以下のようになる。

BlogsController.new.index

コントローラもインスタンスを生成する?
ちょっとイメージしづらいので、モデルを例に説明していこう。

app/models/blog.rb
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

イメージは確かにこちらのがしやすいのは事実。

一方でコントローラはどうか?

app/controllers/blogs_controller.rb
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つ目の newBlogsController クラス内に定義してある インスタンスメソッド
両者は全くの別物ということも気をつけなければならない。

ちなみに他のアクションはブラウザからの情報(パラメータ)が必要なため、railsコンソール上では実行できない。

まとめ

  1. URLが/blogsでHTTPメソッドがGETの時、rake routesよりコントローラとアクションが blogs#index に定まる。
  2. BlogsControllerクラスのインスタンスが生成される
  3. BlogsControllerクラスのインスタンスメソッドであるindexを実行する
  4. indexの中に記述されている @blogs = Blog.all が実行される
24
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
12