Active Record Query Interface 3.0 覚書

Active Record Query Interface 3.0に基づいて

  • 2.3まで使っていたfind(〜)は、find(id)かfind(配列)しか使えない(つまり、id検索にしか使えない)
  • find(:all)、find(:first)は廃止予定。allかfirstを使う
  • find_by_user('文字列')は生き残り。
  • :conditionsを使いたい場合は、whereを使う。

追記:本家

より詳しい説明を本家に見つけた。

id から検索する場合

  • User.find(id) :id一つ
  • User.find(配列) :複数のid

あるフィールドの要素に関して一致するものを探す場合

すぐに取得して使うならばfind_by〜を使った方が良いらしい。

Dynamic attribute-based finders are a cleaner way of getting (and/or creating) objects by simple queries without turning to SQL. They work by appending the name of an attribute to find_by_, find_last_by_, or find_all_by_ and thus produces finders like Person.find_by_user_name, Person.find_all_by_last_name, and Payment.find_by_transaction_id. Instead of writing Person.where(:user_name => user_name).first, you just do Person.find_by_user_name(user_name). And instead of writing Person.where(:last_name => last_name).all, you just do Person.find_all_by_last_name(last_name).
Rais APIより)

  • User_find_by_フィールド名('文字列')
  • User_find_by_フィールド1_and_フィールド2('文字列1', '文字列2')

存在するならそのレコードを返し、存在しないなら新しいレコードを作成する

TagsテーブルのnameフィールドがSummerであるレコードがあれば、そのレコードを返し、そうでなければnameがSummerな新たなレコードを作成する(Tag.create(:name => "Summer")と一緒)。

  • Tag.find_or_create_by_name("Summer")

保存したくなければこちら(Tag.new(:name => "Winter")と一緒)。

  • Tag.find_or_initialize_by_name("Winter")

条件(SQLでいうwhere節、2.3系でいう:conditions => [])

  • User.where("user_name = ? AND password = ?", user_name, password)
  • User.where(:user_name => user_name, :password => password)

一つ目と二つ目は同じ意味。whereで引数をただ並べると、ANDでつながれたことになるとのこと。
条件部分が長い場合は、以下のようにする。

User.where(
    "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
    { :id => 3, :name => "37signals", :division => "First", :accounting_date => '2005-01-01' }
  )

条件+BETWEEN

SQLのBETWEENを使う場合。以下の場合gradeフィールドで9から12の値が格納されているものを探す。

  • Student.where(:grade => 9..12)

条件+IN

SQLのINを使う場合。以下の場合gradeフィールドで9, 11, 12の値が格納されているものを探す。

  • Student.where(:grade => [9,11,12])

共通に何度も使う条件をあらかじめ定義しておく

モデルにて以下のように定義する。

class Item
  scope :red, where(:colour => 'red')
  scope :since, lambda {|time| where("created_at > ?", time) }
end

引数がある場合はlamdaを使って定義する。仕様する際には以下のように使う。

  • Item.red
  • Item.since(10.days.ago)

返り値

モデルがUserであるとき

インターフェース 成功したとき 失敗したとき
User.find(id) レコード 例外 RecordNotFound
User.first() レコード nil
User.last() レコード nil
User.all() レコード 空の配列
他のインターフェース ActiveRecord::Relation ActiveRecord::Relation