JQ Blog

ActiveRecordの中身

動的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
require 'activerecord'
ActiveRecord::Base.establish_connection :adapter => "sqlite3",
                                        :database => "dbfile"

ActiveRecord::Base.connection.create_table :tasks do |t|
  t.string   :description
  t.boolean  :completed
end

class Task < ActiveRecord::Base; end

task = Task.new
task.description = 'ブログの記事作成'
task.completed = true
task.save
task.description # => "ブログの記事作成"
task.completed?  #=> true

上記のコードに属性にアクセスする4つのメソッドを呼び出している。(description=()、completed=()、description()、completed?())
しかし、これらの「属性アクセサ」はTaskクラスの定義にはない。
では、このアクセサはどこからきたものなんだろうか。

ActiveRecord::Base#method_missing()

実際にactive_record/attribute_methods.rbではActiveModel::AttributeMethodsincludeしてmethod_missing()を使っている。method_missing()が呼び出されたら該当メソッドがあるかどうかを判断し、ゴーストメソッドを生成する。そのゴーストメソッドはゴーストアクセサになり、動的に属性にアクセスすることができる。

動的ファインダ

1
2
3
4
5
6
7
8
9
10
task = Task.find(:first, :conditions => {:completed => true})
task.description # => "ブログの記事作成"

task = Task.find_by_description('ブログの記事作成')
task.id # => 1

Task.find_all_by_completed(true)
Task.find_by_description_and_completed('ブログの記事作成', true)
Task.find_or_create_by_description('ランチターイム')
Task.find_by_description!('帰宅')

ActiveRecord::Base.findfind_by_<attr>のように属性名を含むメソッドでの検索もできる。
and, or での連結などもできる。
これも動的属性と同じく「ゴーストメソッド」で実装している。
ここでもやはり最初にmethod_missingでメソッドを定義して次からは直接呼び出せるようにしている。

参照

rails/activerecord at master · rails/rails · GitHub