跟踪如何在保存后更新列



我想为我的rate动作创建一个after_save方法。它将划分rating_score/ratings并更新列评级。

class KonkurrancersController < ApplicationController
  def rate
    @konkurrancer = Konkurrancer.find(params[:id])
    @container = "Konkurrancer"+@konkurrancer.id.to_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)

我应该如何创建这个?

在Rails3+中,after_save回调中的任何update_attribute都将导致递归。应该做的是:

after_save :updater
# Awesome Ruby code
# ...
# ...
private
  def updater
    self.update_column(:column_name, new_value) # This will skip validation gracefully.
  end

你想要的是一个回调。您可以在您的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

[EDIT]您应该使用self,因为您正在编辑的模型就是模型本身。测试它,并应用必要的逻辑/实现。

查看本指南了解更多信息。

希望有帮助!

这篇文章中的许多答案可能是正确的,但现在已经过时了。Rails文档建议在回调中直接赋值(self.attribute = 'value')而不是更新或保存属性(update(attribute: 'value')。

after_save :do_foobar
private
def do_foobar
  self.attribute = "value"
end

Bad (.update_column)

安全,因为它将防止触发额外的回调,但不建议使用,因为它可能有意想不到的副作用。

after_save :do_foobar
private
def do_foobar
  update_column(:attribute, "value")
end

更糟(.update)

可以无限地触发后续回调。

after_save :do_foobar
private
def do_foobar
  update(attribute: "value")
end
  @konkurrancer.update_attributes :ratings=>'updated value'

查看这个after_save方法

相关内容

  • 没有找到相关文章

最新更新