Rails 3 check if attribute changed

前端 未结 5 707
渐次进展
渐次进展 2020-11-29 17:53

Need to check if a block of attributes has changed before update in Rails 3.

street1, street2, city, state, zipcode

I know I could use something like

相关标签:
5条回答
  • 2020-11-29 17:59

    For rails 5.1+ callbacks

    As of Ruby on Rails 5.1, the attribute_changed? and attribute_was ActiveRecord methods will be deprecated

    Use saved_change_to_attribute? instead of attribute_changed?

    @user.saved_change_to_street1? # => true/false
    

    More examples here

    0 讨论(0)
  • 2020-11-29 18:08

    Check out ActiveModel::Dirty (available on all models by default). The documentation is really good, but it lets you do things such as:

    @user.street1_changed? # => true/false
    
    0 讨论(0)
  • 2020-11-29 18:12

    This is how I solved the problem of checking for changes in multiple attributes.

    attrs = ["street1", "street2", "city", "state", "zipcode"]
    
    if (@user.changed & attrs).any?
      then do something....
    end
    

    The changed method returns an array of the attributes changed for that object.

    Both @user.changed and attrs are arrays so I can get the intersection (see ary & other ary method). The result of the intersection is an array. By calling any? on the array, I get true if there is at least one intersection.

    Also very useful, the changed_attributes method returns a hash of the attributes with their original values and the changes returns a hash of the attributes with their original and new values (in an array).

    You can check APIDock for which versions supported these methods.

    http://apidock.com/rails/ActiveModel/Dirty

    0 讨论(0)
  • 2020-11-29 18:16

    ActiveModel::Dirty didn't work for me because the @model.update_attributes() hid the changes. So this is how I detected changes it in an update method in a controller:

    def update
      @model = Model.find(params[:id])
      detect_changes
    
      if @model.update_attributes(params[:model])
        do_stuff if attr_changed?
      end
    end
    
    private
    
    def detect_changes
      @changed = []
      @changed << :attr if @model.attr != params[:model][:attr]
    end
    
    def attr_changed?
      @changed.include :attr
    end
    

    If you're trying to detect a lot of attribute changes it could get messy though. Probably shouldn't do this in a controller, but meh.

    0 讨论(0)
  • 2020-11-29 18:23

    Above answers are better but yet for knowledge we have another approch as well, Lets 'catagory' column value changed for an object (@design),

    @design.changes.has_key?('catagory')
    

    The .changes will return a hash with key as column's name and values as a array with two values [old_value, new_value] for each columns. For example catagory for above is changed from 'ABC' to 'XYZ' of @design,

    @design.changes   # => {} 
    @design.catagory = 'XYZ'
    @design.changes # => { 'catagory' => ['ABC', 'XYZ'] }
    

    For references change in ROR

    0 讨论(0)
提交回复
热议问题