Luis Correa d''Almeida
2010-Jul-28 23:44 UTC
ActiveRecord associations seem to assume primary keys are always integers
Beyond issues in migrations (http://groups.google.com/group/ rubyonrails-core/browse_thread/thread/ cf8ae1f3e26b96f2/4ea93be5e77aed92?lnk=gst&q=primary +key#4ea93be5e77aed92) ActiveRecord (3.0.0beta4) associations seem to assume a primary key is always meant to be an integer. For instance, the following will fail. Assuming records with primary keys "uid1", "uid2", and "uid3" exist and are of the expected type (Medium), @flashbck.medium_ids = ["uid1", "uid2", "uid3"] will fail. Trace below ActiveRecord::AssociationTypeMismatch (Medium(#13305080) expected, got NilClass(#645570)): /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ lib/active_record/associations/association_proxy.rb:258:in `raise_on_type_mismatch'' /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ lib/active_record/associations/association_collection.rb:347:in `replace'' /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ lib/active_record/associations/association_collection.rb:347:in `each'' /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ lib/active_record/associations/association_collection.rb:347:in `replace'' /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ lib/active_record/associations.rb:1417:in `media='' /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ lib/active_record/associations.rb:1423:in `send'' /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ lib/active_record/associations.rb:1423:in `medium_ids='' /Users/luis/Projects/flashbck/app/controllers/ flashbcks_controller.rb:22:in `create'' NilClass is the result of Medium.find(0) as opposed to Medium.find("uid1"). This happens because the ids are converted to integers, below. Looking into associations.rb (http://github.com/rails/rails/blob/ master/activerecord/lib/active_record/associations.rb around line 1430) the following looks suspicious. def collection_accessor_methods(reflection, association_proxy_class, writer = true) collection_reader_method(reflection, association_proxy_class) if writer define_method("#{reflection.name}=") do |new_value| # Loads proxy class instance (defined in collection_reader_method) if not already loaded association = send(reflection.name) association.replace(new_value) association end define_method("#{reflection.name.to_s.singularize}_ids=") do |new_value| ids = (new_value || []).reject { |nid| nid.blank? }.map(&:to_i) send("#{reflection.name}=", reflection.klass.find(ids).index_by(&:id).values_at(*ids)) end end end The following line calls to_i on all ids. ids = (new_value || []).reject { |nid| nid.blank? }.map(&:to_i) This does not seem to be expected behavior. I was under the impression that non-integer based primary keys were supported by activerecord. Any thoughts? -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Robert Pankowecki
2010-Jul-29 06:29 UTC
Re: ActiveRecord associations seem to assume primary keys are always integers
On Thu, Jul 29, 2010 at 1:44 AM, Luis Correa d''Almeida <luis.ca@gmail.com> wrote:> Beyond issues in migrations (http://groups.google.com/group/ > rubyonrails-core/browse_thread/thread/ > cf8ae1f3e26b96f2/4ea93be5e77aed92?lnk=gst&q=primary > +key#4ea93be5e77aed92) ActiveRecord (3.0.0beta4) associations seem to > assume a primary key is always meant to be an integer. > > For instance, the following will fail. Assuming records with primary > keys "uid1", "uid2", and "uid3" exist and are of the expected type > (Medium), > > @flashbck.medium_ids = ["uid1", "uid2", "uid3"] > > will fail. Trace below > > ActiveRecord::AssociationTypeMismatch (Medium(#13305080) expected, got > NilClass(#645570)): > /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ > lib/active_record/associations/association_proxy.rb:258:in > `raise_on_type_mismatch'' > /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ > lib/active_record/associations/association_collection.rb:347:in > `replace'' > /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ > lib/active_record/associations/association_collection.rb:347:in `each'' > /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ > lib/active_record/associations/association_collection.rb:347:in > `replace'' > /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ > lib/active_record/associations.rb:1417:in `media='' > /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ > lib/active_record/associations.rb:1423:in `send'' > /Users/luis/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta4/ > lib/active_record/associations.rb:1423:in `medium_ids='' > /Users/luis/Projects/flashbck/app/controllers/ > flashbcks_controller.rb:22:in `create'' > > NilClass is the result of Medium.find(0) as opposed to > Medium.find("uid1"). This happens because the ids are converted to > integers, below. > > Looking into associations.rb (http://github.com/rails/rails/blob/ > master/activerecord/lib/active_record/associations.rb around line > 1430) the following looks suspicious. > > > def collection_accessor_methods(reflection, > association_proxy_class, writer = true) > collection_reader_method(reflection, > association_proxy_class) > > if writer > define_method("#{reflection.name}=") do |new_value| > # Loads proxy class instance (defined in > collection_reader_method) if not already loaded > association = send(reflection.name) > association.replace(new_value) > association > end > > define_method("#{reflection.name.to_s.singularize}_ids=") > do |new_value| > ids = (new_value || []).reject { |nid| > nid.blank? }.map(&:to_i) > send("#{reflection.name}=", > reflection.klass.find(ids).index_by(&:id).values_at(*ids)) > end > end > end > > The following line calls to_i on all ids. > > ids = (new_value || []).reject { |nid| nid.blank? }.map(&:to_i) > > This does not seem to be expected behavior. I was under the impression > that non-integer based primary keys were supported by activerecord. > Any thoughts?https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/5125-collection_singular_ids-method-raises-an-exception-when-primary_key-is-string-rails-3 There is patch for this issue. You might want to verify so it is applied faster. Robert Pankowecki -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.