goddamnyouryan
goddamnyouryan

Reputation: 6906

Implementing vote_fu in rails app (or alternatives)

I've been trying to implement a robust voting system in Rails for some time but have been struggling. Initially I built my own voting system, but it was simplistic.

In a nutshell it just incremented a votes_count column in the Answer model using the counter cache. This worked fine for me for a while until I discovered vote_fu and realized how much more robust my voting system could be. I immediately installed it and spent the entire weekend tearing apart my application trying to get it to work.

I found a few other questions here on Stack Overflow related to this plugin, but none of them actually came up with a final solution. Here is my code:

answers_controller.rb:

def vote_up
    answer = Answer.find(params[:id])
    current_user.vote_up(answer), :voter_id => current_user.id
    redirect_to :back
end

votes_controller.rb:

def create
  @quote = Answer.find(params[:answer_id])

  respond_to do |format|
    if current_user.vote(@answer, params[:vote])
      format.rjs  { render :action => "create", :vote => @vote }
      format.html { redirect_to root_url }
    else
      format.rjs  { render :action => "error" }
      format.html { render :action => "new" }
      format.xml  { render :xml => @vote.errors, :status => :unprocessable_entity }
    end
  end
end

answer.html.erb: (two different methods here, neither of these work)

<span id="vote_form"  style="float: right;">
  <%= link_to "Vote up", :url => vote_up_answer_path(answer) %>
  /
  <%= link_to_remote "Down", :
    url => user_answer_votes_path(answer.user, answer,  :vote => :false, :format => :rjs), :method => :post
  %> 
</span>

<span id="<%= answer.id %>_vote_score" class="vote_score">
  <%= answer.votes_for - answer.votes_against %>
</span> 

routes.rb:

map.resources :users, :member => { :suspend => :put, :unsuspend => :put, :purge => :delete } do |user|
  user.resources :votes
  user.resources :answers do |answer|
    answer.resources :votes
  end
end
map.resources :answers, :has_many => :votes, :member => {:vote_up => :post, :vote_down => :post}

I am using Rails 2.3.5.

Does anyone have any suggestions? Should I just go back to my old, handmade voting system? Is there another voting plugin or method I haven't heard of?

Upvotes: 3

Views: 616

Answers (2)

Jonathan
Jonathan

Reputation: 16349

I think the first step will be to get it working through the console. From the last error in your comment, it seems maybe your models are not set up correctly. In your User model you should have the following:

#In User.rb
acts_as_voter

#In Answer
acts_as_votable

Also, make sure you have applied rake:migrate to your db, then try this in the console:

u = User.first 
a = Answer.last 
u.votes_for(a)

When I used this in the past I would have a controller action that looked like the following:

def vote
  @question = Question.find(params[:id])
  if params[:vote] == 'up'      
    current_user.vote_for(@question)
  elsif params[:vote] == 'down'      
    current_user.vote_against(@question)
  end
  redirect_to @question
end

Upvotes: 1

Dan Voell
Dan Voell

Reputation: 23

The answer by jt helped me get it working. My controller didn't have the vote_for method out of the box. I think they should add that to the documentation.

def vote
    @question = Question.find(params[:id])
    if params[:vote] == 'up'      
      current_user.vote_for(@question)
    elsif params[:vote] == 'down'      
      current_user.vote_against(@question)
    end
    redirect_to @question
  end

Upvotes: 0

Related Questions