This project is archived and is in readonly mode.
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 January 13th, 2011 @ 01:26 AM
- Tag changed from :id primary_key to :id primary_key, 2.3.5, active_record
-
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 January 14th, 2011 @ 12:11 AM
And, of course, your example is obviously fixed with "c = Country.new; c.code = 'X2'; c.save"
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>