简体   繁体   中英

Rails custom order of records?

My Rails site has different categories that the user can browse through. Right now they're rendered in the view through a simple loop, but I'd like to be able to choose the order from left to right in which they're displayed.

Here's the current code:

<h4>Explore Listings</h4>
  <% @categories.each do |f| %>
    <p class="category-page-category"><%= link_to f.name, view_category_path(f.id) %></p>
  <% end %>

What would be an easy solution to accomplish what I want to do?

First of all native sorting by the DB is to be preferred in every case (it's much faster). If your sorting does not depend on already existing Category attributes, migrate a new attribute like position:

add_column :categories, :position, :integer

and add a scope to the model:

class Category < ActiveRecord::Base
  def self.ordered default_order=nil
    return scoped if default_order.nil? or 
      not( %w(asc desc).include?(default_order.to_s) )
    order("position #{default_order}")
  end
end

and then in the controller:

def index
  @categories = Category.ordered params[:order]
end

following the sorting attribute approach you also should ensure your position attribute is valid defined. So like:

class Category < ActiveRecord::Base
  before_create :default_position
  validates :position, 
    presence: true,
    numericality: true,
    uniqueness: true,
    on: :update

  def self.ordered default_order=nil
    return scoped if default_order.nil? or 
      not( %w(asc desc).include?(default_order.to_s) )
    order("position #{default_order}")
  end

  private
  def default_position
    self.position = self.class.maximum("position") + 1
  end
end

Changing positions has to be implemented.
Otherwise if positions never change, this means Categories have to be sorted by their creation datetime. Then you also could sort by created_at instead of position.

The easiest way I know of how to do this is to set up an AJAX form which will pass an order parameter which will be handled by the controller to re-render the form. Your controller would then listen for the order parameter and append that to @categories .

For example, your controller code might look something like:

def index
  @categories = Category.<some_other_scope>

  @categories = @categories.order(order_param) if order_param.present?

  respond_to do |format
    format.js { render :index }
  end
end

private

def order_param
  params.permit(:order)
end

It sounds like you want to sort the array of categories before they are shown, no?

If so you can use http://www.ruby-doc.org/core-2.1.2/Enumerable.html#method-i-sort_by or http://www.ruby-doc.org/core-2.1.2/Enumerable.html#method-i-sort to sort your categories however you want before rendering them.

So this could end up looking something like:

 <% @categories.sort_by(&:name).each do |f| %>

assuming categories have a name field. This should probably be done in the controller or in the model with a scope (if you are sorting based on a database field) to keep this logic out of the view.

看起来act_as_list正是您需要的

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