0.0
Repository is archived
No commit activity in last 3 years
No release in over 3 years
Sanitizes simple and readable query parameters -great for building APIs & HTML filters
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

Runtime

 Project Readme

Constrainable

Simple filtering for ActiveRecord. Sanitizes simple and readable query parameters - great for building APIs & HTML filters.

Straight to the point. Examples:

Let's assume we have a model called Post, defined as: Post(id: integer, title: string, body: string, author_id: integer, category: string, created_at: datetime, updated_at: datetime)

In the simplest possible case you can define a few attributes and start filtering:

class Post < ActiveRecord::Base

  constrainable do
    fields :id, :author_id
  end

end

# Example request:
#   GET /posts?where[id__not_eq]=1&where[author_id__eq]=2
# Params:
#   "where" => { "id__not_eq" => "1", "author_id__eq" => "2" }

Post.constrain(params[:where])
# => SELECT posts.* FROM posts WHERE id != 1 AND author_id = 2

By default, only eq and not_eq operations are enabled, but there are plenty more:

class Post < ActiveRecord::Base

  constrainable do
    fields :id, :author_id, :with => [:in, :not_in, :gt, :gteq, :lt, :lteq]
    fields :created_at, :with => [:between]
  end

end

# Example request (various notations are accepted):
#   GET /posts?
#     where[id__not_in]=1|2|3|4&
#     where[author_id__in][]=1&
#     where[author_id__in][]=2&
#     where[created_at__between]=2011-01-01...2011-02-01

Want to alias a column? Try this:

class Post < ActiveRecord::Base

  constrainable do
    timestamp :created, :using => :created_at, :with => [:lt, :lte, :between]
  end

end
# Example request:
#   GET /posts?where[created__lt]=2011-01-01

What about associations?

class Post < ActiveRecord::Base
  belongs_to :author

  constrainable do
    string :author_name, :using => lambda { Author.arel_table[:name] }, :with => [:matches], :scope => lambda { includes(:author) }
  end
end
# Example request:
#   GET /posts?where[author__matches]=%tom%

Post.constrain(params[:where])
# => SELECT posts.* FROM posts LEFT OUTER JOIN authors ON authors.id = posts.author_id WHERE authors.name LIKE '%tom%'

Integration with controllers, views & filter forms:

# In app/models/post.rb
class Post < ActiveRecord::Base
  constrainable do
    fields :author_id
  end
end

# In app/controllers/posts_controller.rb
class PostsController < ApplicationController
  respond_to :html

  def index
    @filters = Post.constrainable.filter(params[:where])
    @posts   = Post.constrain(@filters)
    respond_with @posts
  end
end

# In app/views/posts/index.html.haml
= form_for @filters, :as => :where do
  = f.collection_select :author_id__eq, Author.order('name'), :id, :name