I have a Post model:
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
a Tag model:
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
and a Vote model:
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
As you can see in this last model, it updates the :total_votes attribute of a post each time a new instance of Vote is created.
For some reason, this action is triggering the after_save :assign_tags action in the post model. So each time I create a vote for a post this part is called:
def assign_tags
self.tags = [] // I added this so that the previous array of tags are removed before the new ones are added.
and all the tags are removed. I want the assign_tags to only be triggered when a post is being edited. Any suggestions to fix this?
EDIT:
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
update post without callback inside
votemodel –OR
you can use `update_column(name, value) it skips validations & callbacks –
Here is revised vote model