2013-10-08 138 views
2

我创建了一个黑客新闻克隆,我试图实现一个投票系统,该系统根据过去7天的排名从大多数投票到最少投票。我知道有几个宝石可以做到这一点,但我想在使用宝石之前手动做一次。如何在没有投票权的情况下在Rails中实现投票

我有第一个问题,是多票。我希望让每个用户都能够根据自己的意愿对尽可能多的链接进行投票,但每个链接只能投一票。我试图在我的votes_controller中做到这一点,但它只允许链接本身总共投一票,而不是每个链接有一个投票的用户。下面是我在votes_controller方法:

def create 
    @vote = Vote.new(voter_params) 
    if @vote.save 
     redirect_to links_path, notice: "Thanks for voting!" 
    else 
     redirect_to links_path, notice: "Sorry, you can only vote on a link once." 
    end 
    end 

schema.rbuserslinksvotes在两个linksvotes一个user_id属性为这里列出:

create_table "links", force: true do |t| 
    t.string "description" 
    t.string "url" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    t.integer "user_id" 
    end 

    create_table "users", force: true do |t| 
    t.string "name" 
    t.string "email" 
    t.string "user_name" 
    t.string "password_digest" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    create_table "votes", force: true do |t| 
    t.integer "user_id" 
    t.integer "link_id" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

我如何修改我的电流采取行动来允许对任何链接进行投票,但每个用户只能投一票?

好的,我的第二个也是最后一个问题是,一旦我把投票问题摆平了,我怎么能根据过去7天的时间从大多数投票中选出最少的投票,然后通过postgres服务器方法。在我看来,通过数据库更有效率。我很感激任何见解,我可以得到,我完全难住,谢谢!

这里是我的链接模式,以提供更好的主意:

class Link < ActiveRecord::Base 
    validates :url, :presence => true, :url => true 
    belongs_to :user 
    has_many :votes 
    has_many :comments, :as => :commentable 

    def self.sort_by_votes 
    sorted_votes = Link.all.sort_by { |link| link.votes.count } 
    sorted_votes.reverse 
    end 
end 

,这里是我的观点:

<% if current_user %> 
<p style="float:right; padding-right: 10px;"> Logged in as: <%= current_user.name %> </p> 
<% end %> 
<div class="container" id="content"> 
    <button class="btn btn-default btn-xs" style="float:right"><%= link_to "New Link", new_link_path %></button><br><br> 
<table > 
    <thead> 
    <tr> 
    </tr> 
    </thead> 
    <tbody class="stories"> 
    <% @links.sort_by_votes.each do |link| %> 
      <%= form_for link.votes.new do |f| %> 
        <%= f.hidden_field :link_id %> 
        <%= f.submit '▲' %> 
        <% end %> 
      <%= "#{link.votes.count} votes " %> 
      <%= link_to link.description, link.url %> 
      <small><%= "(#{link.url})" %></small> 
      <span class="date"><%= link.created_at.to_time.strftime("%b %-d, %Y @ %-I:%M%P") %></span> 
      <br> 
      <button class="btn btn-default btn-xs"> 
      <%= link_to "Delete", link, :method => :delete, :data => { :confirm => "are you sure about that?" } %> 
      </button> 
      <button class="btn btn-default btn-xs"> 
      <%= link_to "Comment", link_path(link)%> 
      </button><hr/> 
     <% end %> 
</tbody> 

</div> 
+0

你可以为它创建自定义的验证。 –

回答

4

您应该使用验证了这一点:

class Vote 
    #... 
    validates :user_id, uniqueness: { scope: :link_id } 

关系计数器相当复杂,具体取决于您的数据库,并且通常会产生复杂的耗时查询。我会使用counter_cache选项。有关于如何使用这些的nice post

$ rails g migration add_votes_counter_to_link votes_count:integer 
class AddVotesCounterToLinks < ActiveRecord::Migration 
    def change 
    add_column :links, :votes_count, :integer, default: 0 
    end 
end 
$ rake db:migrate 

class Vote 
    belongs_to :link, counter_cache: true 
end 

class Link 
    has_many :votes 

    scope :most_voted, -> do 
    where(created_at: (Time.now - 7.days)..Time.now) # created 7 days ago 
    .order('votes_count DESC')      # ordered by votes_count 
    .limit(100)          # first 100 
    end 

然后,你可以做这样的事情:

Link.most_voted 
+0

我已经验证过了。你可以分享其他的东西吗? –

+0

请参阅编辑:)。 – nicooga

+0

单词。我不认为我以前见过' - > do'脚本,那是coffeescript?我试图通过添加列和删除我的sort_by_votes方法来实现这一改变,但即使它能够让多个人对相同的任务进行投票,这是一个小小的胜利,但它没有对任何东西进行排序。我是否需要将该范围调用嵌套到函数中?据我所知DESC是一个数据库查询,是吗?你能帮我理解如何将它实现到我的模型中,以便它执行吗?多谢,伙计! –