i18n_alchemy
i18n_alchemy copied to clipboard
Exception when localize a model with polymorphic belongs to
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? :-)
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 ;)
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!
Any news on this one?
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!