Deli

Tasty URL Parameters for Rails.

Usage

Install

gem install deli

Wire up the controller

class UsersController < ApplicationController
  queries :users do
    match :created_at
    match :status
    match :name
  end
end

Request Something

/users?created_at=2010..2011&status=active&sort=created_at-,name+&page=2&limit=20

Paginate

You can paginate ActiveRecord and Mongoid models the same way.

def index
  @users = User.paginate(self.deli)
  @users.total_count
  @users.page_count
  @users.current_page
  # ...
  @users.where(:status => "active").each do |user|
    # it's scoped
  end
end

More coming on this part.

Make your own Sandwich

Perform complex queries on your ActiveRecord/Mongoid models from the URL. Done with the ActiveRecord one, still trying to find the best/right ways to to text and OR queries in mongo with Mongoid.

/users?created_at=2010..2011&status=active&sort=created_at-,name+&page=2&limit=20

...becomes

{
  :conditions => [
    {:namespace => "users", :key => "created_at", :operators => [">="], :value => "2010"},
    {:namespace => "users", :key => "created_at", :operators => ["<="], :value => "2011"},
    {:namespace => "users", :key => "status", :operators => ["="], :value => "active"}
  ],
  :order      => [
    {:namespace => "users", :key => "created_at", :operator => "-"},
    {:namespace => "users", :key => "name", :operator => "+"}
  ],
  :offset     => 20,
  :limit      => 20
}

...which in ActiveRecord looks like:

{
  :conditions => ["users.created_at >= ? AND users.created_at <= ? AND users.status = ?", Time.zone.parse("2010"), Time.zone.parse("2011"), "active"],
  :order      => "users.created_at DESC, users.name ASC",
  :offset     => 20,
  :limit      => 20
}

...and in Mongoid like this:

{
  :created_at => {"$gte" => Time.zone.parse("2010"), "$lte" => Time.zone.parse("2011")}, :status => "active"},
  :order      => [[:created_at, :desc], [:name, :asc]],
  :offset     => 20,
  :limit      => 20
}

There's a ton more you can do with it.

Parameter Types

Deli took ruby-ish conventions for structuring query parameters. Below is how you can write them for each supported attribute type. These conventions aim to be human-readable, so I have avoided using things like "double quotes" because they're escaped to %22 which is not human readable.

Also, you'll have to use javascript to format the query parameters like this, because this is overly complicated for the basic user. But it makes our lives easy, you can write the query straight in the url no problem. And with some simple javascript, the end-user's life is way easier as well.

String

# one word
title=Hello

# multiple individual words (tokens)
title=Hello+World

# exact match (single quotes)
title='Hello+World'

# include "Hello", exclude "World"
title=Hello+-World

# same, for exact matches
title=ruby+-'ruby+on+rails'

# match beginning (match phone, not iphone)
title=^phone

# match end (match ip, like in ip address, not iphone)
title=ip$

# OR or ,
title=jquery+OR+'ruby+on+rails'
title=javascript,ruby

# mix and match them all
title=javascript+-jquery+OR+'ruby+on+rails'+OR+git$

Define in the controller whether you want these to be `exact`.  This will make a SQL `=` or `!=` instead of `LIKE` and `NOT LIKE`.

Number

# positive
score=10

# negative
score=-10

# multiple
score=10,-10

# range
score=10..100

# multiple ranges
score=10..100,1000..1500

# range with no start
score=n..100

# range with no end
score=100..n

# mix and match ranges and values
score=1,10,100,1000..n

Dates/Times

# single
start_date=2011-03-12

# multiple
start_date=2011-02-01,2011-03-01

# range
start_date=2011-02-01..2011-03-01

# multiple ranges
start_date=2010-02-01..2010-03-01,2011-02-01..2011-03-01

# range with no start
start_date=t..2011-03-01

# range with no end
start_date=2011-02-01..t

# mix and match ranges and values
start_date=2011-01-01,2011-02-01..2011-03-01

# times (can do all of the above, just add @)
created_at=2011-01-01

Pagination/Limits

page=12&limit=20

Sorting

# ascending
sort=created_at
sort=created_at+

# descending
sort=created_at-

# combine
sort=name,created_at-

Reasons

When you get to coding a table, you want something plug-n-chug with searching, sorting, and pagination. This is either will_paginate or some Javascript Ajax grid plugin. Those get you up and running quickly, but they're impossible to really customize.


MIT License. © 2011 Lance Pollard.