问题
Following the RailsCast for the reputation system gem, I added the following code to my microposts_controller
def index
@microposts = Micropost.paginate(page: params[:page]).find_with_reputation(:votes, :all, order: "votes desc")
@micropost = current_user.microposts.build
end
But no sorting happens in my index action aside from the default scope I set in my model
In my micropost model I have
class Micropost < ActiveRecord::Base
belongs_to :user
has_many :retweets
has_reputation :votes, source: :user, aggregated_by: :sum
default_scope -> { order('created_at DESC') }
If I change the default scope to
default_scope -> { order('votes DESC') }
It works how I want it to for the index page only but breaks all of my other pages.
I tried removing the default scope and leaving in the find_with_reputation method but it still doesn't order by votes.
I also tried defining the scope in a method in the micropost model like this
def self.popular
find_with_reputation(:votes, :all, {:order => 'votes desc'})
end
And make the code in the microposts_controller like this
def index
@microposts = Micropost.paginate(page: params[:page]).popular
@micropost = current_user.microposts.build
end
It still does not sort by votes.
Here is a copy of the log output from visiting the micropost index page https://gist.github.com/anonymous/9745552
Here is a link to the gem https://github.com/NARKOZ/activerecord-reputation-system/tree/rails4
My routes.rb for microposts looks like this
resources :microposts, only: [:create, :destroy, :index] do
member { post :vote }
member { post :retweet}
end
Any guidance is appreciated.
Update
My home page feed is designed differently from what I'm doing for the Micropost Index feed. Maybe comparing what works to what doesn't will help pinpoint the issue.
I have a Static Pages Controller which sets its scope for the home action like this
def home
@micropost = current_user.microposts.build
@feed_items = current_user.feed.paginate(page: params[:page])
end
In the user model I define the feed method used in the static pages controller like so
def feed
Micropost.from_users_followed_by_including_replies(self)
end
the from_users_followed_by_including_replies(self)
method is a scope i set in the micropost model
scope :from_users_followed_by_including_replies, lambda { |user| followed_by_including_replies(user) }
def self.followed_by_including_replies(user)
followed_ids = %(SELECT followed_id FROM relationships
WHERE follower_id = :user_id)
where("user_id IN (#{followed_ids}) OR user_id = :user_id OR to_id = :user_id",
{ :user_id => user })
end
Maybe I need to adapt a similar approach to the Index action for the Microposts controller
回答1:
EDIT
In getting my hands on the code, I've found the real problem stems from the use of default_scope
.
The original order()
clause specified in your default scope is still being applied, even when adding your own order()
.
As a side note, this issue was kind of fixed in Rails 4.0, but the behavior was reverted in 4.0.1.
The solution was to apply a reorder()
# model
def self.popular
reorder('votes desc').find_with_reputation(:votes, :all)
end
# controller
def index
@microposts = Micropost.page(params[:page]).popular
end
ORIGINAL ANSWER
It seems that using the paginate
method directly may not work with activerecord-reputation-system
,
However, I found some examples showing that you can use the will_paginate
page
and per
methods:
Perhaps it will work like this:
Micropost.page(params[:page]).per(30).find_with_reputation(:votes, :all, order: "votes desc")
Or with the model scope like this:
def self.popular
find_with_reputation(:votes, :all, order: 'votes desc')
end
you could do this:
Micropost.page(params[:page]).per(30).popular
Also, as a side note, your routes file is a little strange with multiple member
blocks, when only one is necessary. I would make it look like this:
resources :microposts, only: [:create, :destroy, :index] do
member do
post :vote
post :retweet
end
end
来源:https://stackoverflow.com/questions/22617224/using-active-record-reputation-system-gem-no-sorting-happens-when-i-sort-by-vot