RoR入門第14回

引き続きリレーションシップ編。
検索条件の指定の仕方が増えてきてこんがらがってきたので整理する。

findメソッドの引数で指定する
Hoge.find(:all, ["column = ?", param])
Hoge.find(:first, ["column = :param", {:param => value}])
Hoge.find(:all, {:column => param})
ナマSQL

select句でASを使うとその名前の導出カラムが取得できる。
カウントの場合はcount_by_sql

Hoge.find_by_sql("select hoges.* from hoges where column = param")
動的ファインダ
Hoge.find_by_name(name)
Hoge.find_all_by_name(name)
Hoge.find_by_name_and_age(name, age)
Hoge.find_by_name(name, :conditions => "age = 100")
Hoge.find_or_initialize_by(name)  #new
Hoge.find_or_create_by(name)  #create
スコープ
class Hoge < ActiveRecord::Base
  named_scope :fuga, lambda {|parama| :condition => ["column < ?", param]}
  named_scope :same_as_fuga, lambda {:column => param}
end
Hoge.fuga(param)
piyo = Hoge.scoped(:conditions => "age >= 100")
Hoge.piyo.fuga(param)

しかしこれ、どうなっているのかしら。
piyoを実行したときの戻り値がスコープオブジェクトなのだとして、fugaを実行したときの戻り値もスコープオブジェクトになるのではと思いきや、ちゃんとActiveRecordの配列が返るらしい。
piyoとfugaの差は何?
それともSQLの発行は実は遅延実行されている?

アソシエーションの拡張
class Fuga
  #単一の拡張
  has_many :hoges do
    def age_over(age)
      find :all, :conditions => ['age >= ?', age]
    end
  end
  #複数の拡張を使いたいとき、拡張を使いまわしたいとき(たぶん)
  has_many :piyos, extend => ExtendModule
  has_many :hogeras, extend => [ExtendModule, ReusableModule]
end
Fuga.hoges.age_over(100)

やっぱり遅延実行なのか?
Fuga.hogesを呼んだときにSQLが実行されるとしたら、age_overを呼ぶときにもう一度SQLが実行されてしまうし。