2011-04-25 70 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