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?

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