stex / setting_accessors

Global key-value-store and database-persisted attribute accessors

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rails 5 Compatability: Set `#changed?` to false if setting was changed

Haniyya opened this issue · comments

Since rails 5, update_attribute has changed insofar as the changes are only persisted if #changed? is true. Since #changed? is only influenced by changing attributes, changed settings are therefore ignored.

Solution:

One solution could be to mirror normal activerecord behavior and introduce a changed_settings method that gets updated on each write action for a setting. Then #changed? could be overridden like

def changed?
  changed_settings.present? || super
end

This might introduce unforeseeable side effects though since changed? is used heavily in rails itself.

This is from now on covered by tests for future versions:

>> BUNDLE_GEMFILE=/Users/stex/workspace/gems/setting_accessors/gemfiles/rails_4.2.gemfile bundle exec rake
............................................................

Finished in 0.66373 seconds (files took 0.7149 seconds to load)
60 examples, 0 failures

>> BUNDLE_GEMFILE=/Users/stex/workspace/gems/setting_accessors/gemfiles/rails_5.0.gemfile 
...........F................................................

Failures:

  1) SettingAccessors::Integration#save when only a setting was changed using #update_attribute persists the record accordingly
     Failure/Error: expect(TestModel.find(record.id).send(attribute_name)).to eql 'Poiski'

       expected: "Poiski"
            got: "string_setting_value"

       (compared using eql?)
     Shared Example Group: "attribute update and touch" called from ./spec/lib/setting_accessors/integration_spec.rb:114
     Shared Example Group: "attribute setter variations" called from ./spec/lib/setting_accessors/integration_spec.rb:129
     # ./spec/lib/setting_accessors/integration_spec.rb:93:in `block (4 levels) in <top (required)>'

Addendum: From AR 5.1 this gets worse as the internal #_update method actually checks whether the attributes we pass in are table columns or not. This means, if only a setting and no attribute is updated through e.g. update_attributes, nothing will happen.