created_atがNULLで保存される

何が原因なのかわからないけどとりあえずメモ。ここ数日以下のエラーが頻発するようになった。

PG::Error: ERROR:  列"created_at"内のNULL値はNOT NULL制約違反です
: INSERT INTO "answers" ("hogehoge", "created_at", "memo", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"
  activerecord (3.2.9) lib/active_record/connection_adapters/postgresql_adapter.rb:1166:in `get_last_result'

これに対応するコードは objectc_controller.rb の以下の部分。

targetObject.save!

そして 上記のSQLのINSERT文が発行される。

INSERT INTO "answers" ("hogehoge", "created_at", "memo", "updated_at") VALUES ($1, $2, $3, $4) 

どうも、このcreated_atフィールドに渡される値がNULLらしい。でも、これはRAILSが自動的に埋めてくれているはず。Googleで検索したら以下のように同じようなトラブルに直面している方がいた。

Title: Problem with Rails, created_at or updated_at sometime become null
タイトル:Railsでcreated_at もしくは updated_at がnullになる問題

On my Rails web application, records are sometime saved with null created_at or updated_at.
私のRails webアプリで、時々レコードがcreated_atもしくはupdated_atがnullで保存されてしまいます。

This problem occurred for models which have child models.
この問題は、子モデルを持つモデルに発生しました。

Therefore I added before_create method in model.
したがって、before_createメソッドをモデルに追加しました。

def before_create
self.created_at = Time.now if self.created_at.blank?
self.updated_at = Time.now if self.updated_at.blank?
end

This method will fix the problem.
このメソッドで問題は解決するでしょう。

なので、私も上記にならって app/model/object.rb に before_create を追加。ただし、rails 3からはbefore_createをメソッドとして書く方法は不採用になったとのこと。

app/model/object.rb に以下のようなメソッドを追加した。logger.infoにしているのはproductionモードでログに出したいため。参考:Debugging Rails Applications

before_create :check_created_at_and_updated_at

  private

  def check_created_at_and_updated_at
    if self.created_at.blank?
      logger.info("created_at is null. id = #{self.id}")
      self.created_at = Time.now
    end 
    if self.updated_at.blank?
      logger.info("updated_at is null.")
      self.updated_at = Time.now
    end 
  end

これでうまくいくかどうかを様子見。