class Rating < ActiveRecord::Base
attr_accessible :item_type, :item_id, :rating, :voters_up, :voters_down
serialize :voters_up, Hash
serialize :voters_down, Hash
belongs_to :ranks, :polymorphic => true
def self.up(item, user, iteration = 1)
@rating = Rating.where(item_type: item.class.name, item_id: item.id).first
@rating = Rating.create(item_type: item.class.name,
item_id: item.id,
rating: 0,
voters_up: {users:[]}, voters_down: {users:[]}) unless @rating
changed = nil
if !@rating.voters_up[:users].include?(user.id) && !@rating.voters_down[:users].include?(user.id)
if changed.nil?
@rating.increment(:rating, 1)
@rating.voters_up[:users] << user.id
changed = true
end
end
if @rating.voters_up[:users].include?(user.id) && !@rating.voters_down[:users].include?(user.id)
if changed.nil?
@rating.decrement(:rating, 1)
@rating.voters_up[:users].delete user.id
changed = true
end
end
if @rating.voters_down[:users].include?(user.id) && !@rating.voters_up[:users].include?(user.id)
if changed.nil?
@rating.voters_up[:users] << user.id
@rating.voters_down[:users].delete user.id
@rating.increment(:rating, 2)
changed = true
end
end
@rating.save
item.update_attribute(:rating_value, @rating.rating)
end
def self.down(item, user, iteration = 1)
@rating = Rating.where(item_type: item.class.name, item_id: item.id).first
@rating = Rating.create(item_type: item.class.name,
item_id: item.id,
rating: 0,
voters_up: {users:[]}, voters_down: {users:[]}) unless @rating
changed = nil
if !@rating.voters_down[:users].include?(user.id) && !@rating.voters_up[:users].include?(user.id)
if changed.nil?
@rating.decrement(:rating, 1)
@rating.voters_down[:users] << user.id
changed = true
end
end
if @rating.voters_down[:users].include?(user.id) && !@rating.voters_up[:users].include?(user.id)
if changed.nil?
@rating.increment(:rating, 1)
@rating.voters_down[:users].delete user.id
changed = true
end
end
if @rating.voters_up[:users].include?(user.id) && !@rating.voters_down[:users].include?(user.id)
if changed.nil?
@rating.voters_down[:users] << user.id
@rating.voters_up[:users].delete user.id
@rating.decrement(:rating, 2)
changed = true
end
end
@rating.save
item.update_attribute(:rating_value, @rating.rating)
end
end
|
|
|||
|
|
|
Here's a 2-part answer: First, a direct answer to your question, and then an alternative approach to the whole thing. DRYing the current implementation That can be done, provided you can store the current user somewhere that's accessible to the models. But let's keep it a little simpler and just go for a syntax like To DRY out the "vote-enabled" models, try this:
Then, in a record that users can vote on, include that concern:
Now the As for
And that's pretty much it. Now you can do Going straight to the database Make
where Right after that, update the total rating for the post:
From time to time, you may want to do some clean-up to keep the table a little leaner (i.e. delete rows where the vote is zero, or when an associated item is deleted), but otherwise you should have a pretty robust solution with none of the overhead of Rails and ActiveRecord. And it can all be abstracted into a mixin like the concern above, and you can easily add the
|
||||
|
|