eragone
eragone

Reputation: 555

Rails update_attributes trying to insert id column

I have a model:

class MyModel < ActiveRecord::Base
  has_many :other_things
  accepts_nested_attributes_for :other_things
  attr_accessible :other_things_attributes
end

class OtherThing < ActiveRecord::Base
  belongs_to :my_model
  attr_accessible :foo
end

When trying to update_attributes on a MyModel instance, Rails/ActiveRecord tries to insert null into the id column:

my_instance = MyModel.first
my_instance.update_attributes({
  "other_things_attributes"=> {
    "1357758179583" => {"foo"=>"bar", "_destroy"=>"false"},
    "1357758184445" => {"foo"=>"thing", "_destroy"=>"false"}
  }
})

That fails, with:

  SQL (0.5ms)  INSERT INTO "other_things" ("created_at", "my_model_id", "id", "updated_at", "foo") VALUES ($1, $2, $3, $4, $5)  [["created_at", Wed, 09 Jan 2013 14:30:33 EST -05:00], ["my_model_id", 8761], ["id", nil], ["updated_at", Wed, 09 Jan 2013 14:30:33 EST -05:00], ["foo", "bar"]]
   (0.1ms)  ROLLBACK 
ActiveRecord::StatementInvalid: PGError: ERROR:  null value in column "id" violates not-null constraint
: INSERT INTO "other_things" ("created_at", "my_model_id", "id", "updated_at", "foo") VALUES ($1, $2, $3, $4, $5)

Schema showing other_things:

  create_table "other_things", :force => true do |t|
    t.string   "foo"
    t.integer  "my_model_id"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end

What this doesn't show is the primary key constraint (or lackthereof) which was the underlying issue.

Upvotes: 1

Views: 876

Answers (2)

ssuljic
ssuljic

Reputation: 1081

Had similar problem which I solved by using update_columns instead of update_attributes. Hope that it will help someone. :)

Upvotes: 0

eragone
eragone

Reputation: 555

This was caused by somehow losing the primary key specification on the other_things table. I determined this because I had to separate instances (staging and production) where it worked in one but not the other; after comparing code and Rails-related issues, I decided to diff the DB schemas, which showed me the missing primary key constraint. Clearly, Rails uses the primary keys to identify the proper column; intuitively obvious, but not if you don't already know it in my opinion. Thanks for the comments!

ALTER TABLE ONLY other_things ADD CONSTRAINT other_things_pkey PRIMARY KEY (id);

Upvotes: 1

Related Questions