簡體   English   中英

保存之前獲取Rails模型的ID ...?

[英]Get ID of Rails Model before saving…?

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

例如,如果我創建一個新的模型實例,如何在保存之前獲取其ID?

我知道id是在onsave上創建的並且根據數據庫但是有一個解決方法嗎?

我也在尋找這個,我找到了答案:

假設模型名稱為“Model”,表名為“models”

model.rb

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

這將輸出您的記錄將獲取的值,如果它被保存

通常當人們認為他們需要這樣做時,他們實際上並不需要這樣做。 就像John說的那樣,解釋一下你想要做什么,有人可以建議一種方法來做到這一點,而不必提前知道id。

使用自動遞增整數主鍵的默認Rails約定,在保存模型之前無法獲取模型的ID,因為當新行插入相關表時,它是由RDBMS生成的。

你實際上試圖解決什么問題?

這不是一個Rails問題,而是一個數據庫問題。 這個問題將出現在任何Web應用程序框架中,並且解決方案在所有地方都是相同的。 您必須使用數據庫事務。

基本流程將像這樣工作。

  • 打開一個交易
  • 保存你的模型
  • 使用數據庫分配的ID
  • 如果事實證明您實際上不希望將此模型保留在數據庫中,則回滾事務。
  • 如果事實證明您希望將模型保留在數據庫中,則提交事務。

您將從這種方法中注意到的主要事項是,在您回滾事務的ID中存在空白。

大多數情況下,當我需要id時,可以將其分組為一個簡短的列表。 在創建嵌套關聯或連接關聯時。 假設我們有: :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時,我試圖涵蓋最常見的原因,以及如何克服這個問題。 我希望它會有用。

考慮在創建實例后立即執行您想要的操作。

after_create do
  print self.id
end

我不相信有任何變通方法,因為id實際上是由數據庫本身生成的。 在將對象保存到數據庫之后,id才可用。

我在創建數據導入器時遇到了類似的情況。 我正在創建一堆不同類型的記錄,並在保存之前將它們關聯起來。 保存時,某些記錄會拋出驗證錯誤,因為它們有一個尚未保存的記錄的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序列。 如果它在我的項目中只使用過一次,我只會使用它,為我節省了大量的工作,並且在不應經常使用它的原因方面有很好的記錄。

首先要了解數據庫的結構。

  • Id使用序列進行gerated。
  • 增量為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  

希望這會幫助你。

我知道這是一個老問題,但如果有人需要引用它,也可以拋出我的答案

的usermodel

class User < ActiveRecord::Base
before_create :set_default_value

def set_default_value
   self.value ||= "#{User.last.id+1}"
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM