当前位置 博文首页 > 文章内容

    ruby rails ActiveRecord对象 的修改痕迹追踪

    作者: 栏目:未分类 时间:2020-11-13 9:00:45

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    最近开发需要,找到几个用来追踪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?   指定属性是否改变

    changes 改变属性的hash对象

    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"]}