Rails
ActiveRecord

[Rails]has_oneの関係を作るときに注意すべきこと

More than 1 year has passed since last update.

Railsでhas_oneを用いることがよくある。しかし、この関係は正規化に反しているため色々面倒な状況になることが多い。よくあるのが、DBで親レコードはあるのに子レコードはないという状況で、そうなるとアプリケーションレベルで吸収しないといけなくなる。(子レコードがある場合、ない場合と分岐が必要になってくる)

なので、親モデルをsaveする場合は、has_oneのモデルも自動で作るようにしてあげると良い。そうすれば、親レコードがある場合は子レコードも必ずあるように強制できる。

例えば、UserモデルとUserSettingモデルがhas_oneの関係にある場合、以下のようにすれば良い。

class User < ActiveRecord::Base
  has_one :user_setting
  before_validation :build_child, on: :create

  private 
    def build_child
      build_user_setting
    end
end

こうしておけば、Userをsaveした際に、UserSettingも自動でsaveされる。(ただし、子テーブルの全てのカラムでデフォルト値が設定されている必要あり)

has_oneの乱用には問題があるが、とはいっても代わりに親モデルに子の要素を入れ込んでしまうと見通しが悪くなることも多いので、使った方が良い場合も多い。なので、使う場合は色々とコストを頭に入れた上で使うようにしたい。