Skip to content

Instantly share code, notes, and snippets.

@caok
Last active January 2, 2016 07:19
Show Gist options
  • Save caok/8269030 to your computer and use it in GitHub Desktop.
Save caok/8269030 to your computer and use it in GitHub Desktop.
Active Record Reputation System
-- <%= haiku.user.name %>
| <%= pluralize haiku.votes, "vote" %>
<% if current_user && current_user.can_vote_for?(haiku) %>
| <%= link_to "up", vote_haiku_path(haiku, value: 1), method: "post" %>
| <%= link_to "down", vote_haiku_path(haiku, value: -1), method: "post" %>
<% end %>
class Haiku < ActiveRecord::Base
attr_accessible :content
belongs_to :user
has_many :haiku_votes
def self.by_votes
select('haikus.*, coalesce(value, 0) as votes').
joins('left join haiku_votes on haiku_id=haikus.id').
order('votes desc')
end
def votes
read_attribute(:votes) || haiku_votes.sum(:value)
end
end
class HaikuVote < ActiveRecord::Base
attr_accessible :value, :haiku, :haiku_id
belongs_to :haiku
belongs_to :user
validates_uniqueness_of :haiku_id, scope: :user_id
validates_inclusion_of :value, in: [1, -1]
validate :ensure_not_author
def ensure_not_author
errors.add :user_id, "is the author of the haiku" if haiku.user_id == user_id
end
end
class HaikusController < ApplicationController
before_filter :authorize, except: [:index, :show]
def index
@haikus = Haiku.by_votes
end
def show
@haiku = Haiku.find(params[:id])
end
def create
@haiku = current_user.haikus.create!(params[:haiku])
redirect_to @haiku, notice: "Successfully created haiku."
end
def vote
vote = current_user.haiku_votes.new(value: params[:value], haiku_id: params[:id])
if vote.save
redirect_to :back, notice: "Thank you for voting."
else
redirect_to :back, alert: "Unablet to vote, perhaps you already did."
end
end
end
resources :haikus do
member { post :vote }
end
class User < ActiveRecord::Base
has_many :haikus
has_many :haiku_votes
def total_votes
HaikuVote.joins(:haiku).where(haikus: {user_id: self.id}).sum('value')
end
def can_vote_for?(haiku)
haiku_votes.build(value: 1, haiku: haiku).valid?
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment