Searching RESTful style

Hello list,

Ok, first I would like to say I’m starting to get the hang of thinking
the RESTful way. But, one thing that is still perplexing my
conditioned brain is how to incorporate searching into the RESTful
Rails style.

I’m sure this is a basic question, but I’d really like to see some
examples what what people are doing in this regard.

So I understand that I have URLs like:

http://example.com/posts
http://example.com/posts/123/comments

But, what is the preferred technique for filtering those resource
collections with conditions. I’m fairly sure you wouldn’t want to add
a custom action like:

map.resource :posts, :collection => { :search => :get }

and add more for each type of search you want to perform.

I’m guessing that you would do something more dynamic inside the
standard index action. Somehow I seem to have missed seeing any
examples the RESTful way to do this.

Do we do something like:

http://example.com/posts?publish_date_from=2007-05-01&publish_date_to=2007-05-15

And then determine within the index action if a query string exists
and have conditions to deal with each different set of possible search
criteria. I’m sure there’s a cleaner, easier way than that.

Any thoughts would be greatly appreciated,
Robert W.

On Thu, May 10, 2007 at 11:38:35AM -0700, Robert W. wrote :

criteria. I’m sure there’s a cleaner, easier way than that.
Personnaly, I would have a ‘search’ resource. To fetch results, you
simply GET from this resource. Back to your example, I would add routes
such as:

/search/posts/:publish_date_from/:publich_date_to/

and perform the search query in the show action.

You could extend this resource:

/search/:model/:criteria*

Hope that helps,


,========================.
| Pierre-Alexandre M. |
| email : [email protected] |
`========================’

Pierre,

Hope that helps,

Yes that does help quite a bit actually. What used to be about as
clear as mud, is now about as clear as milk. I feel I’m close to
seeing the solution, but still can’t quite see past the obstruction
(err abstraction).

I’m still a bit of a novice with Rails, so I’m still struggling a bit
on how to map out the routes and such. It would help to have a
concrete example showing such things as the map.resources, a basic
controller action for having a “Search” resource, etc. Could a
“Search” resource be used generically to query any ActiveRecord
subclasses?

On Fri, May 11, 2007 at 07:19:26AM -0700, Robert W. wrote :

Yes that does help quite a bit actually. What used to be about as
clear as mud, is now about as clear as milk. I feel I’m close to
seeing the solution, but still can’t quite see past the obstruction
(err abstraction).

Cool!

I’m still a bit of a novice with Rails, so I’m still struggling a bit
on how to map out the routes and such. It would help to have a
concrete example showing such things as the map.resources, a basic
controller action for having a “Search” resource, etc. Could a
“Search” resource be used generically to query any ActiveRecord
subclasses?

Sorry, you’re right: Show! Don’t Tell!

‘ruby script/generate scaffold_resource Model’ will generated a lot of
stuff.

If you need CRUD actions on a model mapped to a ‘real’ table in your
database, don’t change anything! Notice the map.resources :model added
to your routes.rb. It has generated for you the routes you need.
Maybe you just want to tweak your controller, with a:
before_filter :admin_authorize, :only => [:delete,:update]

You’ll have all the actions and views you need to CRUD your table. See
your app/views/model/*.rhtml for details.

What about the search resource? It’s a little more complicated (hey!
it’s not a big thing! It’s Rails, not Struts!)…
So we want to have an action mapped to a route like:
/search/posts/:publish_date_from/:publish_date_to/

First, ‘ruby script/generate scaffold_resource Search’ will do for you
the half of work. But you still need to tweak the show action:

def show
@results =
Post.find_by_publish_date_from_and_publish_date_to(params[:publish_date_from],params[:publish_date_to])

respond_to do |format|
  format.html #do fancy stuff with @results in your view
  format.xml {}
end

end

Remove the DELETE and UPGRADE actions in this example, since you
won’t need it. The INDEX one will be used to show a form for your
customers
to enter those informations
(params[:publish_date_from],params[:publish_date_to]).

What about the routes? Remove the map.resources :searches since it’s not
the type of routes you need. Instead, you could do something like:
map.search ‘/search/posts/:publish_date_from/:publish_date_to’,
:controller => ‘searches’,
:action => ‘show’,
:conditions => {:method => :get}

The search resource is actually a bad example since you only need a GET.
For example, in a auth_admins resource (wich will CRUD cookies for
authorizations), /logout is mapped to the destroy action:
def destroy
session[:id] = nil

respond_to do |format|
  format.html { redirect_to auth_admins_url }
  format.xml  { head :ok }
end

end
map.cabinet_logout ‘logout’, :controller => ‘auth_cabinets’, :action
=> ‘destroy’, :conditions => {:method => :put}

Be careful to respect the ’ and :, since conventions for them in the
routes module suck (erf, should I say: I don’t understand them?).

Actually, I’m not sure about the pluralization of ‘search’. Just add in
your config/environment.rb:
Inflector.inflections do |inflect|
inflect.irregular ‘search’, ‘searches’
end

Hope I’m clear,


,========================.
| Pierre-Alexandre M. |
| email : [email protected] |
`========================’