Rails ActiveRecord いろいろ

仕事柄プルリクをレビューすることが多々あるのですが、やっぱりまだまだわかっていないことが多い… 忘れないようにメモメモ…

inverse_of

inverse_of を指定したリレーションのある2つのモデルでは、双方から同一のインスタンスを参照することができる。 つまり、双方ともメモリ上では同じインスタンスとして扱われる。 inverse_of の設定がないと同一のインスタンスとしては扱われず、一方からの変更がもう一方から参照されても変更されていない ふむふむ…

class User < ActiveRecord::Base
  has_many :menus
end

class Menu < ActiveRecord::Base
  belongs_to :user
end
user = User.first
menu = user.menus.first
user.name == menu.user.name # => true
user.name = "change"
user.name == menu.user.name # => false

Userのフィールド name の変更が、Menu からたどった時に変更が参照されていない。メモリ上では別インスタンスとして扱われているからである。

inverse_of を指定してあげる

class User < ActiveRecord::Base
  has_many :menus, inverse_of: :user
end

class Menu < ActiveRecord::Base
  belongs_to :user, inverse_of: :menus
end

メモリ上では同一インスタンスとして扱われるようになるので、user もしくは user.menuから name を変更しても以下の結果になる

user.name == menu.user.name # => true

すげーな!

change_column_null

ActiveRecordでcolumnにNotNull成約をかけてしまったけども、後々になってやっぱり制約を外したい…なんてときに使います。

class ChangeColumnToUser < ActiveRecord::Migration[5.1]
  def change
    change_column_null :users, :name, true
  end
end
change_column_null table名, column名, true/false