I'm trying to use ActiveModel::Dirty/ActiveRecord::AttributeMethods::Dirty in views (e.g. in update.js.erb) this way:
<% if @product.saved_change_to_attribute?(:name) %>
alert("Name changed!")
<% end %>
In my controller I have:
class ProductsController < ApplicationController
def update
@product = Product.find(params[:id])
respond_to do |format|
if @product.update(product_params)
format.js { render(:action => :show) }
else
format.js { render(:action => :update) }
end
end
end
private
def product_params
params.require(:product).permit(:price)
end
end
In my model I have:
class Product < ApplicationRecord
after_update :something_that_clears_changed_attributes
private
def something_that_clears_changed_attributes
...
self.reload
end
end
In the above example, the alert("Name changed!")
would be never fired.
In fact, it seems that if during the "update flow" (within the controller) there are "after callbacks" (at model level) that reload the object or further update or save it, then you cannot rely anymore on Dirty. That is, Dirty methods can return "unexpected" values because the object is "manipulated" during the flow.
This would be the case for models that use gems that reload, update or save the object multiple times within callbacks, and so "invalidate" the Dirty model during the flow (even the attribute_before_last_save
method in Rails 5 would return "unexpected" values).
To solve the issue, you could use the first example in this post (by keeping – before update – the changing attributes within a variable for later use) but, perhaps, there is a better way to use Dirty models.
Any idea on how to rely on Dirty models when during the flow there are multiple reloads, updates, saves or others that clear changed attributes?