I’m trying to use this statement:
@vote = Vote.where(:resource_id => params[:id], :user_id => current_user.id).first_or_create(:value => 1)
This is for an upvote or a downvote. If the row doesnt exist in the DB it should create it (ive theyve never voted on that post), otehrwise it should modify the value with -1,0,1.
If they click upvote a second time it needs to ‘undo’ the vote and put the row “value” at 0 instead of 1. The same happens with a downvote but this is only the upvote function right now.
I’m having trouble debugging this statement though in rails. I need to basically differentiate between whether its a saved record or a created record. If i put:
@vote = Vote.where(:resource_id => 25, :user_id => 1)
@vote.exists?
I get true
but if i put this.. (and the record DOES exist, it just worked above)..
@vote = Vote.where(:resource_id => 25, :user_id => 1).first_or_create(:value => 1)
@vote.exists?
I get…
NoMethodError: undefined method `exists?’ for #
After looking at the classes for the two objects i see one is a “Vote” and one is an “ActiveRecord::Relation”.
My ultimate goal is to somehow refactor this (mostly the part where it checks if the vote value is already 1, if so set it to zero (undo the vote) otherwise put it at 1
This is the code before I started trying to refactor with first_or_create. its long and ugly.
if @vote.exists?
# Check if they have already voted
if @vote.first.value == 1
@vote.first.value = 0
else
@vote.first.value = 1
end
flash[:notice] = "previous vote modified"
@vote.first.save
else
# Create a new Vote instance, save it
@vote = Vote.new(:resource_id => params[:id], :user_id => current_user.id, :value => 1)
if @vote.valid?
@vote.save
flash[:notice] = "New vote added"
else
@vote.save
flash[:notice] = (@vote.errors.full_messages).to_s
end
end
I would instead use the Rails magic methods
find_or_create_bymethods.Check out ‘Dynamic Attribute-Based Finders’ here:
http://api.rubyonrails.org/classes/ActiveRecord/Base.html
You use it like a dynamic finding method, but then pass in extra variables you want to add to create the Vote if it doesn’t exist.
In your case, it’d be something like:
If you don’t want it to immediately create, you can use
find_or_initialize_bywhich essentially creates aVote.newwithout saving.