· 2 min read

Screencast: Active Records Reputation System

Downloads in verschiedenen Formaten:

mp4 m4v webm ogg

Resourcen:

terminal

[bash]

rails g reputation_system rake db:migrate [/bash]

Gemfile

[ruby]

gem ‘activerecord-reputation-system’, require: ‘reputation_system’ [/ruby]

models/haiku.rb

[ruby]

has_reputation :votes, source: :user, aggregated_by: :sum [/ruby]

models/user.rb

[ruby]

has_many :evaluations, class_name: “RSEvaluation”, as: :source

has_reputation :votes, source: {reputation: :votes, of: :haikus}, aggregated_by: :sum

def voted_for?(haiku) evaluations.where(target_type: haiku.class, target_id: haiku.id).present? end [/ruby]

config/routes.rb

[ruby]

resources :haikus do member { post :vote } end [/ruby]

haikus_controller.rb

[ruby]

def index @haikus = Haiku.find_with_reputation(:votes, :all, order: “votes desc”) end

def vote value = params[:type] == “up” ? 1 : -1 @haiku = Haiku.find(params[:id]) @haiku.add_or_update_evaluation(:votes, value, current_user) redirect_to :back, notice: “Thank you for voting” end [/ruby]

_haiku.html.erb

[html]

| <%= pluralize haiku.reputation_value_for(:votes).to_i, “vote” %> <% if current_user && !current_user.voted_for?(haiku) %> | <%= link_to “up”, vote_haiku_path(haiku, type: “up”), method: “post” %> | <%= link_to “down”, vote_haiku_path(haiku, type: “down”), method: “post” %> <% end %> [/html]

application.html.erb

[html]

<%= current_user.reputation_value_for(:votes).to_i %> [/html]

models/haiku_vote.rb

[ruby]

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 [/ruby]

models/haiku.rb

[ruby]

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 [/ruby]

models/user.rb

[ruby]

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 [/ruby]

haikus_controller.rb

[ruby]

def index @haikus = Haiku.by_votes 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: “Unable to vote, perhaps you already did.” end end [/ruby]

_haiku.html.erb

[html]

| <%= 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 %> [/html]

application.html.erb

[html]

<%= current_user.total_votes %> [/html]

Back to Blog