Sorting / grouping pagination records with many association-based restrictions

I am working on an application that acts as a directory of locations and (currently, but perhaps not always) allows you to filter the sites of specific enterprises based on 1 city, 1 neighborhood and 1 category. Categories can be nested, and therefore they have parent_id. Associations can be understood by looking at the model code below (everything is pretty simple). So far, everything is working smoothly, but there is one workaround left.

Firstly, some important notes that will affect responses.

1. I use will_paginate to paginate object associations. However, I can’t split the pages into an array. Well, I could, but performance would be a problem along the line.

2. I use the tag model as the object of communication between the business class and the categories associated with it. Currently, the interface is configured only so that one category is tied to any business, and at least one must be attached. I plan to expand the interface for public pages later to allow filtering by several categories, so changes cannot be made to this part of the application structure unless it is much better than to do it better .

3. A possible solution that may (hopefully) exist is to smooth the join of tables in Arel or an area that allows categories to join themselves to get a parent. Currently, I consider it acceptable if the decision made the assumption that there would be no more than 1 level of nesting. However, this sacrifice is a last resort, as it will really interfere with the functionality that I want to introduce in the future.

4. In connection with the last moment, I looked at will_paginate/array , but was scared away by their disclaimer ("If you know what you are doing, and you really need to split pages into arrays, the function is explicit"). Keeping in mind the performance nightmares that I have encountered in the past when trying to collapse my own pagination plugin, I would like to avoid this if someone cannot adequately explain the consequences of such a decision to me.

5. This site should be able to make a punch. Everything is cached right now, and non-cache databases are relatively small and far apart. He must remain so.

Now, the question I want to ask.

Background . Some of the public opinion-oriented design specifications require all places from the current city to be listed and grouped by parent category (subcategories should not be displayed, but all places where company tags belong to the subcategory should also be grouped with places, which tags belong to the parents). Then these places are sorted by parent category, secondarily sorted by the name of the business to which the venue belongs. This should be a flat association, which is then fed to will_paginate. This ActiveRecord request in this place, which I will call further @venues , is then reset to JSON, cached and displayed on the page.

Question How can I build @venues with the specified grouping / ordering so that these places can be correctly paginated and displayed in accordance with the specifications of this interface?

application / models / business.rb

 # Fields: id, name, description, keywords, ... class Business < ActiveRecord::Base has_many :tags, :dependent => :destroy has_many :categories, :through => :tags has_many :venues, :dependent => :destroy has_many :cities, :through => :venues has_many :neighborhoods, :through => :venues end 

app / models / venue.rb

 # Fields: id, business_id, city_id, neighborhood_id, ... class Venue < ActiveRecord::Base belongs_to :business belongs_to :city belongs_to :neighborhood end 

application / models / tag.rb

 # Fields: id, category_id, business_id, ... class Tag < ActiveRecord::Base belongs_to :business belongs_to :category belongs_to :venue end 

application / models / category.rb

 # Fields: id, parent_id, name, description, ... class Category < ActiveRecord::Base has_many :tags, :dependent => :destroy end 

application / models / city.rb

 # Fields: id, name, description, ... class City < ActiveRecord::Base has_many :neighborhoods, :dependent => :destroy has_many :venues end 

app / models / neighborhood.rb

 # Fields: id, city_id, name, description class Neighborhood < ActiveRecord::Base belongs_to :city has_many :venues has_many :businesses, :through => :venues end 

This was one doozey for explanation, and I can provide additional information if necessary.

PS Using Rails 3.0.9 for this application with MySQL.

PSS I am also interested in templates or gems that simplify such filtering based on the possible field values ​​of several nested associations. I would give a + accept + reward discount for those who can provide an accurate solution using the gem of a nested model such as the Awesome Nested Set to group / sort / paginate this way.

+4
source share
1 answer

no subcategories should be displayed, but all places where company tags belong to a subcategory should also be grouped with places whose tags belong to the parent.

as Xavier said in a comment, you should use a nested dialing model. I use this one:

https://github.com/collectiveidea/awesome_nested_set

And that gives me the ability to paginate and sort as usual:

 module Category extend ActiveSupport::Concern included do belongs_to :category scope :sorted, includes(:category).order("categories.lft, #{table_name}.position") end module ClassMethods def tree(category=nil) return scoped unless category scoped.includes(:category).where([ "categories.lft BETWEEN ? AND ?",category.lft, category.rgt ]) end end # ClassMethods end #then with some category @animals = Animal.tree(@mamal_category) 

which will bring you all herbivores, carnivores, omnivores, etc. etc. and subcategories in a single sql call, and it is easily searchable, sortable, as it is scope.

Also see: get all product categories and child categories (rails, awesome_nested_set)

+3
source

All Articles