2011-04-25 81 views
13

我想爲我的費率操作創建after_save方法。它會劃分rating_score/ratings並更新列的評級。Rails如何在保存後更新列?

class KonkurrancersController < ApplicationController 
    def rate 
    @konkurrancer = Konkurrancer.find(params[:id]) 
    @container = "Konkurrancer"[email protected]_s 

    @konkurrancer.rating_score += params[:vind][:rating].to_i 
    @konkurrancer.ratings += 1 
    @konkurrancer.save 

    respond_to do |format| 
     format.js 
    end 
    end 
end 

這是我的模型:

class Konkurrancer < ActiveRecord::Base 
    after_save :do_foobar 

    private 
    def do_foobar 

     rating_score = self.rating_score 
     ratings = self.ratings 
     rating = (rating_score/ratings) 
     self.update_attributes(:rating => rating) 

    end 
end 

我的Rails日誌:

Started POST "/konkurrancers/rate/46" for 127.0.0.1 at 2011-04-26 23:40:56 +0200 

    Processing by KonkurrancersController#rate as */* 
    Parameters: {"utf8"=>"Ô£ô", "authenticity_token"=>"MACFM37hX4S6XA9vryn7gtfl21P 
vcaPBSiKDI8mfurg=", "vind"=>{"rating"=>"4"}, "id"=>"46"} 
    ←[1m←[36mKonkurrancer Load (1.0ms)←[0m ←[1mSELECT `konkurrancers`.* FROM `kon 
kurrancers`←[0m 
    ←[1m←[35mCACHE (0.0ms)←[0m SELECT `konkurrancers`.* FROM `konkurrancers` 
    ←[1m←[36mCACHE (0.0ms)←[0m ←[1mSELECT `konkurrancers`.* FROM `konkurrancers`← 
[0m 
    ←[1m←[35mKonkurrancer Load (1.0ms)←[0m SELECT `konkurrancers`.* FROM `konkurr 
ancers` WHERE (`konkurrancers`.`cached_slug` = '46') LIMIT 1 
    ←[1m←[36mSQL (2.0ms)←[0m ←[1mSELECT sluggable_id FROM slugs WHERE ((slugs.slu 
ggable_type = 'Konkurrancer' AND slugs.name = '46' AND slugs.sequence = 1))←[0m 
    ←[1m←[35mKonkurrancer Load (1.0ms)←[0m SELECT `konkurrancers`.* FROM `konkurr 
ancers` WHERE (`konkurrancers`.`id` = 46) LIMIT 1 
    ←[1m←[36mSQL (0.0ms)←[0m ←[1mBEGIN←[0m 
    ←[1m←[35mLink Load (1.0ms)←[0m SELECT `links`.* FROM `links` WHERE (`links`.k 
onkurrancer_id = 46) LIMIT 1 
    ←[1m←[36mSQL (0.0ms)←[0m ←[1mROLLBACK←[0m 
Rendered konkurrancers/_rating.html.erb (1.0ms) 
Rendered konkurrancers/rate.js.erb (22.0ms) 
Completed 200 OK in 606ms (Views: 286.0ms | ActiveRecord: 6.0ms) 

我應該如何創建呢?

+0

看到這個[回調](http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html) – 2011-04-25 10:05:35

回答

12

你想要的是一個回調。您可以在Konkurrancer模型上創建一個after_save回調函數,該函數將在爲該模型調用save()方法後觸發。

例如:

class Konkurrancer < ActiveRecord::Base 
    after_save :do_foobar 

    private 
    def do_foobar 

     rating_score = self.rating_score 
     ratings = self.ratings 
     rating = (rating_score/ratings) 
     self.update_attributes(:ratings => rating) 

    end 
end 

[編輯]您應該使用自我,因爲你正在編輯的模型是模型本身。測試一下,並應用必要的邏輯/實現。

看看這個guide欲瞭解更多信息。

希望有幫助!

+0

如何確保這是獲得更新的正確列? – 2011-04-25 10:07:49

+0

我已更新我的答案 – 2011-04-25 10:16:24

+0

我更新了我的答案,並用一個示例代碼塊來強調您的問題。修改它以滿足您的需求。 – 2011-04-25 10:27:32

0
​​
+0

在保存回調後添加此代碼 – Naveed 2011-04-25 10:06:34

0

看到這個​​

52

任何update_attributeafter_save回調會引起遞歸,在Rails3中+。 什麼應該做的是:

after_save :updater 
# Awesome Ruby code 
# ... 
# ... 

private 

    def updater 
    self.update_column(:column_name, new_value) # This will skip validation gracefully. 
    end 
7

不知道爲什麼人們upvoting錯誤的答案和downvoting正確的答案。

Zakelfassi是對的,Christian Fazzini對Rails 3及以上版本是錯誤的。如果您在保存回調中執行#update_attributes,則會進入無限遞歸。你想按照他的例子來做#update_column。

爲自己嘗試一下,你會看到。

+1

upvotes讓我感到困惑,所以我去了,並檢查了Rails源碼,廣泛地單元測試了我的代碼,只是爲了100%確定... – zakelfassi 2014-09-04 16:03:13

+0

是的,我只能假設他們是使用舊版本的Rails。 – 2014-09-05 02:45:07

+0

請注意,Christian Fazzini的原始問題和接受的答案都是2011年的。Rails版本幾乎肯定是2.x. – joanwolk 2015-06-10 15:13:36