我创建投票时会触发post模型中的after_save回调吗?

时间:2012-03-10 08:17:47

标签: ruby-on-rails

我有一个发布模型:

class Post < ActiveRecord::Base
  attr_accessible :title, :content, :tag_names

  has_many :votes, :as => :votable, :dependent => :destroy 
  has_many :taggings, :dependent => :destroy
  has_many :tags, :through => :taggings

  attr_writer :tag_names
  after_save :assign_tags

  def tag_names
    @tag_names || tags.map(&:name).join(" ")
  end

  private

  def assign_tags
    self.tags = []
    return if @tag_names.blank?
    @tag_names.split(" ").each do |name|
      tag = Tag.find_or_create_by_name(name)
      self.tags << tag unless tags.include?(tag)
    end
  end
end

标记模型:

class Tag < ActiveRecord::Base
  has_many :taggings, :dependent => :destroy  
  has_many :posts, :through => :taggings
  has_many :subscriptions
  has_many :subscribed_users, :source => :user, :through => :subscriptions

  def tag_posts_count
    "#{self.name} (#{self.posts.count})"
  end
end

投票模型:

class Vote < ActiveRecord::Base
  belongs_to :votable, :polymorphic => true
  belongs_to :user

  before_create :update_total

  protected

  def update_total
    total_average = self.votable.total_votes
    self.votable.update_attribute(:total_votes, total_average + self.polarity)
  end
end

正如您在上一个模型中所看到的,每次创建新的Vote实例时,它都会更新帖子的:total_votes属性。

出于某种原因,此操作会触发帖子模型中的after_save :assign_tags操作。因此,每次我为帖子创建投票时,都会调用此部分:

 def assign_tags
        self.tags = [] // I added this so that the previous array of tags are removed before the new ones are added. 

并删除所有标签。我希望仅在编辑帖子时触发assign_tags。有什么建议可以解决这个问题吗?

修改

votes_controller:

class VotesController < ApplicationController
  def vote_up
    @votable = params[:votable_type].constantize.find(params[:id])

    if @votable.votes.exists?(:user_id => current_user.id)
      @notice = 'You already voted'
    else
      @vote = @votable.votes.create(:user_id => current_user.id, :polarity => 1)
      @votable.reload
    end

    respond_to do |format|
      format.js
    end
  end

2 个答案:

答案 0 :(得分:1)

更新帖子而不在vote模型中回调 -

  def update_total
    self.votable.total_votes += self.polarity
    self.votable.send(:update_without_callbacks)
  end

OR

你可以使用`update_column(name,value)来跳过验证&amp;回调 -

def update_total
  self.votable.update_column(:total_votes, votable.total_votes + polarity)
end

这是修改后的投票模型

class Vote < ActiveRecord::Base
  belongs_to :votable, :polymorphic => true
  belongs_to :user

  after_create :update_total

  protected

  def update_total
    if votable && votable.is_a?(Post)
      self.votable.update_column(:total_votes, votable.total_votes + self.polarity)
    end
  end
end

答案 1 :(得分:1)

使用after_commit作为回调