Screencast: Active Records Reputation System

Wenn der Durchschnittswert für ein Bewertungssystem oder die Summe von abgegebenen Stimmen berechnet werden müssen, dann lohnt sich ein Blick auf das activerecord-reputation-system gem. Ryan zeigt in diesem Screencast wie es verwendet wird und wie eine selbsterstellte Basis-Version gebaut werden kann.

 

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]

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.