find と find_by の違い

ActiveRecord::FinderMethods より

モノが違うので一言では書けないです

概要

#find(*arg)

  • 正常系処理
    • 実引数の値はテーブルのプライマリーキーに対応していることを期待
      • 甲. find(value)
        • 値を WHERE 句で条件制約して SELECT する
          値がテーブル中に存在することを期待
      • 乙. find([value, value, ..., value])
        • 配列中の値を IN 句で条件制約して SELECT する
          すべての値がテーブルに存在することを期待
  • 異常系処理
    • 実引数の値はテーブルのプライマリーキーに対応していることを期待
      • 甲. find(value)
        • value に該当するプライマリーキー無し
      • 乙. find([value, value, ..., value])
        • value に該当するプライマリーキーが 1 つもない
      • 丙. find(value)
        • value が nil
    • 異常動作
      • 甲乙丙 全て ActiveRecord::RecordNotFound を raise する

#find_by(*arg)

  • 正常系処理
    • 実引数の値
      • 甲. fubd(field > value)
        • field に対応する値を WHERE 句で条件制約して SELECT する
      • 乙. find(field > array[value, value, ... value])
        • field に対応する配列中の値を IN 句で条件制約して SELECT する
        • 一番最初に見つかった relation を return する
  • 異常系処理
    • 実引数の値
      • 甲. find(field > value)
        • テーブルの field には value が存在しない
      • 乙. find(field > array[value, value, ... value])
        • 同上
    • 異常動作
      • 甲乙 共に nil が返る

詳細ベタ貼り

説明用の前提環境

  • Rails 4.2.1
  • Ruby 2.2.1
  • MacOSX 10.10.4
  • sqlite3
    • マスターテーブル
    • users(id @ int & PK, name @ text)
      • 1, 'taro'

      • 2, 'jiro'

      • 3, 'saburo'

正常動作

甲. find(value)

> User.find(1)
SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]

乙. find([value, value, ..., value])

> User.find([1, 2, 3])
SELECT "users".* FROM "users" WHERE "users"."id" IN (1, 2, 3)

異常動作

甲. find(value) > value に該当するプライマリーキー無し

> User.find(-1)
SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", -1]]
ActiveRecord::RecordNotFound: Couldn't find User with 'id'=-1

乙. find([value, value, ..., value]) > value に該当するプライマリーキーが 1 つもない

> User.find([1, 2, -1])
SELECT "users".* FROM "users" WHERE "users"."id" IN (1, 2, -1)
ActiveRecord::RecordNotFound: Couldn't find all Users with 'id': (1, 2, -1) (found 2 results, but was looking for 3)

丙. find(value) > value が nil

> User.find
ActiveRecord::RecordNotFound: Couldn't find User without an ID

#find_by

正常動作

甲. find(field > value)

> User.find_by(name: 'taro')
SELECT  "users".* FROM "users" WHERE "users"."name" = ? LIMIT 1  [["name", "taro"]]

乙. find(field > array[value, value, ... value])

> User.find_by(name: ['matsukawa', 'test', 'taro'])
SELECT  "users".* FROM "users" WHERE "users"."name" IN ('matsukawa', 'test', 'taro') LIMIT 1
=> #<User id: 1, name: "taro", created_at: "2015-08-07 16:32:24", updated_at: "2015-08-07 16:32:24">

異常動作

甲. find(field > value)

User.find_by(name: 'matsukawa')
SELECT  "users".* FROM "users" WHERE "users"."name" = ? LIMIT 1  [["name", "matsukawa"]]
=> nil

乙. find(field > array[value, value, ... value])

User.find_by(name: ['matsukawa', 'test'])
SELECT  "users".* FROM "users" WHERE "users"."name" IN ('matsukawa', 'test') LIMIT 1
=> nil