2011-01-06 107 views
26

我有一些模型的create語句,但它創建連接表內的記錄,無論記錄是否已存在。在Rails中,更新記錄或創建新記錄的最佳方式是什麼?

這裏是我的代碼如下所示:

@user = User.find(current_user) 
@event = Event.find(params[:id]) 
for interest in @event.interests 
@user.choices.create(:interest => interest, :score => 4) 
end 

的問題是,它創造的記錄,不管是什麼。我希望它只在沒有記錄存在的情況下才創建記錄;如果記錄確實存在,我希望它將所找到的記錄的屬性加上或減去1.

我一直在四處看看有什麼東西叫做find_or_create_by。當它發現一條記錄時,它做了什麼?我希望它取當前的:score屬性並添加1.

是否可以通過id查找或創建?我不確定我會找到什麼屬性,因爲我正在查看的模型是隻有id外鍵和score屬性的連接模型。

我試圖

@user.choices.find_or_create_by_user(:user => @user.id, :interest => interest, :score => 4) 

,但得到

未定義的方法find_by_user

我應該怎麼辦?

+1

是CURRENT_USER已經是用戶模型的實例?如果是這樣,你不需要重新找到它,只需使用`current_user`而不是`@user = ...`。 – 2011-01-07 05:30:02

回答

23

假設Choice模式有一個user_id(與用戶相關聯)和interest_id(到有興趣的關聯),這樣的事情應該做的伎倆:

@user = User.find(current_user) 
@event = Event.find(params[:id]) 

@event.interests.each do |interest| 
    choice = @user.choices.find_or_initialize_by_interest_id(interest.id) do |c| 
    c.score = 0 # Or whatever you want the initial value to be - 1 
    end 

    choice.score += 1 
    choice.save! 
end 

一些注意事項:

  1. 您不需要在find_or_*_by_*中包含user_id列,因爲您已經指示Rails僅獲取屬於@userchoices
  2. 我使用的是find_or_initialize_by_*,與find_or_create_by_*基本相同,其中一個關鍵區別是initialize實際上並不創建記錄。這與Model.new相似,而不是Model.create
  3. 設置c.score = 0的塊僅在記錄確實存在時纔會執行而不是
  4. choice.score += 1將更新記錄的分值,無論是否存在。因此,默認分數c.score = 0應該是初始值減1。
  5. 最後,choice.save!將更新記錄(如果它已經存在)或創建啓動的記錄(如果它沒有)。
7

find_or_create_by_user_id聽起來更好

+0

tho有什麼區別? – MartinElvar 2014-01-23 13:00:47

+1

這不會更新記錄?它找到它,或者它創建它。 – baash05 2014-09-10 00:26:03

59
my_class = ClassName.find_or_initialize_by_name(name) 

my_class.update_attributes({ 
    :street_address => self.street_address, 
    :city_name => self.city_name, 
    :zip_code => self.zip_code 
}) 
+0

爲什麼要投票? – 2011-01-07 01:25:52

+6

不知道爲什麼這是downvoted。這對我有幫助 - 感謝貢獻! – shedd 2011-03-07 19:16:21

0

如果您使用的是rails 4,我認爲它不會像以前那樣創建查找程序方法,所以find_or_create_by_user不會爲您創建。相反,你會做這樣的:

@user = User.find(current_user) 
@event = Event.find(params[:id]) 
for interest in @event.interests 
@user.choices.find_or_create_by(:interest => interest) do |c| 
    c.score ||= 0 
    c.score += 1 
end 
end 
3

此外,在的Rails 3你可以這樣做:

@user.choices.where(:user => @user.id, :interest => interest, :score => 4).first_or_create 
0

在Rails 4 您可以使用find_or_create_by得到一個對象(如果不存在,它會創建),然後使用update來保存或更新記錄,如果更新方法不存在,則更新方法將保持記錄,否則更新記錄。

例如

@edu = current_user.member_edu_basics.find_or_create_by(params.require(:member).permit(:school)) 

if @edu.update(params.require(:member).permit(:school, :majoy, :started, :ended)) 
相關問題