ActiveRecord keeps returning 1 as the Model's id

I am doing a find:

merchant = Merchant.find(:first, :conditions => c, :readonly => false)

I keep getting "id"=>"1" for every single model that is returned.

Since the id is always 1 I can't do merchant.save without getting errors.

Anyone have any ideas as to why this is happening?

well, yeah, cos you’re telling it to find the first one. What are you actually trying to find?

Not sure that's the problem here... it should return the first record that matches the conditions. That record could have an id of 1 however.

ice5nake: You haven't provided enough information. What errors are you getting when you call save? What are you trying to do? What is your database and migration for this model?

How do I get the actual id of the returned record to be the id in the model instance? While this may make sense to an experienced Rails developer I find this most peculiar that the id is not in fact the actual id of the record returned.

It is failing on unique validations because, as I suspect, it may be trying to update the record with id = 1, when in fact the code is designed to be updating the record where the unique conflict exists.

Does the :first parameter always return 1 as the id?

First of all the id of the model instance should be the id in the database. Second, the :first parameter just returns the first record that matches the conditions supplied. If there are no conditions, then it will always return the record that has id equal to 1.

You should be able to update that record and save it without errors.

What happens when you do Merchant.find(2).id? (it should be 2)

We kind of need more information though, so post up as much code as you can.

This is most peculiar. It's definitely returning the correct information with the exception of the id. import_xml_merchant is called from a loop. All the merchants have the correct information with the exception of the id which is always equal to 1.

Here's an inspect dump of the model. #<Merchant:0xe9833bc @attributes={"status"=>"1", "created_on"=>"2007-10-05 11:13:31", "name"=>"RollerHockey.com", "url"=>"http://www.rollerhockey.com", "deals_count"=>"86", "id"=>"1", "current_deals_count"=>"0", "merchant_id_from_deal_source"=>"K154803"}, @unsaved=false, @errors=#<ActiveRecord::Errors:0xe95b1c8 @errors={"name"=>["already exists"], "url"=>["already exists"]}, @base=#<Merchant: 0xe9833bc ...>>>

#<Merchant:0xe9eeaf4 @attributes={"status"=>"1", "created_on"=>"2007-10-05 11:13:31", "name"=>"Verizon Wireless", "url"=>"http://www.verizonwireless.com", "deals_count"=>"86", "id"=>"1", "current_deals_count"=>"0", "merchant_id_from_deal_source"=>"K8669"}, @unsaved=false, @errors=#<ActiveRecord::Errors:0xe9bc194 @errors={"name"=>["already exists"], "url"=>["already exists"]}, @base=#<Merchant: 0xe9eeaf4 ...>>>

def import_xml_merchant(m)       if !@merchants.has_key?(m['merchantName'].text)         c = Array.new         c[0] = " 0=0 "         unless m['merchantName'].nil?           c[0] += " OR name = ? "           c << m['merchantName'].text         end         unless m['merchantUrl'].nil?           c[0] += " OR url = ? "           c << m['merchantUrl'].text         end         unless m['merchant_id_from_deal_source'].nil?           c[0] += " OR merchant_id_from_deal_source = ? "           c << m['merchant_id_from_deal_source'].text         end         merchant = Merchant.find(:all, :conditions => c, :limit => 1, :readonly => false)         if (merchant.empty?)           #Merchant not in system, create a new merchant           merchant = Merchant.new(:name => "#{m['merchantName'].text}")           @new_merchants.push(merchant)         else           merchant = merchant.pop         end         merchant.id = merchant.id_before_type_cast         merchant.merchant_id_from_deal_source = "#{m['merchant_id_from_deal_source'].text}" unless m['merchant_id_from_deal_source'].nil?()         unless m['merchantUrl'].nil?           merchant.url = "#{m['merchantUrl'].text}" unless m['merchantUrl'].text.nil?         end         merchant.name = "#{m['merchantName'].text}" unless m['merchantName'].nil?()         merchant.save         @merchants.store(merchant.name,merchant)         return merchant       else         return @merchants[m['merchantName'].text]       end     end

why this line?

merchant.id = merchant.id_before_type_cast

It is always going to return the record with id = 1if you have that 0=0 part of the conditions.

Thanks for everyone's help. This was a stupid mistake on my part. The first part of my condition was 0=0 follow by OR conditions, which would always return the first record.

Thanks for everyone's help. This was a stupid mistake on my part. The first part of my condition was 0=0 follow by OR conditions, which would always return the first record.

def import_xml_merchant(m)       if !...@merchants.has_key?(m['merchantName'].text)         c = Array.new         c[0] = " 0=0 "

just start with an array having an empty array:            c = []

        unless m['merchantName'].nil?           c[0] += " OR name = ? "

Then collect the fragments in the first element: c[0] << 'name = ?'

          c << m['merchantName'].text         end         unless m['merchantUrl'].nil?           c[0] += " OR url = ? "

c[0] << 'url = ?'

          c << m['merchantUrl'].text         end         unless m['merchant_id_from_deal_source'].nil?           c[0] += " OR merchant_id_from_deal_source = ? "

c[0] << 'merchant_id_from_deal_source = ?'

          c << m['merchant_id_from_deal_source'].text         end

and deal with multiple clauses at the end: c[0] = c[0].join(' OR ')

        merchant = Merchant.find(:all, :conditions => c, :limit => 1, :readonly => false)         if (merchant.empty?)           #Merchant not in system, create a new merchant           merchant = Merchant.new(:name => "#{m['merchantName'].text}")           @new_merchants.push(merchant)         else           merchant = merchant.pop         end         merchant.id = merchant.id_before_type_cast         merchant.merchant_id_from_deal_source = "#{m['merchant_id_from_deal_source'].text}" unless m['merchant_id_from_deal_source'].nil?()         unless m['merchantUrl'].nil?           merchant.url = "#{m['merchantUrl'].text}" unless m['merchantUrl'].text.nil?         end         merchant.name = "#{m['merchantName'].text}" unless m['merchantName'].nil?()         merchant.save         @merchants.store(merchant.name,merchant)         return merchant       else         return @merchants[m['merchantName'].text]       end     end

That will at least fix your conditions problem.

-Rob

Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com