The situation
I want an "id" column, but I don't want it to be a primary key,
and I want full control over its population.
Steps to reproduce
create_table :people, :id => false do |t|
t.integer :id
t.timestamps
end
>> Person.primary_key
=> "id"
Problem #1 - Person should not have any primary key,
clearly, from the schema dump:
CREATE TABLE "people" ("id" integer, "created_at" datetime,
"updated_at" datetime);
That leads to Problem #2:
>> Person.create(:id => 123)
=> #<Person id: 1, created_at: "2009-01-22 06:31:43", updated_at: "2009-01-22 06:31:43">
Using constructor syntax #create or #new,
#attributes_from_column_definition is used and the "id" column is
filtered out because it's thought of (incorrectly) as the primary
key.
If you use the block creation syntax like:
person = Person.new do |p|
p.id = 123
end
person.save
Then you get id correctly set to 123. So the behavior is
inconsistent.
Conclusion
If possible, ActiveRecord should not consider a column as being
a primary key unless the DB layer says so. Currently it falls back
on the string "id".
I'm not sure if you can "set_primary_key null" in the
ActiveRecord model, but that might be a valid workaround if we
can't rely on the DB layer. In the case of a workaround, it should
be documented alongside AR::CA::SS#create_table to let people know
they should explicitly set the primary key to null (or whatever) if
they expect to use a column called "id".