繁体   English   中英

Rails多态投票结构

[英]Rails Polymorphic Voting Structure

在我的应用程序中, users可以投票(以类似Reddit的方式)进行投票。 这将包括用于jokesrecipesrules等的upvote / downvote结构。现在,我尝试使用joke模型作为示例来设置多态votes

我已将votes添加为多态变量,如在我的schema

create_table "votes", force: :cascade do |t|
    t.integer  "value"
    t.integer  "user_id"
    t.integer  "voteable_id"
    t.string   "voteable_type"
    t.datetime "created_at",    null: false
    t.datetime "updated_at",    null: false
  end

  add_index "votes", ["user_id"], name: "index_votes_on_user_id"
  add_index "votes", ["voteable_type", "voteable_id"], name: "index_votes_on_voteable_type_and_voteable_id"

然后,我在jokes表中添加了一个float列,以提高rank

我创建了一个vote模型:

class Vote < ActiveRecord::Base
  belongs_to :user
  belongs_to :voteable, polymorphic: true
  after_save :update_vote

  private
  def update_joke
    vote.update_rank
  end
end

并对我的joke模型进行了适当的更新:

class Joke < ActiveRecord::Base
  belongs_to :user
  has_many :votes, as: :voteable, dependent: :destroy
  default_scope { order('rank DESC')}
  def up_votes
    votes.where(value: 1).count
  end
  def down_votes
    votes.where(value: -1).count
  end
  def points
    votes.sum(:value)
  end
  def update_rank
    new_rank = points
    update_attribute(:rank, new_rank)
  end
end

而我的user模型:

class User < ActiveRecord::Base
  ...
  has_many :jokes, dependent: :destroy
  has_many :votes, dependent: :destroy
end

我有一个votes_controller如下:

class VotesController < ApplicationController

  def up_vote
    update_vote(1)
    redirect_to :back
  end

  def down_vote
    update_vote(-1)
    redirect_to :back
  end

  private
  def update_vote(new_value)
    @joke = Joke.find(params[:joke_id])
    @vote = @joke.votes.where(user_id: current_user.id).first

    if @vote
      @vote.update_attribute(:value, new_value)
    else
      @vote = current_user.votes.create(value: new_value, joke: @joke)
    end
  end
end

最后是_voter.html.erb部分:

<div class="text-center col-xs-1">
  <% if current_user %>
    <div class="width: 100%"><%= link_to " ", joke_up_vote_path(joke), class: 'glyphicon glyphicon-chevron-up', method: :post, style: "margin-right: 0; margin-left: 0" %></div>
  <% else %>
    <div class="width: 100%"><%= link_to " ", new_user_session_path, class: 'glyphicon glyphicon-chevron-up', method: :post, style: "margin-right: 0; margin-left: 0" %></div>
  <% end %>
  <div class="width: 100%"><h3 style="margin-top: 0; margin-bottom: 0"><strong><%= joke.points %></strong></h3></div>
  <% if current_user %>
    <div class="width: 100%"><%= link_to " ", joke_up_vote_path(joke), class: 'glyphicon glyphicon-chevron-down', method: :post, style: "margin-right: 0; margin-left: 0" %></div>
  <% else %>
    <div class="width: 100%"><%= link_to " ", new_user_session_path, class: 'glyphicon glyphicon-chevron-down', method: :post, style: "margin-right: 0; margin-left: 0" %></div>
  <% end %>
</div>

显示在我的otherjokes/kids.html.erb页面上:

<% @jokes.each do |joke| %>
  <div class="row">
    <% if joke.approved == true && joke.kids == true %>

    <%= render partial: 'votes/voter', locals: { joke: joke } %>

    <div class="col-xs-11"> <!-- non vote container -->

      <h2 id="joke-title" style="margin-top: 0px">
        <%= joke.title %>
        <% if joke.kids == true %>
          <%= image_tag 'icon_kids.jpg', style: "height: 25px; margin-left: 10px" %>
        <% end %>
        <% if joke.mixed == true %>
          <%= image_tag 'icon_mixed.jpg', style: "height: 25px; margin-left: 10px" %>
        <% end %>
      </h2>

      <p id="joke-body"><%= joke.body %></p>
      <p><strong>Submitted by: <%= joke.user.first_name %></strong></p>
      <% if current_user && (current_user == joke.user || current_user.admin) %>
        <%= link_to edit_joke_path(joke) do %>
          <span style="color: blue" class="glyphicon glyphicon-pencil" aria-hidden="true"></span><span style="color: blue">Edit Joke</span>
        <% end %>
        <%= link_to joke_path(joke), data: {:confirm => 'Are you sure?'}, :method => :delete do %>
          <span class="glyphicon glyphicon-trash" aria-hidden="true"></span>Delete Joke
        <% end %>
      <% end %>
    </div> <!-- non vote container -->
  </div> <!-- joke row -->
  <% end %>
  <div class="row text-center">
    <hr style="width: 50%; margin-top: 30px; margin-bottom: 30px">
  </div> <!-- row -->

<% end %>

我也对routes做了以下调整:

  resources :jokes do
    patch :approve, on: :member
    patch :reject, on: :member
    post '/up-vote' => 'votes#up_vote', as: :up_vote
    post '/down-vote' => 'votes#down_vote', as: :down_vote
  end

现在,当我尝试对一个笑话进行投票时,我得到unknown attribute 'joke' for Vote. 在我的@vote = current_user.votes.create(value: new_value, joke: @joke)行上votes_controller

我希望使该系统以一种可以应用于将来需要投票的其他模型(也可能(如果可能)以“ Ruby方式”进行)的方式运行。 谁能帮我正确地组织这个结构?

如错误所述, joke不是Vote的属性。 因为它是一个多态关联,所以给它提供了通用名称votable 使用它创建一个Joke Vote

@vote = current_user.votes.create(value: new_value, votable: @joke)

votable_idvotable_type将由框架自动派生。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM