0

我实现了一个简单的方法来让用户对 pin 进行投票,但是我想按 upvotes 的数量对 pin 进行排序,这是我的 upvote 系统:

应用程序/控制器/pins_controller.rb

def upvote
  @pin = Pin.find(params[:id])
  @pin.votes.create
  redirect_to(pins_path)
end

应用程序/模型/vote.rb

class Vote < ActiveRecord::Base

belongs_to :pin


end

应用程序/模型/pin.rb

has_many :votes, dependent: :destroy

我的routes.rb看起来像:

resources :pins do
  member do
    post 'upvote'
  end
en

所以我想要我的app/views/pins/index.html.erb

以最多投票到较少投票显示图钉。

我知道acts_as_votable提供了一个系统来做到这一点,但由于我没有使用那个gem 来实现我的投票系统,我不确定使用它是一个好主意。

你怎么看?

我的app/views/pins/index.html.erb如下:

<% @pins.each do |pin| %>
    <div class="box panel panel-default">
      <%= image_tag pin.image.url(:medium) %>
      <div class="panel-body">

        <p class="startupinfo">
          <%= pin.startupname %><span class="reward"><i class="fa fa-heart"></i> <%= pin.reward %></p></span>

        <p class="startupname"><%= pin.description %></p>

        <p class="startuptag"><i class="fa fa-map-marker turquoise"></i> <%= pin.tag %> <i class="fa fa-tags turquoise"></i> <%= pin.city %><%= link_to upvote_pin_path(pin), method: :post do %> <i class="fa fa-chevron-circle-up fa-1x" style="color:#28c3ab"></i>  <% end %>
            <%= pluralize(pin.votes.count, "upvote") %></p>

        <p class="users-edit">
        <%= link_to pin_path(pin), class: "btn btn-success" do %> Tweet <% end %>

        <% if pin.user == current_user %>
          <%= link_to 'Edit', edit_pin_path(pin) %>
          <%= link_to 'Delete', pin, method: :delete, data: { confirm: 'Are you sure?' } %></p>
        <% end %>
      </div>
    </div>
  <% end %>

基于 BALOO 答案:

我跑了:

rails generate migration add_votescount_to_pins votes_count:integer

rails generate migration add_countercache_to_votes counter_cache:integer

我手动更新了迁移_add_votescount_to_pins.rb所以它看起来像:

class AddVotescountToPins < ActiveRecord::Migration
  def change
    add_column :pins, :votes_count, :integer
    Pin.reset_column_information
        Pin.includes(:votes).all.each do |pin|
    Pin.update_counters(pin.id, :votes_count => pin.votes.size)
  end
end

我跑了:

rake db:migrate

然后我将以下行添加到我的pins.controller.rb

def index
    @pins = Pin.all
    @pins = Pin.order(votes_count: :desc)
  end

现在我的schema.rb文件如下所示:

# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20140704125839) do

  create_table "pins", force: true do |t|
    t.string   "description"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "user_id"
    t.string   "image_file_name"
    t.string   "image_content_type"
    t.integer  "image_file_size"
    t.datetime "image_updated_at"
    t.string   "tag"
    t.string   "reward"
    t.string   "startupname"
    t.string   "city"
    t.string   "tweet"
    t.string   "logo"
    t.string   "website"
    t.string   "rewardcode"
    t.string   "logo_file_name"
    t.string   "logo_content_type"
    t.integer  "logo_file_size"
    t.datetime "logo_updated_at"
    t.integer  "votes_count"
  end

  add_index "pins", ["user_id"], name: "index_pins_on_user_id"

  create_table "startups", force: true do |t|
    t.string   "name"
    t.text     "description"
    t.text     "location"
    t.text     "tag"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "users", force: true do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "name"
    t.string   "provider"
    t.string   "uid"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true

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

end

但是我的 pin 索引仍然没有按赞数排序!有任何想法吗?

4

2 回答 2

1

因此,当您投反对票时,它会破坏吗?

您可以将votes_count整数列添加到引脚,然后将 a 添加counter_cache到投票中。

class Vote < ActiveRecord::Base
  belongs_to :pin, counter_cache: true
end

当有人投票时,这将增加 pin 上的 votes_count。

然后简单地基于那个查询

@pins = Pin.order(votes_count: :desc)

在您的迁移中,您需要根据现有投票更新 votes_count。

add_column :pins, :votes_count, :integer, default: true
Pin.reset_column_information
Pin.all.each do |pin|
  Pin.reset_counters(pin.id, :votes)
end
于 2014-07-04T12:08:44.883 回答
0

要在没有计数器缓存的情况下实现它,您可以尝试以下操作:

@pins = Pin.joins(:votes).select('pins.*, COUNT(votes.id) AS vote_count').group('votes.pins_id').order('vote_count DESC')
于 2014-07-04T12:21:17.983 回答