Why does activerecord not populate the auto-increment column in the item returned from create?

Why don't the rails fill the auto-increment column in the element returned from create? Is there a better way to do this?

In rails, when you execute a = Foo.create , then a.id filled

But if you have a field that was created through

 def up execute "ALTER TABLE my_table ADD COLUMN my_auto_incrementing_column INTEGER AUTO_INCREMENT not null UNIQUE KEY;" end 

Then this field does not appear when using create. You must also use reboot.

 a = Foo.create a.id # not nil a.my_auto_incrementing_column # nil a.reload a.my_auto_incrementing_column # is now populated 

Version Information:

 $ ruby -v ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-darwin14.5.0] $ bundle exec rails -v Rails 3.2.12 $ mysql --version mysql Ver 14.14 Distrib 5.6.26, for osx10.10 (x86_64) using EditLine wrapper 

Some background:

This code applies to a large rails existing in the production database, which requires all id fields to be UUID. The auto_increment column is not a primary key because it was added after we discovered that the new external integration partner could not process our existing long unique identifiers (UUIDs).

We are working hard to update our version of ruby, but we do not want to wait for this as a solution to this problem. Also, after reading the changelogs in activerecord, I still have no evidence that any future version of ruby ​​/ rails will contain a fix for this problem.

The code I want to improve is:

 class Foo < ActiveRecord::Base has_one :object_containing_auto_incrementing_column def my_method if self.object_containing_auto_incrementing_column.nil? self.object_containing_auto_incrementing_column = ObjectContainingAutoIncrementingColumn.create(owner: self) self.object_containing_auto_incrementing_column.reload end self.object_containing_auto_incrementing_column.my_auto_incrementing_column end end 
+7
ruby mysql ruby-on-rails activerecord
source share
1 answer

After looking at the source code, it doesn’t appear that ActiveRecord is trying to populate automatically growing columns. It assigns the value returned by the INSERT to the #id attribute and nothing else.

  # ActiveRecord:: Persistence::ClassMethods def create # ... self.id ||= new_id if self.class.primary_key # ... end 

If you want to populate my_auto_incrementing_column without going into a double DB, I think that there is no fix for ActiveRecord itself.

See how the insertion method is implemented:

  # Returns the last auto-generated ID from the affected table. # # +id_value+ will be returned unless the value is nil, in # which case the database will attempt to calculate the last inserted # id and return that value. # # If the next id was calculated in advance (as in Oracle), it should be # passed in as +id_value+. def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) sql, binds = sql_for_insert(to_sql(arel, binds), pk, id_value, sequence_name, binds) value = exec_insert(sql, name, binds) id_value || last_inserted_id(value) end 

Perhaps there is no trivial way to change the current API to populate your field.

+2
source share

All Articles