前提
find_or_initialize_by
にこだわるのは本質的ではなく、find_by
や where
などでも同じです。本質はタイムゾーンの違いです。
結論
具体例を見たほうが早いと思いますので、載せます。
NG な例
user = User.find_or_initialize_by( name: 'hoge', submitted_at: '2023/04/07 17:48:31' )
これを繰り返し実行した場合に、常に user.new_record?
が true
を返してしまいます。
OK な例
期待通りの動作をさせるためには、テキストでそのまま入れるのではなく Time.zone.parse
します。
ただし、データソースによってはタイムゾーンには注意が必要です(こちらなどを参照)。
user = User.find_or_initialize_by( name: 'hoge', submitted_at: Time.zone.parse('2023/04/07 17:48:31') )
これで find
でちゃんと見つけてきてくれます。
検討
SQL を見てみるとよく分かります*1。
NG な例
User.find_by(submitted_at: "2023/04/07 17:48:31") #=> SELECT "users".* FROM "users" WHERE "users"."submitted_at" = $1 LIMIT $2 [["submitted_at", "2023-04-07 17:48:31"], ["LIMIT", 1]]
OK な例
User.find_by(submitted_at: Time.zone.parse("2023/04/07 17:48:31")) #=> SELECT "users".* FROM "users" WHERE "users"."submitted_at" = $1 LIMIT $2 [["submitted_at", "2023-04-07 08:48:31"], ["LIMIT", 1]]
*1:PostgreSQL を使用しています