mea*_*eah 4 ruby-on-rails ruby-on-rails-3 rails-activerecord
@user = User.new 
@user.id返回nil,但我需要知道它才能保存.可能吗 ?
Dou*_*las 11
是的你可以!
我有同样的问题并调查了文档.解决这个问题的能力实际上与您的数据库类型密切相关.
Oracle和Postgresql确实有很多有用的功能来轻松解决这个问题.对于MySQL(oracle)或SkySQL(开源),它似乎更复杂(但仍然可能).如果您需要高级数据库工具,我建议您避免使用这些(MySQL/SkySQL)数据库.
首先,您必须尽可能避免在应用程序设计中避免这种情况,因为在保存之前使用ID是危险的.
可能存在以下情况:您没有任何其他选择:例如,当两个表引用自身时,出于安全原因,您不允许在这些表上使用DELETE或UPDATE.
在这种情况下,您可以使用(PostgreSQL,Oracle)数据库nextval函数生成下一个ID号,而无需实际插入新记录.
将它与find_by_sql rails方法结合使用.
例如,要使用postgreSQL和Rails执行此操作,请选择一个rails模型并添加类方法(而不是实例方法!).这可以通过方法名称开头的" self "字来实现. self告诉Ruby这个方法只能由类使用,而不能由实例变量(用'new'创建的对象)使用.
我的Rails模型:
class MyToy < ActiveRecord::Base
...
  def self.my_next_id_sequence
    self.find_by_sql "SELECT nextval('my_toys_id_seq') AS my_next_id"
  end
end
当您使用Rails迁移生成表时,默认情况下,Rails会自动创建一个名为id的列,并将其设置为主键的表.为了确保您没有得到任何" 重复的主键错误 ",Rails会自动在数据库中创建一个序列并将其应用于id列.对于您在表中插入的每个新记录(行),数据库将自行计算新记录的下一个ID.
Rails自动命名此序列,表名附加"_id_seq".为解释PostgreSQL的NEXTVAL函数必须应用于这个序列在这里.
现在关于find_by_sql,如这里所解释的,它将创建一个 包含类的新对象实例的数组.每个对象都将包含SQL语句生成的所有列.这些列将以属性的形式出现在每个新对象实例中.即使您的类模型中不存在这些属性!
正如您明智地意识到的那样,我们的nextval函数只返回一个值.因此,find_by_sql将创建一个包含具有单个属性的单个对象实例的数组.为了便于读取此属性的值,我们将使用"my_next_id"命名生成的SQL列,因此我们的属性将具有相同的名称.
就是这样了.我们可以使用我们的新方法:
my_resulting_array = MyToy.my_next_id_sequence
my_toy_object = my_resulting_array[0]
my_next_id_value = my_toy_object.my_next_id
并使用它来解决我们的死锁情况:
my_dog = DogModel.create(:name => 'Dogy', :toy_id => my_next_id_value)
a_dog_toy = MyToy.new(:my_dog_id => my_dog.id)
a_dog_toy.id = my_next_id_value
a_dog_toy.save
请注意,如果您不使用my_next_id_value,则此ID号将永远丢失.(我的意思是,未来任何记录都不会使用它).
数据库不会等你使用它.如果在任何时候,您的应用程序需要在my_table_example中插入新记录(可能与我们正在使用my_next_id_sequence同时),数据库将始终在您生成的新记录之后立即为此新记录分配一个ID号my_next_id_sequence,考虑到你的my_next_id_value是保留的.这可能会导致my_table_example中的记录看起来没有按创建时间排序.
| 归档时间: | 
 | 
| 查看次数: | 8468 次 | 
| 最近记录: |