Search code examples
ruby-on-railsruby-on-rails-4ransack

ransack sort by model method that returns an integer


I'm trying to figure out how to sort by a method on my model that returns an integer.

class Business < ActiveRecord::Base

  has_many :questions

  def questions_count
    questions.count
  end
end

I'd like to be able to sort by the questions_count method in my table using ransack.

I have tried <th><%= sort_link @q, :questions_count %></th> with no luck.

Is this even possible? How can I achieve it?


Solution

  • The sort_link helper method can only accept an attribute or the attribute of an association, but if you wish to simple return a count of associated records, this is possible using an existing rails mechanism.

    The easiest way to achieve this is by using counter_cache - a way to count the number of objects that belong to an associated model. You'll have to add this to the association in your business model like this:

    has_many :questions, counter_cache: true
    

    It also requires a database column in the businesses table called questions_count, however, you can actually customise the name of this (and this is what will enable you to pass the number of questions to the sort_link method).

    Once this is set up you should be able to call the sort_link helper method without an issue.

    sort_link @q, :questions_count
    

    Find more about counter_cache here.

    Alternatively, there is 'another' way to achieve this. You can define a ransacker instead. You can use it to explicitly write a SQL statement that can perform a COUNT function on all associated questions for a business, but I don't think its as convenient a solution as the counter_cache method. Mainly because the SQL statement would redefine/replace the questions_count method functionality.

    Find more about ransackers here.