Wahtever
Wahtever

Reputation: 3678

Rails using Ransack gem to filter results based on association count

I am trying to use the ransack gem to filter results based on the association count:

For instance each class has 50 students, so i would like to filter to classes with 20 students only.

<%= search_form_for @q do |f| %>
  <%= f.text_field :name_cont %>

  <%= f.text_field :children_count_lt %>

  <%= f.submit 'Filter' %>
<% end %>


@q = Company.ransack(params[:q])
@companies = @q.result.paginate(:page => params[:page], :per_page =>  60)

how can i do that.

Upvotes: 1

Views: 2876

Answers (2)

sites
sites

Reputation: 21795

Is better to add counter cache, not only simplifies code, it also helps performance(relative), and then you only have to use ransack:

Company.search(params[:q])

No need to change anything in controller. Just model changes to add counter cache:

class Company < ActiveRecord::Base
  has_many :children
end

class Child < ActiveRecord::Base
  belongs_to :company, counter_cache: true
end

Upvotes: 0

cschroed
cschroed

Reputation: 6834

I don't know that Ransack can handle that kind of condition. But you could still have the condition applied along with the other Ransack predicates in your search form with something like this...

Define a class method in the model to filter by child record count:

def self.children_count_lt(count)
  return Company.all if count.blank?
  Company.includes(:students).group('companies.id').having("COUNT(students.id) < #{count.to_i}").references(:students)
end

Include a number_field_tag in the search_form_for in the view:

 <%= number_field_tag :children_count_lt, params[:children_count_lt] %>

Call ransack through the filter in the controller:

@q = Company.children_count_lt(params[:children_count_lt]).ransack(params[:q])

Upvotes: 2

Related Questions