search
LoginSignup
22

More than 5 years have passed since last update.

Organization

カラム名をメソッドとして実行できる概念

カラム名をメソッドとして実行できる、とは

Railsコンソールで以下のコードを実行してみる。


@blog = Blog.new #=> #<Blog id: nil, title: nil, content: nil, created_at: nil, updated_at: nil>
@blog.title = "aaa" #=> "aaa"
@blog.title #=> "aaa"

カラム名がそのままメソッドになっている ことは上記コードを見ればなんとなくわかるだろう。
当たり前のように実行しているが、この概念を本当に理解しているか?
特に2行目の @blog.title = "aaa"=代入 と勘違いしてる人が多いのではないか?

カラム名をメソッドとして実行できる概念を理解する

そこで今回はActiveRecordの機能を除き、以下5つのコードを正常に実行できるようなblogモデルにそっくりのクラスを、ライブラリなしで作成していく。


@blog = Blog.new("aaa", "bbb") #=> #<Blog:0x007fe748e000b0 @title="aaa", @content="bbb">
@blog.title #=> "aaa"
@blog.content #=> "bbb"
@blog.title = "aaa" #=> "aaa"
@blog.content = "bbb" #=> "bbb"

まず1行目を見ると以下を把握できる

  • Blogというクラスがある
  • newメソッドを実行した時点で引数が2つある
  • @title , @content というインスタンス変数を用いて、Blogクラスのインスタンスに代入している

従って以下のように実装できる


class Blog
  def initialize(title, content)
    @title = title
    @content = content
  end
end

次に2行目と3行目に着目する

  • @blog の中にはBlogクラスのインスタンスが入っている
  • titleというインスタンスメソッドがある
  • contentというインスタンスメソッドがある

class Blog
  def initialize(title, content)
    @title = title
    @content = content
  end

  def title
    return @title
  end

  def content
    return @content
  end
end

Rubyではreturnを省略すると、そのメソッドの最後の行がreturnされる。
ここではtitle, contentというメソッド内は1行しかないので、そのままreturnを省略する。


class Blog
  def initialize(title, content)
    @title = title
    @content = content
  end

  def title
    @title
  end

  def content
    @content
  end
end

で、問題の4行目と5行目。
これは @blog.titleへの代入 ではないので勘違いしないように気をつけよう。


@blog.title = "aaa"

上記のコードを以下に書き換えてみよう。


@blog.title=("aaa")

このようにすると @blog.title代入 ではなく title= という名前の インスタンスメソッドを実行している ということがわかる。
5行目も同じだ。

最終的に以下のようになる。


class Blog
  def initialize(title, content)
    @title = title
    @content = content
  end

  def title
    @title
  end

  def title=(title)
    @title = title
  end

  def content=(content)
    @content = content
  end
end

Railsにおいてはどこに定義されているのか

Railsのblogモデルを見ると以下のようになっている。


class Blog < ApplicationRecord
end

上記コードを見ると def titledef content=(content) のような記述は見当たらない。
ではどこに定義されているのか?
それは ActiveRecord::Base である。

ActiveRecord::Baseが動的に titlecontent= というメソッドを生成している。


class Blog < ApplicationRecord
  # def title
  # end

  # def title=(title)
  # end

  # def content
  # end

  # def content=(content)
  # end
end

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
What you can do with signing up
22