Closed hspindell closed 6 years ago
That is acceptable ruby as your are modifying a field value by reference (self-mutating) and intentionally bypassing dirty tracking. In your example, you are not invoking dirty tracking methods manually when calling ruby mutating methods.
See ActiveModel documentation: http://api.rubyonrails.org/classes/ActiveModel/Dirty.html
If an attribute is modified in-place then make use of [attribute_name]_will_change! to mark that the attribute is changing. Otherwise Active Model can't track changes to in-place attributes.
In your example 1, while m.content
is now "interesting"
using the mutating method gsub!
, it never calls the dirty tracking system. You will need to call m.content_will_change!
before you mutate the internal value. In Example 2, the reason dirty tracking is working is because you are using the method content=
, which internally triggers dirty tracking on your behalf by ActiveModel.
When dealing with mutating methods, you should trigger dirty tracking yourself to let the system know that the underlying value will change:
m.content # => "interesting..."
m.content_will_change! # => "interesting" (dirty tracking manually invoked)
m.content.gsub!("...","") # => "interesting"
m.content_changed? # => true
m.changed_attributes # => {'content' => "interesting..."} (original value)
m.changes # => {"content"=>["interesting...", "interesting"]}
Example 1 with gsub! :
Example 2 with gsub (non-modifying):
Or if this is intended, what's the reasoning for it?