All Futures
  • All Futures
  • Setup
  • Usage
    • Active Record
    • Attributes
    • Associations
    • Aggressions
    • Callbacks
    • Dirty
    • Errors
    • Readonly
    • Validations
    • Versioning
  • API Reference
    • Class Methods
    • Instance Methods
    • Getter Methods
    • Overwritable Methods
  • Examples
    • Faceted Search
Powered by GitBook
On this page
  • Filtering, Pagination and Sorting
  • Providing a scope
  • Draw the rest of the owl

Was this helpful?

  1. Examples

Faceted Search

Filtering, Pagination and Sorting

PreviousExamples

Last updated 3 years ago

Was this helpful?

Define a class that inherits from All Futures, in a location that makes sense for your application. Many times, app/models is a suitable home but in the example, an app/filters folder was created.

Your first task is to define attributes representing the data structure you intend to persist. attribute supports all of the same data types you could use in a migration:

app/filters/customer_filter.rb
class CustomerFilter < AllFutures::Base
  # Facets
  attribute :search, :string
  attribute :threshold, :float, default: 0.1
  attribute :status, :string
  attribute :lawyers, :boolean, default: false
  attribute :low, :integer, default: 21
  attribute :high, :integer, default: 65
  
  # Pagination
  attribute :items, :integer, default: 10
  attribute :page, :integer, default: 1
  
  # Sorting
  attribute :order, :string, default: "name"
  attribute :direction, :string, default: "asc"
end

The above code is an example of using All Futures to implement an exclusion filter. It's taken from the , and is used to hold the values required to create a faceted search UI for a tabular dataset.

Filtering, Pagination and Sorting

When working with tabular data, there are typically three concerns:

  1. Filtering: attributes used to reduce and exclude data from the total pool of possible values

  2. Pagination: attributes used to track the current page and number of items per page

  3. Sorting: attributes used to sort the filtered results in a specific direction (ASC vs DESC)

The CustomerFilter doesn't describe the data - that's the model's job. Instead, facets describe the ways a user might exclude rows. Facets are composable, meaning that you can add them together to remove more data. Ultimately, the filter that is applied is the sum total of all active facets.

For example, the lawyers attribute is used to reduce the results to only rows where the name of the employer has the string and in it. threshold is used to alternate between loose and strict text matching.

When designing faceted search UIs, it's important that you handle impossible states so that there are no combinations of filters which could produce invalid combinations or even errors.

Providing a scope

class CustomerFilter < AllFutures::Base

  # Attribute definitions cut for brevity

  def scope
    Customer
      .with_status(status)
      .only_lawyers(lawyers)
      .between(low, high)
      .order(order => direction)
      .search_for(search, threshold)
  end
  
end

The business logic required to filter the data is fully contained in the model as a set of scopes. This CustomerFilter#scope method simply connects the dots to provide access to a relation for this filter instance.

Draw the rest of the owl

You can if you search for "ste". Initially, you'll see 7 matches. If you turn on Uptight mode, it reduces the results to 3 matches.

For example, it's recommended that you configure so that a user viewing page 10 is automatically taken to page 5 if the user adjust the number of records per-page from 10 to 20. Set Pagy::DEFAULT[:overflow] = :last_page in your pagy.rb initializer.

Since this example doesn't require any attribute validation, we complete the Filter by defining a scope method to return an ActiveRecord::Relation object. You can pass this relation directly into to perform the search, or additional scope clauses can be added to suit the needs of your application.

Going through building the rest of a faceted search is beyond the scope of this document, but you are encouraged to clone and explore the Beast Mode and/or follow along with the .

Beast Mode repo
see this for yourself
Pagy
Pagy
codebase
tutorial blog post
Hole In The Wall