2016-08-05 3 views
0

私のアプリでは、usersが(Redditのようなやり方で)投票できるようになるでしょう。これには、jokesrecipesrulesなどのupvote/downvote構造が含まれます。今、jokeモデルを例に使用して多形votesを設定しようとしています。Rails Polymorphic投票構造

私は私のschemaに見られるように、多型変数としてvotesを追加しました:

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" 

そして私はrankのための私のjokesテーブルにfloat列を追加しました。

私はvoteモデル作成:私はvotes_controllerを持って

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

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 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部分:

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 
:私も私の routesに以下の調整を行いました

<% @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 %> 

<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ページに表示されます

今、私が冗談に投票しようとすると、votes_controllerの末尾に@vote = current_user.votes.create(value: new_value, joke: @joke)という行が呼び出され、unknown attribute 'joke' for Vote.が呼び出されます。

私はこのシステムを投票が必要な他の将来のモデルにも適用できるようにしたいと思っています。また、(可能であれば)「Rubyのやり方」にすることもできます。誰も私がこれを適切に構造化するのを助けることができる?

答えて

0

エラーとして、jokeVoteの属性ではありません。それは多型関連であるため、汎用名votableを与えました。これを使用してJokeVoteを作成します。

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

votable_idvotable_typeはフレームワークによって自動的に導出されます。

+0

これは 'jokes_controller'か' votes_controller'にありますか?私がジョークコントローラのインデックスアクトンに入れた場合、私はその行に '#JokesController:0x007fb99f5adf88>のための'未定義のローカル変数またはメソッド 'new_value'というエラーを受け取ります。 – Liz

+0

あなたのvotes_controllerのほぼ同じ行を置き換えるものです。それはエラーを打ち消した行です。 – AmShaegar

+0

これは#のエラーを '未定義メソッド 'update_vote'に変更しました。 – Liz

関連する問題