开发者

Voting update on Ruby on Rails

开发者 https://www.devze.com 2023-01-14 15:14 出处:网络
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 kn

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]}  }
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号