Skip to content
This repository has been archived by the owner on Dec 23, 2024. It is now read-only.

Fix Rails 4.2 "can't modify frozen hash ActiveSupport::HashWithIndifferentAccess" #26

Closed
wants to merge 1 commit into from
Closed

Fix Rails 4.2 "can't modify frozen hash ActiveSupport::HashWithIndifferentAccess" #26

wants to merge 1 commit into from

Conversation

stevenschobert
Copy link
Contributor

@stevenschobert stevenschobert commented May 31, 2016

Looks like in rails 4.2, the changed_attributes method returns a frozen hash when no attributes have changed, which raises an error when we try to delete keys from it.

Looks like other libraries have used the internal instance variable directly (mbleigh/acts-as-taggable-on#583) to access the mutable copy.

Our tests didn't catch it because the audit spec is based on a stubbed class. To add in a quick safe-guard, I added a spec that runs the audit against our built in User model. Since the Audit module is available to all of ActiveRecord, it gets tested indirectly.

Test Case:

describe "with an real model subclass" do
  it "should not raise an error if nothing has changed" do
    expect { User.new.send(:initialize_dup, nil) }.to_not raise_error
  end
end
1) Challah::Audit with an real model subclass should not raise an error if nothing has changed
   Failure/Error: expect { stub.send(:initialize_dup, nil) }.to_not raise_error

     expected no Exception, got #<RuntimeError: can't modify frozen ActiveSupport::HashWithIndifferentAccess> with backtrace:
       # ./lib/challah/audit.rb:99:in `block in clear_audit_attributes'
       # ./lib/challah/audit.rb:94:in `each'
       # ./lib/challah/audit.rb:94:in `clear_audit_attributes'
       # ./lib/challah/audit.rb:39:in `initialize_dup'
       # ./spec/lib/audit_spec.rb:109:in `block (4 levels) in <module:Challah>'
       # ./spec/lib/audit_spec.rb:109:in `block (3 levels) in <module:Challah>'
   # ./spec/lib/audit_spec.rb:109:in `block (3 levels) in <module:Challah>'

in rails 4.2, the #changed_attributes method returns
a frozen hash when no attributes have changed, which
causes -> “can't modify frozen ActiveSupport::HashWithIndifferentAccess”
@stevenschobert
Copy link
Contributor Author

@jdtornow looks like this change is failing in rails 5 beta, i'll dig into it. if you have thoughts in the mean time let me know!

@jdtornow
Copy link
Owner

jdtornow commented Jun 2, 2016

Hey @stevenschobert thanks for finding this one!

See if this commit works in your local testing (works and passes tests on this end): 73ed0ca

Instead of modifying the hash (and therefore throwing those frozen errors) I switched it to just remove those keys in a reduce and return a new hash instead. I also changed the stub class to have a changed_attributes instance method just like in Rails itself. Seemed cleaner that way.

@stevenschobert
Copy link
Contributor Author

@jdtornow yep that commit works locally for me! I figured you'd have a better refactor in mind 👍

@jdtornow
Copy link
Owner

jdtornow commented Jun 3, 2016

Sweet thanks! I merged this into master from my other branch I changed. Will push a new version shortly :)

@jdtornow jdtornow closed this Jun 3, 2016
@stevenschobert stevenschobert deleted the fix-audit-error-rails-4-2 branch June 3, 2016 05:10
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants