Rails 5 with mongoid .changed is always empty on update - ruby-on-rails

In my controller, I have the *_params to permit attributes. No matter what, even when things are definitely changed, .changed is always blank. Is there a new Rails 5 way to detect changed attributes?
# case_params is the basic rails controller permission method
if #case.update(case_params)
puts #case.changed.count # this is is always 0
...
Can anyone see what I'm doing wrong? I need to know what's changed so I can selectively do some other work in a thread but only for changed attributes.
Thanks for any help.

You can use #cases.previous_changes which gives all the changes to the document in the form of a hash. The hash also consitis of updated_at attribute. You can do -1 to the above count to get all the changed attributes count excluding updated_at.
You can get the count by #cases.previous_changes.keys.count - 1
We need to subtract -1 for removing updated_at attribute changes.
If you want to detect changes in the assosiation you can use try using children_changed? for it.

Related

Modify updated_at attribute through db trigger in rails

I was wondering if there is anything wrong about updating the updated_at attribute of a record through a db trigger in terms of fragment caching (i.e. the partials dont get re-cached / the old cache keys do not disappear from memory).
additional info I'm using a trigger due to using the upsert gem which does not modify the updated_at attribute unless explicitly told to do so ( which I do not want to do ); also, due to the same gem I cannot use an active::record after_save or before_save on the model.
Please let me know if there any other information I should provide to add some clarity to my question.
There isn't nothing wrong, but if you need to do so you can simply use record.touch in a method so your code will be more clean and app will be more maintainable.
One more way to achive that is to use on_duplicate attribute of the Rails upsert_all method (without any gems). Check the documentation, pseudo code example:
YourModel.upsert_all(
array_of_data,
unique_by: %i[field_1 field_2],
on_duplicate: Arel.sql('updated_at = current_timestamp')
)
If you have other fields to update, don't forget to add them into Arel.sql:
on_duplicate: Arel.sql('updated_at = current_timestamp, field_to_update = excluded.field_to_update')

Ignore a column when using `.changed?` in rails

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).

Rails - Get old value in before_save

I'm trying to get the old value in the before_save by adding "_was" to my value but it doesn't seem to work.
Here is my code:
before_save :get_old_title
def get_old_title
puts "old value #{self.title_was} => #{self.title}"
end
Both "title_was" and "title" got the new title just been saved.
Is it possible to get the old value inside before_save ?
The reason for you getting the same value is most probably because you check the output when creating the record. The callback before_save is called on both create() and update() but on create() both title and title_was are assigned the same, initial value. So the answer is "yes, you can get the old value inside before_save" but you have to remember that it will be different than the current value only if the record was actually changed. This means that the results you are getting are correct, because the change in question doesn't happen when the record is created.
Instead of before_save use before_update. It should work now.
So, the answer above might work but what if I wanted to get the previous value for some reason and use it to perform some task then you would need to get the previous value. In my case I used this
after_update do
if self.quantity_changed?
sku.decrement(:remaining, (self.quantity_was - self.quantity) * sku.quantity)
end
end
The _was and _changed? added to any of the columns would do the job to get the job done.
In rails 5.1.1 ActiveRecord::AttributeMethods::Dirty provides
saved_changes()
Link for saved_changes()
which returns a hash containing all the changes that were just saved.

Rails 3: update_attributes sets column to 'nil'

The problem I'm having is with the method update_attributes. The code:
n is set to an Active Record object.
n = Notification.find(notification_id)
Then, n is updated with the hash notification_options.
n.update_attributes(notification_options)
The issue I'm having is when I
raise n.inspect
It shows the two fields are set to nil. Also, in the database the two fields are empty.
Why won't it update the attributes?
Let me know if I need to be more specific.
This is because you're using attr_accessor, and not attr_accessible, I would guess. Please show us your Notification model.
So it ends up that the issue was with a line in the model for a gem that being used. It needed a specific format which was causing it to set to nil if it didn't match.

Track changes when updating a record

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

Resources