在保存之前获取Rails Model的ID …?

如何在保存之前获取rails模型的id?

例如,如果我创建一个新的模型实例,如何在保存之前获取其ID?

我知道id是在onsave上创建的,并且根据数据库但是有解决方法吗?

通常当人们认为他们需要这样做时,他们实际上并不需要这样做。 就像John说的那样,解释一下你想要做什么,有人可以建议一种方法来做到这一点,而不必提前知道id。

我也在寻找这个,我找到了答案:

假设模型名称为“Model”,表名为“models”

model.rb

before_save { next_id=Model.connection.select_value("Select nextval('models_id_seq')") } 

这将输出您的记录将获取的值,如果它被保存

使用自动递增整数主键的默认Rails约定,在保存模型之前无法获取模型的ID,因为当新行插入相关表时,它是由RDBMS生成的。

你实际上试图解决什么问题?

这不是一个Rails问题,而是一个数据库问题。 这是一个在任何Web应用程序框架中都会出现的问题,并且解决方案在所有地方都是相同的。 您必须使用数据库事务。

基本流程将像这样工作。

  • 打开一个交易
  • 保存您的模型
  • 使用数据库分配的ID
  • 如果事实certificate您实际上不想将此模型保留在数据库中,则回滚事务。
  • 如果事实certificate您希望将模型保留在数据库中,则提交事务。

您将从这种方法中注意到的主要事情是,在您回滚事务的ID中存在空白。

我不相信有任何变通办法,因为id实际上是由数据库本身生成的。 在将对象保存到数据库之后,该ID才可用。

在创建实例后,请考虑立即执行您想要的操作。

 after_create do print self.id end 

大多数时候,我需要一个id可以分为一个简短的列表。 创建嵌套关联或连接关联时。 让我们假设我们有: :user :user_pets通过:user_pets关联,我们将保存他们的类型。

如果我们有一个正确配置的“has_many:通过关联”,我们可以只使用User.pets.create(name: "Rex")但这太简单了,因为我们想创建:pet type in :user_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. 

你看到了这为我们创造了所有的ids? 让我们转向更复杂的事情吧! 现在我们有一个额外的表:shampoo完全如下:user_pet ,属于:pet和a :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时,我试图涵盖最常见的原因,以及如何克服这个问题。 我希望它会有用。

我在创建数据导入器时遇到了类似的情况。 我正在创建一堆不同类型的记录,并在保存之前将它们关联起来。 保存时,某些记录会抛出validation错误,因为它们有一个尚未保存的记录的validate_presence_of。

如果您正在使用postgres,则活动记录会通过在数据库中保留名为models_id_seq(sales_id_seq for Sale等)的序列来增加它分配给Model的ID。 您可以在此序列中获取下一个id,并使用以下函数递增它。

 def next_model_id ActiveRecord::Base.connection.execute("SELECT NEXTVAL('models_id_seq')").first["nextval"].to_i end 

但是,这种解决方案并不是一种好的做法,因为无法保证活动记录将来会以这种方式保留id序列。 如果它在我的项目中只使用过一次,我只会使用它,为我节省了大量的工作,并且在不应经常使用它的原因方面有很好的记录。

我知道这是一个老问题,但是如果有人需要引用它,也可以抛出我的答案

的usermodel

 class User < ActiveRecord::Base before_create :set_default_value def set_default_value self.value ||= "#{User.last.id+1}" end