Voting update on Ruby on Rails
Right now, I'm in the middle of building a social media app on Ruby on Rails, i have implemented a 5 point voting system. Where you can vote the news posted on the site from 1-5, what I'd like to know is, What is the best approach at handling the updates on the voting system.
In example. If a user already voted in an article I'd like to bring back score he gave in the article and soft-lock the voting (since i only allow 1 vote per user and i allow to change your vote at any time), but if he hasn't I'll bring up the article with the the voting on 0.
I know a way to accomplish this, i could do it in the view, and check if the current user has already voted on this article i would send them to the EDI开发者_C百科T view otherwise to the SHOW view. (I think)
Anyways, what would be the "correct" approach to do this?
EDIT: I forgot to say that the voting combo box it's a partial that I'm rendering. Am i suppose to just update the partial somehow?
EDIT2:
class Article < ActiveRecord::Base
has_many :votes
belongs_to :user
named_scope :voted_by, lambda {|user| {:joins => :votes, :conditions => ["votes.user_id = ?", user]} }
end
class User < ActiveRecord::Base
has_many :articles
has_many :votes, :dependent => :destroy
def can_vote_on?(article)
Article.voted_by(current_user).include?(article) #Article.voted_by(@user).include?(article)
end
end
Create a method in the User model that responds true
if the user can vote on an article:
class User < ActiveRecord::Base
...
def can_vote_on?(article)
articles_voted_on.include?(article) # left as an exercise for the reader...
end
end
In the view, render a form if the user can edit, otherwise render a normal view:
<% if @user.can_vote_on?(@article) %>
<%= render :partial => "vote_form" %>
<% else %>
<%= render :partial => "vote_display" %>
<% end %>
Or you could handle the whole thing in the controller, and render separate templates for the form version and the normal version. The best approach depends on the specifics of your situation.
EDIT2
As you discovered, current_user
doesn't work in the model. This makes sense, because the can be called from migrations, libraries, etc., where there is no concept of a session.
There's no need to access the current user anyway, since your instance method is (by definition) being called on an instance. Just refer to self
in the model, and call the method from the view on current_user
, which is an instance of User:
(in the model)
def can_vote_on?(article)
Article.voted_by(self).include?(article)
end
(in the view)
<% if current_user.can_vote_on?(@article) %>
Or you could substitute @user
for current_user
if the controller assigns it.
One last thing, I think your named scope should use user.id
, like so:
named_scope :voted_by, lambda {|user| {:joins => :votes, :conditions => ["votes.user_id = ?", user.id]} }
精彩评论