ActiveRecordのfindには"123ABC"という文字列を渡しても動く

3950 ワード

結論

モデルのPrimary Keyが整数の場合、Person.find("123ABC")という文字列を渡すとto_iで数値に変換され、Person.find(123)と評価される。

Person.find("123ABC")
↓ 
Person.find(123)

経緯

仮にPersonというモデルがあり、Primary Keyが整数、/persons/:idの形式で渡されるIDを使ってPerson.find(params[:id)のようにクエリを投げている処理があるという前提。

アクセスログを眺めていたら/persons/123ABCのように文字列を入れてアクセスしてきているケースがあった。
ActiveRecordのfindでは指定されたIDを持つレコードが見つからなければActiveRecord::RecordNotFoundがraiseされるはずが、普通にアクセスできてしまうことに気付く。(ID = 123のレコードのデータが表示されている)

よくよくドキュメントを読んでみると以下の記載があった。

Person.find(1)          # returns the object for ID = 1
Person.find("1")        # returns the object for ID = 1
Person.find("31-sarah") # returns the object for ID = 31

If the primary key is an integer, find by id coerces its arguments by using to_i.