Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Sorting Tables in Rails w/ Mongoid

DZone's Guide to

Sorting Tables in Rails w/ Mongoid

· Database Zone
Free Resource

Download the Guide to Open Source Database Selection: MySQL vs. MariaDB and see how the side-by-side comparison of must-have features will ease the journey. Brought to you in partnership with MariaDB.

Sorting tables in Rails is a common problem. It must have been done before, right? In fact it has been done so many times that it’s really hard to find anything that “just works”.  Turned out to waste a lot of time of at least two people with creative libraries that fall short in many rather trivial ways. Of the good ones, a colleague tried sortable_table, but it’s not maintained and we finally settled on the much better handles_sortable_columns, which needed a tiny bit of integration work for Mongoid.

Lets make all our controllers support sorting with the sort_by parameter. Add the following to your ApplicationController.

    handles_sortable_columns do |conf|
      conf.sort_param = "sort_by"
    end

This lets us add column sorting with sortable_column to a view (views/tags/index.html.haml).

    #tags
      %table
        %tr
          %th= sortable_column "Name"
          %th= sortable_column "Count"
     
        - @tags.each do |tag|
          %tr
            %td.name= link_to h(tag.name), edit_tag_path(tag)
            %td= tag.count

We can use sorting on a Mongoid model directly. For a Tag model, this means invoking Tag.desc(:field) or Tag.asc(:field) by name.

    sortable_column_order do |column, direction|
      tags = Tag.send(direction, column)
    end

There’re several issues with this.

  1. We’ve just enabled parameter injection where one can send all kinds of wonderful queries into the Mongoid model by editing the URL.
  2. There’s no clear default sorting, for tags we’d like to sort by count in descending order.

The first issue can be solved by checking whether the direction is one of :asc or :desc and whether a column is a field in the model (added to config/initializers/mongoid_document.rb).

    module Mongoid
      module Document
        module ClassMethods
          def sort_by(sort_column, sort_direction)
            return nil unless ! sort_direction.blank? and [ :asc, :desc ].include?(sort_direction)
            return nil unless ! sort_column.blank? and self.fields.has_key?(sort_column.to_s)
            return self.send(sort_direction, sort_column)
          end
        end
      end
    end

Since sort_by_column returns nil if no sorting has been done, we can use it to introduce a default sort in the Tags controller.

    class TagsController < ApplicationController
      def index
        sortable_column_order do |column, direction|
            @tags = Tag.sort_by(column, direction)
        end
        @tags ||= Tag.desc(:count)
        ...
      end
      ...
    end

Screenshots

image


I love the attention to detail with the little arrow next to the sorted column as well as the fact that this gem uses the –column syntax for sorting in descending order. It also properly supports pagination. Well done.


source: http://code.dblock.org/sorting-tables-in-rails-w-mongoid

Interested in reducing database costs by moving from Oracle Enterprise to open source subscription?  Read the total cost of ownership (TCO) analysis. Brought to you in partnership with MariaDB.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}