Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Easily implement search forms and column ordering based on your models scopes
Ruby
tag: v0.6.0

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
lib
spec
.gitignore
Gemfile
LICENSE
README.textile
Rakefile
VERSION
init.rb
scoped-search.gemspec

README.textile

ScopedSearch

ScopedSearch is a plugin to easily create search forms and do column ordering.
It is written specifically for Rails 3 and is compatible with both ActiveRecord and Mongoid.

ScopeSearch is Copyright © 2010 Novagile, written by Nicolas Blanco

Philosophy

I’ve begun writing this plugin because I really like Searchlogic from Ben Johnson.
I was using it in all my Rails 2 Active Record projects.

Searchlogic has a feature that dynamically adds a lot of scopes in your models. But a feature from Searchlogic I really like is the ability to create an object
that binds to your models scopes and being able to use it directly in a form. You can add many fields in your search forms, and the controller stays
the same. I really wanted the same behaviour in Rails 3 and compatible with both ActiveRecord and Mongoid.

Installation

For now, ScopedSearch is under development.
You may use it as plugin or as a gem.

Gem

Edit your Gemfile and add :

  gem 'scoped-search', :require => "scoped_search"

Plugin

  rails plugin install git://github.com/novagile/scoped-search.git

ScopedSearch does not dynamically include itself in ActiveRecord or Mongoid, you have to include it in your models where you want to use it.

Simply include the ScopedSearch::Model module in your models like this…

  class Post < ActiveRecord::Base
    include ScopedSearch::Model
  
    scope :retrieve, lambda { |q| where("title like ?", "%#{q}%") }
    scope :state_equals, lambda { |state| where( {:state => state }) }
    scope :published, where(:published => true)
    ...

In your ApplicationHelper, include the ScopedSearch::Helpers module :

  module ApplicationHelper
    include ScopedSearch::Helpers
  end

Console testing

You can test the search object in a console!

  > search = Post.scoped_search
   => #<ScopedSearch::Base...>
  > search.count
   => 4
  > search.all.map(&:body)
   => ["test", "lalala", "foo", "bar"] 
  > search.retrieve = "foo"
   => "foo"
  > search.count
   => 1 
  > search.all
   => [#<Post id: 3, title: nil, body: "foo"...]

Usage

Then in your controller you can do like this :

  class PostsController < ApplicationController
    def index
      @search = Post.scoped_search(params[:search])
      @posts = @search.all # or @search.paginate(...), or you can even continue the scope chain ! Just add your scopes like this : @search.build_relation.other_scope.other_other_scope... :)
      ...

In your view, you can create a form that takes your search object as parameter, like this :

  <%= form_for @search do |f| %>
    <%= f.text_field :retrieve %>
    <%= f.select :state_equals, ["pending", "accepted", "deleted"] %>
    <%= submit_tag "Search" %>
  <% end %>

Column ordering

You want to get column ordering for free? Sure!
In your model, use the scoped_order method like this :

  class Post < ActiveRecord::Base
    ...
    scoped_order :title, created_at, :updated_at # , ...
    ...

It will add two scopes for each column, named “ascend_by_column_name” and “descend_by_column_name” (like Searchlogic).

Then in your views, you may use the order_for_scoped_search view helper like this :

  <table>
    <tr>
      <th><%= link_to "Title", order_for_scoped_search(:title) %></th>
      ...

Issue with single Array attribute and multi parameters scopes

When you define a scope, you may define it with a single value that accepts an array, or as a multi parameters scope.
But I haven’t found an easy way yet to know the number of parameters a scope accepts (if you know, please tell me!).
So, for now, if you pass an array to a scoped attribute, it will be passed as an array to the scope.
If you set attributename_multi_params to true, it will be passed as multiple params to the scope.

Example :

  class Post < ActiveRecord::Base
    scope :retrieve_in_title_and_body, lambda { |a, b| where("title like ? and body like ?", "%#{a}%", "%#{b}") }
    scope :retrieve_ids, lambda { |ids| where(:id => ids) }
  end
  
  # For a multi params scope
  #
  > search = Post.scoped_search
  > search.retrieve_in_title_and_body = ["test", "whaaaa"]
  > search.retrieve_in_title_and_body_multi_params = true
  
  # For an Array param
  > search.retrieve_ids = [1,2,3]  

Notes

This plugin is new and under development, patches and contributions are welcome! Please fork and make pull requests, thanks!

Something went wrong with that request. Please try again.