ActiveModel::Dirtyのattribute_changed?とかが便利なんです

saveしているはずなのにsaveできないんです! - なんでや。。

上記でも少し触れたActiveModel::Dirtyのchange的なメソッドたちが便利。

ActiverRecord::BaseがActiveRecord::AttributeMethods::Dirtyを、それがActiveModel::Dirtyをincludeしている関係。

ActiveModel::Dirtyを使うにはdefine_attribute_methodsを呼んだり下準備が必要だが、ActiveRecordを使っていれば全部面倒見てくれる様子。

使ってみる

正直、メソッド名が似すぎてて覚えにくい。

o = Employee.find(209)
o.attributes = {
  first_name: 'ichiro',
  last_name: 'yamada',
  manager_id: 154,
  salary: o.salary + 1000,
  phone_number: '12-3456-7890'
}

if o.changed?
  puts '変更された項目'
  o.changes.each do |attribute, change_set|
    puts "  #{attribute}#{change_set[0]} -> #{change_set[1]}"
  end

  puts '変更された項目(別の方法で出力)'
  o.changed.each do |attribute|
    puts "  #{attribute}#{o.send(attribute + '_change')[0]} -> #{o.send(attribute + '_change')[1]}"
  end

  puts '変更された項目(別の方法で、変更前の値のみ出力)'
  o.changed_attributes.each do |attribute, original_value|
    puts "  #{attribute}: original value = #{original_value}"
  end

  puts 'えっ また上司変わったの??' if o.manager_id_changed?
  puts 'これがアベノミクス効果か!' if o.salary_was < o.salary
  puts '専用の内線番号もらったぞ' if o.phone_number_was.blank? && o.phone_number.present?
end

参考