Ian
Ian

Reputation: 65

How to get Rails 4 if a record has two conditions return true else false?

I'm setting up my vote system, and trying to have a helper model so I can check if a user has voted for a card. I'm new to rails and can't seem to figure this one out.

How do I have the model check votes for a record that has the user_id of the current_user and the card_id?

I'm also trying to limit calling the helper many times for each iteration of _cards.html.erb by setting the voted variable. Not sure how to do this, trying to set the variable is just printing true for every card, even the ones that have no votes.

Setting the variable is not working and neither is the helper, as it is always true.

cards_controller.rb:

def if_voted(card_id)
  if Vote.where(:user_id => current_user.id, :card_id => card_id) then
    true
  else
    false
  end
end
helper_method :if_voted

_cards.html.erb:

<td>
  <%= @voted = if_voted(card.id) %>
  <% if @voted == true %>
    <span class="green"><center>
  <% elsif @voted == false %>
    <span class="red"><center>
  <% else %>
    <span class="gray"><center>
  <% end %>
    <%= card.up_votes - card.down_votes %>
  </center></span>
</td>

With the help of @tadman

cards_controller.rb

def if_voted(card_id)
  if Vote.where(:user_id => current_user.id, :card_id => card_id).any? then
    @vote = Vote.find_by(:user_id => current_user.id, :card_id => card_id)
    return @vote.voted
  else
    return nil
  end
end
helper_method :if_voted

_cards.html.erb

    <td>
      <% @voted = if_voted(card.id) %>
      <% if @voted == true %>
      <span class="green"><center>
      <% elsif @voted == false %>
      <span class="red"><center>
      <% else %>
      <span class="gray"><center>
      <% end %>
        <%= card.up_votes - card.down_votes %>
      </center></span>
    </td>

Thank you

Upvotes: 1

Views: 231

Answers (1)

tadman
tadman

Reputation: 211540

The where method always returns a scope even if that scope does not contain any records. The find_by method uses the same options but returns either the first matching record or nil if none are found.

That's not quite what you want here, though. You don't actually want to retrieve any of the records, but instead just check if they exist. The any? method on a scope is true if one or more records exist, or false otherwise.

You should update your code to look like this:

def if_voted(card_id)
  Vote.where(:user_id => current_user.id, :card_id => card_id).any?
end

It's worth noting a few things about your Ruby style:

  • Using then at the end of an if clause, while supported, is extraneous and generally not done.
  • Comparing things == true is usually a sign your logic is confused. If you're concerned about something being literal true rather than just logically true, use === true instead. In this case, close enough counts, so if (if_voted(...)) should suffice.
  • Your method returned either true or false but you had three conditions as if you were expecting a maybe to pop up one day.
  • Method names like if_voted are a little clumsy, especially if used inside an if. Something like has_voted? is much more in line with Ruby and Rails in general, so you get if (has_voted?(...)) which reads a lot better.
  • Even better would be to migrate this method into the User class so you can eliminate the helper and end up with if (current_user.has_voted?(card_id)) as a very clear way of expressing your intent.

Upvotes: 4

Related Questions