Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rails 4.2.0 ActiveType::Object#save fails with ActiveModel::MissingAttributeError can't write unknown attribute `` #31

Closed
mattbrictson opened this issue Feb 9, 2015 · 15 comments

Comments

@mattbrictson
Copy link
Contributor

Update: this affects Rails 4.2.0 only. Rails 4.2.1 does not seem to be affected.

Scenario:

  • Class MyForm inherits from ActiveType::Object
  • @myform has validation errors
  • Controller calls @myform.save

Expectation:

  • @myform.save should return false, since the object is invalid

Bug:

Instead, I get this exception:

ActiveModel::MissingAttributeError can't write unknown attribute ``

Cause:

  1. When save is called and validation fails, ActiveRecord calls restore_transaction_record_state
  2. This in turn calls write_attribute(self.class.primary_key, restore_state[:id])
  3. But for an ActiveType::Object, primary_key is nil
  4. write_attribute doesn't expect a nil attribute name, so it blows up

Workaround:

I've worked around the bug by explicitly declaring a MyForm.primary_key. I'm not sure if this has other consequences, but it seems to work:

def self.primary_key
  :id
end

Here's the relevant stack trace:

ActiveModel::MissingAttributeError - can't write unknown attribute ``:
  activerecord (4.2.0) lib/active_record/attribute.rb:124:in `with_value_from_database'
  activerecord (4.2.0) lib/active_record/attribute_set.rb:39:in `write_from_user'
  activerecord (4.2.0) lib/active_record/attribute_methods/write.rb:74:in `write_attribute_with_type_cast'
  activerecord (4.2.0) lib/active_record/attribute_methods/write.rb:56:in `write_attribute'
  activerecord (4.2.0) lib/active_record/attribute_methods/dirty.rb:92:in `write_attribute'
  activerecord (4.2.0) lib/active_record/transactions.rb:393:in `restore_transaction_record_state'
  activerecord (4.2.0) lib/active_record/core.rb:514:in `update_attributes_from_transaction_state'
  activerecord (4.2.0) lib/active_record/core.rb:508:in `sync_with_transaction_state'
  activerecord (4.2.0) lib/active_record/persistence.rb:86:in `new_record?'
  activerecord (4.2.0) lib/active_record/persistence.rb:99:in `persisted?'
  actionview (4.2.0) lib/action_view/helpers/form_helper.rb:456:in `apply_form_for_options!'
  actionview (4.2.0) lib/action_view/helpers/form_helper.rb:434:in `form_for'
@vevisystems
Copy link

We were experienced the same problem, the suggested workaround works. Thanks for the hint

@treznick
Copy link

treznick commented Mar 9, 2015

+1

@triskweline
Copy link
Member

I'm afraid I can't reproduce the issue:

2.1.2 :001 > class Foo < ActiveType::Object
2.1.2 :002?>     attribute :flag, :boolean
2.1.2 :003?>     validates_presence_of :flag
2.1.2 :004?>   end
 => [ActiveModel::Validations::PresenceValidator] 
2.1.2 :005 > 
2.1.2 :006 >   
2.1.2 :007 >   foo = Foo.new(flag: false)
 => #<Foo > 
2.1.2 :008 > foo.save
   (0.1ms)  BEGIN
   (0.1ms)  ROLLBACK
 => false 

@mattbrictson
Copy link
Contributor Author

@henning-koch Sorry, my explanation was a bit misleading. The call to save works fine. The exception is encountered when the form is rendered again in the view after validation fails. Here's the stack trace for clarification. Notice the problem originates with form_for being called in the view.

ActiveModel::MissingAttributeError - can't write unknown attribute ``:
  activerecord (4.2.0) lib/active_record/attribute.rb:124:in `with_value_from_database'
  activerecord (4.2.0) lib/active_record/attribute_set.rb:39:in `write_from_user'
  activerecord (4.2.0) lib/active_record/attribute_methods/write.rb:74:in `write_attribute_with_type_cast'
  activerecord (4.2.0) lib/active_record/attribute_methods/write.rb:56:in `write_attribute'
  activerecord (4.2.0) lib/active_record/attribute_methods/dirty.rb:92:in `write_attribute'
  activerecord (4.2.0) lib/active_record/transactions.rb:393:in `restore_transaction_record_state'
  activerecord (4.2.0) lib/active_record/core.rb:514:in `update_attributes_from_transaction_state'
  activerecord (4.2.0) lib/active_record/core.rb:508:in `sync_with_transaction_state'
  activerecord (4.2.0) lib/active_record/persistence.rb:86:in `new_record?'
  activerecord (4.2.0) lib/active_record/persistence.rb:99:in `persisted?'
  actionview (4.2.0) lib/action_view/helpers/form_helper.rb:456:in `apply_form_for_options!'
  actionview (4.2.0) lib/action_view/helpers/form_helper.rb:434:in `form_for'

@mattbrictson
Copy link
Contributor Author

@henning-koch Here is a minimal Rails app the demonstrates the issue:

https://github.com/mattbrictson/active-type-31

To run the demo:

  1. Check out the repo
  2. bin/setup
  3. bin/rails server
  4. Visit http://localhost:3000

@jhirbour
Copy link

+1

@mattbrictson mattbrictson changed the title Rails 4.2 ActiveType::Object#save fails with ActiveModel::MissingAttributeError can't write unknown attribute `` Rails 4.2.0 ActiveType::Object#save fails with ActiveModel::MissingAttributeError can't write unknown attribute `` Mar 19, 2015
@mattbrictson
Copy link
Contributor Author

This is fixed in activerecord 4.2.1. I upgraded my test case from Rails 4.2.0 to 4.2.1 and the bug is no longer present.

@v-sh
Copy link

v-sh commented Apr 1, 2015

Thanks for the hint.

@thatandyrose
Copy link

Was about to shoot myself dead, thanks for this! 🔫 💩

@kvanderd
Copy link

kvanderd commented Jun 2, 2015

+1

@mattbrictson
Copy link
Contributor Author

Everyone who +1'd this issue: does upgrading to Rails 4.2.1 solve the problem for you? I.e. does it eliminate the need for the def self.primary_key workaround?

@kvanderd
Copy link

kvanderd commented Jun 3, 2015

Upgrading to Rails 4.2.1 solved this problem for me. Thank you for opening this issue and providing a solution.

@v-sh
Copy link

v-sh commented Jun 3, 2015

Yes, I just upgrade.

@mattbrictson
Copy link
Contributor Author

@kvanderd @v-sh thanks for confirming! Glad to hear it worked for you, too.

@triskweline
Copy link
Member

ActiveType 0.3.5 now refuses to load with ActiveRecord 4.2.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants