Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding id on create in ActiveRecord

People also ask

Can you use ActiveRecord without rails?

One of the primary aspects of ActiveRecord is that there is very little to no configuration needed. It follow convention over configuration. ActiveRecord is commonly used with the Ruby-on-Rails framework but you can use it with Sinatra or without any web framework if desired.

Is ActiveRecord an ORM?

ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code. When you need to make changes to the database, you'll write Ruby code, and then run "migrations" which makes the actual changes to the database.

What is ActiveRecord naming convention?

Active Record uses naming conventions for the columns in database tables, depending on the purpose of these columns. Foreign keys - These fields should be named following the pattern singularized_table_name_id (e.g., item_id , order_id ).

What does ActiveRecord base mean?

ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending.


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.


You could also use something like this:

Post.create({:id => 10, :title => 'Test'}, :without_protection => true)

Although as stated in the docs, this will bypass mass-assignment security.


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.


For Rails 4:

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

Other Rails 4 answers did not work for me. Many of them appeared to change when checking using the Rails Console, but when I checked the values in MySQL database, they remained unchanged. Other answers only worked sometimes.

For MySQL at least, assigning an id below the auto increment id number does not work unless you use update_column. For example,

p = Post.create(:title => 'Test')
p.id
=> 20 # 20 was the id the auto increment gave it

p2 = Post.create(:id => 40, :title => 'Test')
p2.id
=> 40 # 40 > the next auto increment id (21) so allow it

p3 = Post.create(:id => 10, :title => 'Test')
p3.id
=> 10 # Go check your database, it may say 41.
# Assigning an id to a number below the next auto generated id will not update the db

If you change create to use new + save you will still have this problem. Manually changing the id like p.id = 10 also produces this problem.

In general, I would use update_column to change the id even though it costs an extra database query because it will work all the time. This is an error that might not show up in your development environment, but can quietly corrupt your production database all the while saying it is working.