The basic outline of my code is this:
-
Check to see if a user has a “vote” object associated with a particular “report”
-
If there is no such vote object, then create one.
-
Assign it a value (upvote vs. downvote)
-
If there IS such a vote object, then change the existing vote’s value.
Here’s the problem though…The program never FINDS the vote object even when it (apparently) exists in the database!
My code looks like this:
def vote_up # voting code
@was_new = false
current_report = Report.find(params[:id])
@report = current_report
begin
@vote = current_report.votes.find_by_user_id(current_user.id) #<<---HERE IS THE BUG!!
rescue
@was_new = true
@vote = Vote.create(:user_id => current_user.id, :votable_type => 'Report', :value => 0) # default vote score of zero
end
current_report.votes << @vote
current_report.save
if @was_new #if the vote was new...
@report.upvotes += 1
@vote.value = 1
elsif !@was_new and @vote.value == -1 #else, if you are changing your vote...
@report.upvotes += 1
@report.downvotes -= 1
@vote.value = 1
end
@vote.save
@report.save
redirect_to(report_path(@report))
end
The error I receive is this:
SQLite3::SQLException: no such column: votes.votable_id: SELECT "votes".* FROM "votes" WHERE "votes"."votable_id" = 3 AND "votes"."votable_type" = 'Report' AND "votes"."user_id" = 1 LIMIT 1
I feel like the solution is simple, like writing @vote = current_report.votes.find(params[:user_id], :as => :user_id) or something like that.
EDIT:
I got it working. Here’s the working code:
def vote_up # voting code
@exists = false
get_vote(1)
if !@exists #if the vote was new...
@report.upvotes += 1
elsif @exists and @vote.value == -1 #else, if you are changing your vote...
@report.upvotes += 1
@report.downvotes -= 1
@vote.value = 1
end
@vote.save
@report.save
redirect_to(report_path(@report))
end
def vote_down
@exists = false
get_vote(-1)
if !@exists # this should handle vote changing
@report.downvotes += 1
elsif @exists and @vote.value == 1
@report.downvotes += 1
@report.upvotes -= 1
@vote.value = -1
end
@vote.save
@report.save
redirect_to(report_path(@report))
end
def get_vote(val) # voting code
current_report = Report.find(params[:id])
@report = current_report
@vote = current_report.votes.find_by_user_id(current_user.id)
unless @vote # create a vote only if it's nil
@vote = Vote.create(:user_id => current_user.id, :votable_id => 3, :votable_type => 'Report', :value => val) # default vote score of zero
current_report.votes << @vote
current_report.save
else #if it's not nil
@exists = true
end
end
Check the Dynamic attribute-based finders. You should be able to do something like: (untested code)
IMPORTANT: And one more thing. You should port most of this method to your Report model, it’s clearly a business thing, so there is where this should go!