com*_*ird 8 ruby mysql activerecord ruby-on-rails
为什么rails不会在create中返回的项中填充自动递增列?有一个更好的方法吗?
在轨道,当你这样做a = Foo.create,然后a.id填充
但是如果你有一个通过创建的字段
def up   
  execute "ALTER TABLE my_table ADD COLUMN my_auto_incrementing_column INTEGER AUTO_INCREMENT not null UNIQUE KEY;"
end
然后,当您使用create时,该字段不会出现.你也必须使用重装.
a = Foo.create
a.id # not nil
a.my_auto_incrementing_column # nil
a.reload
a.my_auto_incrementing_column # is now populated
版本信息:
$ 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
一些背景:
此代码适用于大型现有生产中的rails代码库,该代码库要求所有id字段都是UUID.auto_increment列不是主键,因为它是在我们发现新的外部集成伙伴无法使用我们现有的长唯一标识符(UUID)处理后添加的.
我们正在努力更新我们的ruby版本,但我们不想等待它作为解决此问题的方法.此外,在读取activerecord中的更改日志后,我仍然没有证据表明任何未来版本的ruby/rails将包含此问题的错误修复程序.
我要改进的代码:
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
查看源代码后,似乎没有 ActiveRecord 尝试填充自动递增列。它只将INSERT语句返回的值分配给#id属性,而不分配其他任何值。
 # ActiveRecord:: Persistence::ClassMethods
 def create
 # ...
   self.id ||= new_id if self.class.primary_key
 # ...
 end
如果您想在my_auto_incrementing_column不两次击中 DB的情况下进行填充,我认为没有办法修补 ActiveRecord 本身。
看看insert方法是如何实现的:
  # 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
可能没有任何简单的方法可以更改当前 API 以填充您的相关字段。
| 归档时间: | 
 | 
| 查看次数: | 313 次 | 
| 最近记录: |