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?