Search code examples
ruby-on-railsrubyruby-on-rails-3ratingvoting

Rails: current_user.vote_up(@micropost) undefined method


I am currently getting an undefined method for adding <% if current_user.vote_up?(@micropost) == true %>, I am unsure what is causing the error because I defined it here in the micropost controller. Any suggestions?

Micropost Controller

 def vote_up
    @micropost = Micropost.find(params[:id])
    current_user.vote_exclusively_for(@micropost)
    current_user.vote_up(@micropost)
    respond_to do |format|
      format.html { redirect_to :back }
      format.js
      end
  end

   def unvote
    @micropost = Micropost.find(params[:id])
    current_user.vote_exclusively_against(@micropost)
    current_user.unvote(@thred)
    respond_to do |format|
      format.html { redirect_to :back }
      format.js
      end
  end

Micropost HTML

<% if current_user.vote_up?(@micropost) == true %>
<div class='<%=micropost.id %>'>
<a href="/microposts/<%=micropost.id %>/vote_up" data-remote='true' class='CounterButton b2'>
<span id="CounterIcon" class="<%=micropost.id%>"></span>
</a>
</div>
<% else %>
<div class='<%=micropost.id %>'>
<a href="/microposts/<%=micropost.id %>/unvote" data-remote='true' class='CounterButton b2'>
<span id="CounterIcon" class="<%=micropost.id%>"></span>
</a>
</div>
<% end %>

Solution

  • Controller methods can't be called directly like you intend to from the view.

    Furthermore, there seems to be a bit of confusion on how the MVC separation works in Rails.

    Your current_user variable (in the view) corresponds to the "Model" layer, and as such, vote_up? should be a method of whichever class current_user is an instance of. This would be defined in models/User.rb or something like that, and there should be a vote_up? method that just queries the user's instance and returns a boolean value.

    This has nothing to do with the controller's vote_up action. This will not return a value per se: I understand it to actually vote up a "micropost". A method in the controller will be fired in response to a user's request, do some stuff to objects from the database (model layer), possibly put some of these model objects in variables, and invoke a view to show information to the user (possibly taken from these objects). But methods in the controllers aren't meant to be "called" from the view.

    Incidentally, doing == true as you do in the Micropost HTML is redundant as by convention, methods ending in ? return a boolean value. You can just:

    <% if current_user.vote_up?(@micropost) %>