Searching, Sorting and Pagination in Elixir & Phoenix with Rummage: Part 1

Adi Iyengar
4 min readFeb 27, 2017

--

In this blog, we will explore how to add Search, Sort and Pagination functionality to an Ecto or a Phoenix application. We will be using a certain framework which will make this task a lot easier: Rummage. Rummage comes with a lot of powerful features which are available right away, without writing a bunch of code. We are going to see how to best use those features and follow the patterns laid out by the framework.

Goal

Adding Rummage will take your application from this:

Before Rummage

To this:

Rummage: All together

Prerequisites

To follow this tutorial, you will need a working phoenix environment. I will use Elixir 1.3 with Phoenix 1.2. You should be able to run code in other Elixir and Phoenix versions using compatible releases for Rummage.

Introduction to Rummage

Rummage is a framework that can be used to Search, Sort or Paginate queries in Ecto or collections in Phoenix. Rummage is made out of two modules: Rummage.Ecto and Rummage.Phoenix. Rummage.Ecto is used to perform operations on Ecto queries and structs, and Rummage.Phoenix provides HTML support to Rummage.Ecto and enables it’s use in a Phoenix application.

Hooks - Hooks form the core part of Rummage’s functionality. Each operation performed on a query-able entity during its Rummage lifecycle is controlled by a Hook. By default, Rummage has three Hooks: one each for Search, Sort and Paginate operations. Hooks consist of logic that allow us to Search, Sort or Paginate Ecto queries. These hooks can also be configured. To learn more about how to configure Rummage Hooks, take a look at the README on Rummage.Ecto’s Github. For the purposes of this blog we will be using default Rummage configuration.

In order to use Rummage we will create a new Phoenix application: rummage_example. If you already have a phoenix application set up, then you can jump to part 2 of this tutorial.

Creating the phoenix app

Generate a phoenix app using the following command:

Generate a new phoenix app

Once we have created the app, we can use phoenix generators to generate models, views and controllers for categories and products.

Use phoenix html generators to generate model, view, templates and controller for categories
Use phoenix html generators to generate model, view, templates and controller for products

Make sure that you add products and categories resources to web/router.ex file.

Add “products” and “categories” to web/router.ex

After creating and migrating the database, you should be able to start a phoenix server and visit the index page for products.

create, migrate and start a phoenix server.

The index page can be visited by going to http://localhost:4000/products

You shouldn’t see any products on it at this point.

Now, it’s time to add new products to the application, using the Interactive Elixir Console, by typing iex -S mix on the command line:

Open up an iex to populate the database
Add categories and products to the database
Added products to the database, with categories

Now, we can update the Products index page to show category_name instead of category_id. We can do that by changing the index page to call product.category.category_name and by preloading the categories in product_controller.ex:

Now, the index page should look somewhat like this:

Products index page with Category names

Now, we have a functioning Phoenix application which is all set to use Rummage. In the next part, we will see how to do that!

Up next:

Coming Soon..

  • Searching, Sorting and Pagination with Elixir & Phoenix: Part 3
  • Advanced Rummage: Utilizing the Rummage Search hook
  • Advanced Rummage: Utilizing the Rummage Sort hook
  • Advanced Rummage: Writing a Custom Rummage.Ecto Hook
  • Advanced Rummage: Writing a Custom Rummage.Phoenix HTML helper
  • Using Rummage with other Libraries: Kerosene
  • Using Rummage with other Libraries: Scrivener

--

--

Adi Iyengar

~w(C Haskell Elixir Ruby Rust Erlang) Developer, Learner, Thinker, (Software) Bug Catcher!