Действие vote_up
должно быть реализовано в вашем контроллере posts
и comments
соответственно. Пользователи голосуют за сообщения или комментарии, но не голосуют.
Я бы извлек логику голосования и поместил бы ее в модуль, который будут включены в ваши модели, а затем назвал его на голосуемым объектом из контроллера.
в каталоге lib
, создайте votable.rb
module Votable
def up_vote_from(usr)
place_vote(1, usr.id)
end
def down_vote_from(usr)
place_vote(-1, usr.id)
end
private
def place_vote(direction, usr_id)
v = self.votes.find_or_create_by_user_id(usr_id)
v.update_attribute(:polarity, direction)
end
end
(Этот пересмотренный код изменит исходный голос пользователя, если он проголосует снова. Методы голосования вернутся true
, если голос сохранится, false
в противном случае.)
В каждой голосовой модели, такой как post.rb
и comment.rb
, добавьте эту строку, чтобы смешать методы голосования:
include Votable
Теперь это можно сделать в контроллере:
@post.up_vote_from current_user # => true
Что касается реализации, то в результате вы получите некоторое повторение в ваших контроллерах / маршрутах.
В каждом голосовом контроллере установите что-то вроде:
def cast_vote
@post = Post.find params[:id]
if @post.call("#{params[:updown]}_vote_from", current_user)
respond_to do |format|
format.js
end
else
head :not_found
end
end
(ожидается .../posts/123/vote/up
для повышения, .../posts/123/vote/down
для снижения.)
затем добавьте каждый ресурс, чтобы включить ваш метод голосования:
resources :posts do
member do
post 'vote/:updown', :to => "posts#cast_vote", :as => :vote_on
end
end
, который можно вызвать в ваших представлениях с помощью:
<%= button_to "Up", :url => vote_on_post_path(@post, "up"), :remote => true %>
<%= button_to "Down", :url => vote_on_post_path(@post, "down"), :remote => true %>
Это намного меньше работы, чем кажется. Это будет иметь смысл, как только вы положите его на место. Это будет иметь больше смысла, если вы закодируете его вручную, а не копируете и вставляете. :)