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

Exception when localize a model with polymorphic belongs to #18

Open
sobrinho opened this issue Jun 6, 2012 · 4 comments
Open

Exception when localize a model with polymorphic belongs to #18

sobrinho opened this issue Jun 6, 2012 · 4 comments

Comments

@sobrinho
Copy link
Contributor

sobrinho commented Jun 6, 2012

Hey mate,

Seems like we have a "integration" problem with active record and i18n alchemy but I'm not sure.

Just to you follow my production code, we can't accept nested attributes for polymorphic associations:

class Person < ActiveRecord::Base
  belongs_to :personable, :polymorphic => true

  accepts_nested_attributes_for :personable
end
Loading development environment (Rails 3.2.3)
irb(main):001:0> person = Person.new
=> #<Person ...>
irb(main):002:0> person.localized
=> #<Person ...>
irb(main):003:0> person.personable
=> nil
irb(main):004:0> person.assign_attributes(:personable_type => 'Company', :personable_attributes => { :cnpj => 'nohup' })
ArgumentError: Cannot build association personable. Are you trying to build a polymorphic one-to-one association?
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/nested_attributes.rb:339:in `assign_nested_attributes_for_one_to_one_association'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/nested_attributes.rb:288:in `personable_attributes='
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/attribute_assignment.rb:94:in `block in assign_attributes'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/attribute_assignment.rb:93:in `each'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/attribute_assignment.rb:93:in `assign_attributes'
    from (irb):4
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.3/lib/rails/commands/console.rb:47:in `start'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.3/lib/rails/commands/console.rb:8:in `start'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.3/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

It's ok, not the best solution but you can work around it:

class Person < ActiveRecord::Base
  belongs_to :personable, :polymorphic => true

  accepts_nested_attributes_for :personable

  def build_personable(attributes, options = {})
    self.personable = personable_type.constantize.new(attributes, options)
  end
end

And, it just works now:

Loading development environment (Rails 3.2.3)
irb(main):001:0> person = Person.new
=> #<Person ...>
irb(main):002:0> person.localized
=> #<Person ...>
irb(main):003:0> person.personable
=> nil
irb(main):004:0> person.assign_attributes(:personable_type => 'Company', :personable_attributes => { :cnpj => 'nohup' })
=> nil
irb(main):005:0> person.personable
=> #<Company ...>

But, if we try to use localized version:

irb(main):006:0> person.localized.assign_attributes(:personable_type => 'Company', :personable_attributes => { :cnpj => 'nohup' })
NameError: uninitialized constant Person::Personable
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/inheritance.rb:119:in `compute_type'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/reflection.rb:172:in `klass'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/bundler/gems/i18n_alchemy-259277ade608/lib/i18n_alchemy/association_parser.rb:49:in `proxy'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/bundler/gems/i18n_alchemy-259277ade608/lib/i18n_alchemy/association_parser.rb:25:in `parse'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/bundler/gems/i18n_alchemy-259277ade608/lib/i18n_alchemy/attributes_parsing.rb:43:in `block in parse_attributes'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/bundler/gems/i18n_alchemy-259277ade608/lib/i18n_alchemy/attributes_parsing.rb:40:in `each'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/bundler/gems/i18n_alchemy-259277ade608/lib/i18n_alchemy/attributes_parsing.rb:40:in `parse_attributes'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/bundler/gems/i18n_alchemy-259277ade608/lib/i18n_alchemy/attributes_parsing.rb:12:in `assign_attributes'
    from (irb):6
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.3/lib/rails/commands/console.rb:47:in `start'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.3/lib/rails/commands/console.rb:8:in `start'
    from /Users/sobrinho/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.3/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

The alchemy offending code is that:

def proxy
  @proxy ||= @association.klass.new.localized
end

This won't work because polymorphic associations do not have the class defined.

I'm not sure about using build_#{association_name} because we will mutate the object, but maybe that is expected if we are receiving the #{association_name}_attributes in a localized proxy.

Anyway, I need this polymorphic association to be assigned localized.

Thoughts? :-)

@sobrinho
Copy link
Contributor Author

sobrinho commented Jun 6, 2012

I forgot, we are workarounding this issue using that bizarre code:

class Person < ActiveRecord::Base
  belongs_to :personable, :polymorphic => true

  accepts_nested_attributes_for :personable

  def personable_attributes=(personable_attributes, options = {})
    self.personable ||= personable_type.constantize.new
    personable.localized.assign_attributes(personable_attributes, options)
  end
end

This version is more ugly than first option, do not work for all cases and assume we want localized version all the time but it's working for now ;)

caironoleto pushed a commit to caironoleto/i18n_alchemy that referenced this issue Jun 13, 2012
@carlosantoniodasilva
Copy link
Owner

I don't have an idea off the top of my head, but I'll try to search and think what can be done. Meanwhile if you want to send a failing test case, would help :). Thanks!

@sebastianludwig
Copy link

Any news on this one?

@carlosantoniodasilva
Copy link
Owner

Not actually, I haven't stopped to put much thought on it :)

I may have some time available to get back to it in a couple weeks, in the meanwhile any help would appreciated. Thanks!

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

3 participants