I want to use the .changed? method to check if a record has changed. The problem is that one of the fields will always be different. I would like to ignore the field. Something like:
record.changed?.except(:field_to_ignore)
How can I solve this?
ActiveModel::Dirty gives you a list of all the attributes that have changed via the changed method. So you could do something like
record.changed.reject { |attr| attr == 'field_to_ignore' }.size > 0
Read more about changed method here
EDITED
A simple solution to this is to use the same changed? functionality from ActiveModel::Dirty, so let's say that the attribute you don't want to take into account is x, with that said you can do something like this:
atttibutes_changed = record.changed_attributes.keys
atttibutes_changed.size > 1 || !atttibutes_changed.include?('x')
The above condition means: if more than one attribute changed or in case one changed need to be different from x. changed_attributes returns a hash with all the attributes that changed and his values (before change).
Related
I can't think of a better way to title this Sorry!
Ultimately I have a callback that 99% of the time I only want to run when a particular list of attributes get changed. But in a couple of cases I'd love to be able to by pass my return unless previous_changes & watched_attributes.
Is there any way to mock a change to a particular attribute? Somehow set model.attribute_changed? to true?
I've been using model.touch but updated_at is a column I deliberately want to ignore.
Yes, you can check whether your attribute is changed or not by using following command
#object.column_changed? #=> true
You can get an array of changed attributes by using changed method
#object.changed #=> ['column_name']
You can try something like the following:
object.attribute_name_will_change!
object.changed << :attribute_name
puts object.attribute_name_changed?
puts object.changed?
resulting output is:
true
true
attribute_name is to be replaced with the name of your attribute.
I've been trying to update the wrong migrated values of the hash store,
"area_unit"=>NULL, "building_type"=>"{:building_type=>\"apartment\"}",
to
"area_unit"=>NULL, "building_type"=>"apartment"}",
the value should stay the same, I don't want to use regular expression. is there an easy way for doing that ? I'm working with ruby.
I was able to do it like the following, not a generic solution like I wanted, but it works.
SELECT id, properties::hstore ->'building_type' FROM stops WHERE (properties->'building_type' like '{:building_type=>\"apartment\"}');
UPDATE stops SET properties = properties || '"building_type"=>"apartment"'::hstore
WHERE (properties->'building_type' like '{:building_type=>\"apartment\"}');
I want to find any product that has a higher ip_solid than ip_liquid.
I am trying to do the following:
Product.where("ip_solid > ?", :ip_liquid).count
However, it seems that :ip_liquid is not being read out from each object, and is probably evaluating to 0 or nil. Is something like this even possible?
Product.where("ip_solid > ip_liquid").count should do it as long as ip_liquid is a field in the database and not a method on your model
I have an ActiveRecord model #new_profile that has some, but not all of its properties filled in. I have another model #default_profile that has a bunch of values I want to copy over, but only if the properties from the first are not filled in. Is there a built in way to do this besides a block like...
#new_profile.name ||= #default_profile.name
#new_profile.address ||= #default_profile.address
# etc.
This might work
#new_profile.update_attributes!(#default_profile.attributes.merge(#new_profile.attributes))
The problem with this, is that if the attribute is in #new_profile, but it is nil, the merge might leave the value set as nil. You might need to do the following.
new_profile_attrs = #new_profile.attributes.reject{ |key,value| !value }
#new_profile.update_attributes!(#default_profile.attributes.merge(new_profile_attrs))
#new_profile.update_attributes(#default_profile.attributes.merge(#new_profile.attributes))
You could try something like
#new_profile.attributes = #new_profile.attributes.reverse_merge #default_profile.attributes
If you need to copy ALL the attributes (except id of course):
#new_profile.attributes.each{|k,v| #new_profile[k] ||= #default_profile[k] if k != 'id'}
Things like update_attributes won't allow you to copy attr_protected-attributes. This thing should.
How do I check if the data is changed when I edit a record?
So before update
game.player=1
after update / edit
game.player=2
for example
how to track changes (check if changed) and do something in ruby on rails, when the data is changed.
Have a look at ActiveModel::Dirty
You can check if a model has been changed by doing:
game.changed?
Or an individual field like:
game.player_changed?
Both return a boolean value.
All changes are also kept in a hash. This comes in handy if you want to use the values.
game.changes #=> {:player => [1,2]}