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