简体   繁体   中英

How to paginate elements of an array after sorting on it?

I've got a controller method that sorts elements by a derived attribute. I can print to the view as long as I don't attempt to paginate. When I call @foos = @foos.page params[:page] I get the following error: undefined method 'page' for #<Array:...>

Can anyone provide some guidance here? Thanks.

Here's the whole controller method:

def index_by_capacity
    if current_user.is_view_major?
      @foos = Foo.major_attr(:name)
    else
      @foos = Foo.order(:name)
    end


  @foos = @foos.sort_by! {|a| a.capacity_available.to_i }
  @total_foos = @foos.count

  @foos = @foos.page params[:page]

  respond_to do |format|
    format.html
    format.json { render json: @foos }
  end
end
  • The .sort_by! method returns an Array , which has no method page (a ruby Array can't be paginated, you would have to implement it yourself or use an external lib).

  • The pagination works on ActiveRecord::Relation objects , returned by queries like .where or .order

  • In you case , you should do an order at the DB-level (faster than doing a sort via Ruby):

     @foos.order(:capacity_available) 
  • If the capacity_available attribute is a String (not an Integer), you can CAST it as an INT :

     @foos.order('CAST(capacity_available AS INT) ASC') 

(You may need to edit the CAST() function, it should work on PostGreSQL, not sure about MySQL)

If you want to continue using an array instead of an active record relation object, you can simply include WillPaginate::Collection .

From WillPaginate Documentation

Previously, all objects returned from paginate methods were of WillPaginate::Collection type. This is no longer true; in Active Record 3, the paginate and page methods return a Relation that is extended to look like a WillPaginate::Collection. Similarly, DataMapper returns a regular DataMapper::Collection that is also extended.

Both ActiveRecord::Relation and DataMapper::Collection are lazy arrays in the way that they don't execute any SQL queries until the point when data is needed. This makes them better than ordinary arrays.

The WillPaginate::Collection class is still available, however, and mostly unchanged.

The Array#paginate method still exists, too, but is not loaded by default. If you need to paginate static arrays, first require it in your code:

require 'will_paginate/array'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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