This project is archived and is in readonly mode.

#4203 new
Horace Ho

create and find_or_create_by behaves differently on model with no :id column

Reported by Horace Ho | March 17th, 2010 @ 09:01 AM

$ rails -v
Rails 2.3.5
$ rails tour
$ cd tour
$ script/generate model country code:string name:string --skip-timestamps

    class CreateCountries < ActiveRecord::Migration
      def self.up
        create_table :countries, :id => false do |t|
          t.string :code
          t.string :name
        end
      end

      def self.down
        drop_table :countries
      end
    end

$ rake db:migrate   
$ script/console
Loading development environment (Rails 2.3.5)
>> Country.create(:code => 'ZW', :name => 'Zimbabwe')
=> #<Country code: "ZW", name: "Zimbabwe">

define a primary key in country.rb:

class Country < ActiveRecord::Base
  set_primary_key :code
end
back to console:
>> reload!
Reloading...
=> true
>> Country.find_or_create_by_code('X1')
=> #<Country code: "X1", name: nil>
>> Country.create(:code => 'X2')
=> #<Country code: 2, name: nil>
>> Country.all
=> [#<Country code: "ZW", name: "Zimbabwe">, #<Country code: nil, name: nil>, #<Country code: "X1", name: nil>]
After "set_primary_key" is defined, Country.create no longer works. The :code field (primary key) of newly created records is a nil. find_or_create_by_code still works.

Comments and changes to this ticket

  • Alexey Nayden

    Alexey Nayden January 13th, 2011 @ 01:26 AM

    • Tag changed from :id primary_key to :id primary_key, 2.3.5, active_record
  • Alexey Nayden

    Alexey Nayden January 14th, 2011 @ 12:10 AM

    • Tag changed from :id primary_key, 2.3.5, active_record to :id primary_key, 2.3.5, active_record, invalid

    @Horace actually AR always marks primary key column as attr_protected, so you're unable to mass-assign it with hash in #create. If you try to activate logging to stdout ActiveRecord::Base.logger = Logger.new(STDOUT) you'll get an error message regarding mass-assignment protected attribute. So in your case you're trying to create a record without PK column set to any value. And due to your database inconsistency in that example (i.e. PK insn't NOT NULL and UNIQUE as it always should), DB allows you to create such invalid record. If you set DB constraints for PK, you'd get an error — all correct.

    That's it.

  • Alexey Nayden

    Alexey Nayden January 14th, 2011 @ 12:11 AM

    And, of course, your example is obviously fixed with "c = Country.new; c.code = 'X2'; c.save"

  • bingbing

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

People watching this ticket

Pages