ruby rails ActiveRecord對象 的修改痕跡追蹤

最近開發需要,找到幾個用來追蹤ActiveRecord對象修改歷史的方法,記錄於此

ActiveRecord對象有不少關於change的方法

irb(main):099:0>  ActiveRecord::Base.public_instance_methods.grep(/change/)
[:attachment_changes, :changed_for_autosave?, :saved_change_to_attribute, :saved_changes?, :saved_changes, :will_save_change_to_attribute?,
:attribute_change_to_be_saved, :changes_to_save, :changed_attribute_names_to_save, :has_changes_to_save?, :saved_change_to_attribute?, :attribute_changed_in_place?,
:changed, :clear_attribute_changes, :changes_applied, :attribute_changed?, :attribute_previously_changed?, :clear_changes_information, :changed_attributes,
:changed?, :previous_changes, :changes]

我認爲重要的方法:

第一組方法,只反映屬性修改後 且未曾保存到數據庫時的狀態

changed?   對象整體是否改變

attribute_changed?   指定屬性是否改變

changed    返回有改變的屬性名數組 => ["note"]

changes 返回有改變的屬性的hash對象  => {"note"=>["abd", "abe"]}

attribute_was  指定屬性修改前的值

 

第二組方法,反映屬性修改且已經保存到數據庫後的狀態

saved_changes?  對象整體是否有過改變

previous_changes  有過改變的屬性的hash對象

saved_changes   previous_changes

attribute_previously_changed?  指定屬性是否有已保存到數據庫的改變

attribute_before_last_save   指定屬性上次修改前的值

 

通過給每個屬性賦新值對ActiveRecord對象進行修改的情況,可以再save之前使用第一組方法獲知修改情況

# 獲取數據對象
irb(main):020:0> d = Notice.find(13)
# 查看原屬性
irb(main):020:0> d.note
=> ""
# 修改屬性,然後再保存 change, and save
irb(main):026:0> d.note='abc'
=> "abc"
irb(main):027:0> d.attribute_was :note
=> ""
irb(main):028:0> d.note
=> "abc"
irb(main):028:0> d.changed?
=> true
irb(main):029:0> d.save   
=> true
irb(main):030:0> d.note
=> "abc"

irb(main):031:0> d.attribute_was :note
=> "abc"
irb(main):032:0>  d.attribute_previously_changed? :note
=> true
irb(main):033:0> d.attribute_before_last_save :note
=> ""
irb(main):034:0>

  irb(main):034:0> d.changed?
  => false
  irb(main):034:0> d.attribute_previously_changed? :note
  => true

直接調用update對ActiveRecord對象進行修改的情況,由於數據已經保存了,只能使用第二組方法獲知修改情況

# 重新獲取數據對象
irb(main):020:0> d = Notice.find(13)
# 查看原屬性
irb(main):020:0> d.note
=> "abc"
# 直接更新數據 update directly
irb(main):020:0> d.update! note: 'abd'
   (0.2ms)  begin transaction  
   (89.1ms)  commit transaction
=> true
irb(main):023:0> d.attribute_changed? :note
=> false
irb(main):022:0> d.attribute_previously_changed? :note
=> true
irb(main):021:0> d.attribute_before_last_save :note
=> "abc"

irb(main):024:0> d.note
=> "abd"
irb(main):025:0> d.attribute_was :note
=> "abd"
取得新的ActiveRecord對象,不能追蹤屬性變化,說明修改信息僅位於內存對象中
# 新的ActiveRecord對象,不能追蹤,說明修改信息僅僅位於內存對象中
irb(main):037:0> d2 = Notice.find(13)
  Notice Load (0.2ms)  
irb(main):039:0> d2.note
=> "abd"
irb(main):040:0> d2.attribute_previously_changed? :note
=> false
irb(main):041:0> d2.attribute_before_last_save :note
=> nil
irb(main):041:0>

 

# 遍歷修改的屬性
irb(main):044:0> (d.attribute_names - ["updated_at","created_at"]).each{|f| puts "#{f} chaned from [#{d.attribute_before_last_save(f)}] to [#{d[f]}]" if d.attribute_previously_changed?(f)}
note chaned from [abc] to [abd]

使用previous_changes獲取修改過的那些屬性的 hash, 包含原值和新值
# ActiveRecord對象的方法previous_changes獲取修改的屬性 hash, 包含原值和新值
irb(main):079:0> d.changes
=> {}
irb(main):078:0> cs=d.previous_changes
=> {"note"=>["abc", "abd"], "updated_at"=>[Thu, 12 Nov 2020 15:18:07 CST +08:00, Thu, 12 Nov 2020 16:21:45 CST +08:00]}
# 刪除無用屬性
irb(main):080:0> cs.delete :updated_at
=> [Thu, 12 Nov 2020 15:18:07 CST +08:00, Thu, 12 Nov 2020 16:21:45 CST +08:00]
irb(main):081:0> cs
=> {"note"=>["abc", "abd"]}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章