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