Question

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

Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top