Ruby on rails 在保存之前获取Rails模型的ID。。。?
如何在保存rails模型之前获取其id 例如,如果我创建了一个新的模型实例,如何在保存它之前获取它的IDRuby on rails 在保存之前获取Rails模型的ID。。。?,ruby-on-rails,Ruby On Rails,如何在保存rails模型之前获取其id 例如,如果我创建了一个新的模型实例,如何在保存它之前获取它的ID 我知道id是在保存时根据数据库创建的,但是有解决方法吗?使用默认的Rails约定,即自动递增的整数主键,无法在保存之前获取模型的id,因为它是在相关表中插入新行时由RDBMS生成的 你到底想解决什么问题?我认为没有任何解决办法,因为id实际上是由数据库本身生成的。在将对象保存到数据库之前,该id不应可用 通常,当人们认为他们需要这样做时,他们实际上不需要这样做。正如John所说,解释一下你想
我知道id是在保存时根据数据库创建的,但是有解决方法吗?使用默认的Rails约定,即自动递增的整数主键,无法在保存之前获取模型的id,因为它是在相关表中插入新行时由RDBMS生成的
你到底想解决什么问题?我认为没有任何解决办法,因为id实际上是由数据库本身生成的。在将对象保存到数据库之前,该id不应可用 通常,当人们认为他们需要这样做时,他们实际上不需要这样做。正如John所说,解释一下你想做什么,也许有人可以建议一种方法,而不必事先知道id。我在创建数据导入器时遇到了类似的情况。我正在创建一组不同类型的记录,并在保存之前将它们关联起来。保存时,某些记录抛出验证错误,因为它们验证了尚未保存的记录是否存在 如果您使用的是postgres,active record会通过在数据库中保留名为models_id_seq(sales_id_seq for Sale等)的序列来增加它分配给模型的id。您可以获取此序列中的下一个id,并使用以下函数将其递增
def next_model_id
ActiveRecord::Base.connection.execute("SELECT NEXTVAL('models_id_seq')").first["nextval"].to_i
end
但是,这种解决方案不是一种好的做法,因为不能保证活动记录将来会以这种方式保留id序列。如果在我的项目中只使用过一次,为我节省了大量的工作,并且在为什么不应该经常使用它方面有很好的文档记录,我才会使用它。我也在寻找这个,我找到了一个答案: 假设模型名为“model”,表名为“models” model.rb
before_save {
next_id=Model.connection.select_value("Select nextval('models_id_seq')")
}
这将输出您的记录保存后id的值我知道这是一个老问题,但如果有人需要引用,也可以抛出我的答案 用户模型
class User < ActiveRecord::Base
before_create :set_default_value
def set_default_value
self.value ||= "#{User.last.id+1}"
end
class用户
在创建实例后立即考虑执行所需操作
after_create do
print self.id
end
这不是一个Rails问题,而是一个数据库问题。这是一个在任何web应用程序框架中都会出现的问题,解决方案在所有地方都是相同的。您必须使用数据库事务 基本流程将如下所示
- 打开交易
- 保存您的模型
- 使用数据库分配的ID
- 如果事实证明您实际上不想将此模型保留在数据库中,请回滚事务
- 如果您希望将模型保留在数据库中,请提交事务
从这种方法中,您会注意到,您回滚事务的id中会有间隙。大多数情况下,当我需要id时,可以将id分组到短列表中。 通过创建嵌套关联或关联的连接时。 假设我们有:
:user
通过:user\u pets
关联,我们将保存它们的类型
如果我们有一个正确配置的“has_many:through Association”,我们就可以
User.pets.create(name:“Rex”)
但这太简单了,因为我们要创建:pet
键入:User\u pets
u = User.create(name: "Cesar")
u.id # => 1 # works fine
p = u.pets.create(name: 'Rex')
# => rails will create UserPets => {id: 1, user_id: 1, pet_id: 1} for us
# But now we have a problem, how do we find :user_pets of our :pet?
# remember we still need to update the :type, the ugly (wrong) way:
up = p.user_pets.first
up.type = 'dog'
up.save! # working but wrong
# Do you see the problems here? We could use an id
P = Pet.new( name: "Destroyer" )
p.id # will not work, as the pet not saved yet to receive an id
up = UserPet.new( user_id: U.id, pet_id: p.id )
# => UserPet {id: 2, user_id: 1, pet_id: nil} # as we expected there is no id.
# What solutions do we have? Use nested creation!
# Good
up = UserPet.new(user_id: u.id, type: "dog")
# even better
up = u.user_pets.new(type: "dog")
# it's just a shortcut for the code above,
# it will add :user_id for us, so let's just remember it.
# Now lets add another 'new' from our creatd 'user_pet'
p = up.pets.new(name: "Millan")
user.save!
# => UserPet: {id: 3, user_id: 1, pet_id: 2, type: 'dog'} # => Pet: {id: 2, name: "Sam"}
# everything is working! YEY!
# we can even better, than writing in the beginning "User.create",
# we can write "User.new" and save it with all the nested elements.
你看到这是如何为我们创建所有ID的吗?让我们转向更复杂的事情!
现在我们有一个额外的表:shampo
,它与:user_pet
完全相同,属于:pet
和:user
我们需要在不知道:user
和:pet
的id的情况下创建它
u = User.new('Mike')
up = u.user_pets.new(type: "cat")
p = up.pets.new(name: "Rowe")
# But what are we doing now?
# If we do:
s = u.shampoos.new(name: "Dirty Job")
# => Shampoo: {user_id: 2, pet_id: nil, name: "..."}
# We get "pet_id: nil", not what we want.
# Or if we do:
s = p.shampoos.new(name: "Schneewittchen")
# => Shampoo: {user_id: nil, pet_id: 3, name: "..."}
# We get "user_id: nil", in both cases we do not get what we want.
# So we need to get the id of not created record, again.
# For this we can just do as in the first example (order is not important)
s = u.shampoos.new(name: "Mission Impossible")
# => Shampoo: {id: 3, user_id: 2, pet_id: nil, name: "..."}
s.pet = p # this will give the missing id, to the shampoo on save.
# Finish with save of the object:
u.save! #=> Shampoo: {id: 3, user_id: 2, pet_id: 3, name: '...'} # => Pet: ...
# Done!
当您需要元素id时,我试图介绍最常见的原因,以及如何克服这一问题。我希望它会有用。首先了解数据库的结构
- Id是使用序列来表示的李>
- 1完成的增量(在创建序列时指定)
- 数据库的最后一个条目将具有最高值
id
id
然后,您可以使用以下命令:
1. id = Model.last.id + 1
model = Model.new(id: id)
model.save
# But if data can be delete from that dataabse this will not work correctly.
2. id = Model.connection.select_value("Select nextval('models_id_seq')")
model = Model.new(id: id)
model.save
# Here in this case if you did not specified 'id' while creating new object, record will saved with next id.
e.g.
id
=> 2234
model = Model.new(id: id)
model.save
# Record will be created using 'id' as 2234
model = Model.new()
model.save
# Record will be created using next value of 'id' as 2235
希望这对你有帮助 对Rails有更多了解的人可以确认这一点,但通常ID是由数据库生成的,因此在插入行之前无法知道它是什么。你当然可以自己生成ID,但这打开了一个蠕虫罐头…我认为你应该把它作为一个单独的问题发布在这里。有时候,在保存之前而不是保存之后做一些需要id的事情是有意义的,如果你问得好,99%的dbs会给你,rails会允许你在保存之前将它分配给模型对象。在保存之前不启用id不是Rails的惯例,这是一个容易规避的可疑的实现好奇心。没错,我正在尝试开发一个复杂的过程。我应该重新考虑设计。。。!你能给我指一个链接,我可以在那里读到关于铁路的信息吗?这不是答案。看,这对各种比赛条件都是开放的。如果保存记录和设置值之间在时间上存在任何差异,那么您将在具有任何合理流量的站点上获得副本。这可以通过ValidationRails来缓解。Rails验证无法缓解此风险,只有数据库唯一性约束对此有所帮助(通常会引发异常)。为了解释,如果到数据库的往返时间是10毫秒,以提取/检查最后一个用户id,并且在此时间范围内创建了另一个用户,那么您将有两个相同的值。如果这是单用户sit