views:

1358

answers:

6

Is there any way of overriding a model's id value on create? Something like:

Post.create(:id => 10, :title => 'Test')

would be ideal, but obviously won't work.

A: 

I don't know if that would be posible, but I can think of two motivations, one is that you want to create the new model to be asociated with an existing one, in that case, you can use the other model collection methods, something like:

blog.posts.create(:title => "Test")

The other is that you need to use that field for some special function, I would strongly recommend against that, use a model method instead, like a virtual attribute, you only need to create the corresponding getter and setter. Think about what would happen if you need to migrate or recreate your db for some reason, depending on controlling the primary key is not a great idea.

Could you specify your objective?

krusty.ar
yes please clarification would be nice
Ryan Bigg
Please clarify your objective
aivarsak
A: 

I think you can try setting before_create to manually assign the id

before_create :set_id

private

def set_id
  self[:id] = id
end
Sikachu
+1  A: 

Try

a_post = Post.new do |p| 
  p.id = 10
  p.title = 'Test'
  p.save
end

that should give you what you're looking for.

PJ Davis
not sure why you're getting downvoted, this works great for me
semanticart
A: 

Actually, it turns out that doing the following works:

p = Post.new(:id => 10, :title => 'Test')
p.save(false)
Mr. Matt
+4  A: 

id is just attr_protected, which is why you can't use mass-assignment to set it. However, when setting it manually, it just works:

o = SomeObject.new
o.id = 8888
o.save!
o.reload.id # => 8888

I'm not sure what the original motivation was, but I do this when converting ActiveHash models to ActiveRecord. ActiveHash allows you to use the same belongs_to semantics in ActiveRecord, but instead of having a migration and creating a table, and incurring the overhead of the database on every call, you just store your data in yml files. The foreign keys in the database reference the in-memory ids in the yml.

ActiveHash is great for picklists and small tables that change infrequently and only change by developers. So when going from ActiveHash to ActiveRecord, it's easiest to just keep all of the foreign key references the same.

+1  A: 

As Jeff points out, id behaves as if is attr_protected. To prevent that, you need to override the list of default protected attributes. Be careful doing this anywhere that attribute information can come from the outside. The id field is default protected for a reason.

class Post < ActiveRecord::Base

  private

  def attributes_protected_by_default
    []
  end
end

(Tested with ActiveRecord 2.3.5)

Nic Benders