Convert GET query strings into ActiveRecord queries
Ruby
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
spec
.gitignore
.rspec
.ruby-version
Gemfile
Guardfile
LICENSE.txt
README.md
Rakefile
lou.gemspec

README.md

Lou

Lou converts query strings to ActiveRecord queries.

So requests like this

  curl "http://example.com/some_resource?filter=first_name:eq=bob&limit=10"

Become this

  SomeResource.where(first_name: "bob").limit(10)

Installation

Add this line to your application's Gemfile:

gem 'lou'

And then execute:

$ bundle

Or install it yourself as:

$ gem install lou

Usage

Lou is intended to be used in a Rails controller and makes the most sense as part of the index method.

require 'lou'

class ThingController < ApplicationController
  def index
    # Lou needs to parse the raw query string so passing params here is not going to work
    # Lou.search returns an ActiveRecord collection of model Thing
    result = Lou.search(Thing, request.query_string)
    render json: result
  end
end

Features

Lou understands three query string params: limit, order, and filter.

Limit

Limits the number of results recturned.

  Lou.search(SomeModel, "limit=10")

  # Results in

  SomeModel.all.limit(10)

Order

Orders the results by some column. Direction can be asc, desc, or blank.

  Lou.search(SomeModel, "order=id:desc")

  # Results in

  SomeModel.all.order("id desc")
  Lou.search(SomeModel, "order=id")

  # Results in

  SomeModel.all.order("id")

Filter

The filter query param allows filtering on multiple fields using a it's own format.

Filters support equality, inequality, and inclusion.

Equality

  # All users with first name 'Bob'
  Lou.search(User, 'filter=first_name:eq=bob')

Inequality

  # All users without the first name 'bob'
  Lou.search(User, 'filter=first_name:ne=bob')

Inclusion

  # All users with first name 'bob', 'bib', or 'bub'
  Lou.search(User, 'filter=first_name:in=bob,bib,bub')

For exmple this filter finds all users with last name 'smith' and a first name of 'Tod' or 'Tom'

  Lou.search(User, "filter=first_name:eq=smith+last_name:in='tod,tom'

Multiple Filters

Combine multiple filters with a +

  # All users with first name 'bob' and a scope of 1, 2, or 3
  Lou.search(User, 'filter=first_name:eq=bob+scope:in=1,2,3')

Virtual Attributes and Joins

Lou allows you to define virtual attibutes on your models that can be used to reference joins.

  options = { virtual_attributes: { company_id: { joins: :employees } } }

  Lou.search(User, "filter=employee_id:in=1,2,3+company_id:eq=10", options)

  # results in

  User.joins(:employees).where(:employees => {:company_id => 77}).where(employee_id: [1,2,3])

NOTE:

Ideally this would be prettier if Lou were a mixin, but I wouldn't bother with that now.

class User < ActiveRecord::Base include Lou

lou_virtual_attribute company_id: { joins: employee_id } end

User.search "filter=employee_id:in=1,2,3,4+company_id:eq=10"

Future

Ideas for the future include:

  • An option to disallow certain attributes
  • More filter operators e.g. lt (less than) gt (greater than)

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request