In a current project I need to support finding a User by login credentials and also by email address. I know that in RESTful design you use a GET to find resources. In Rails…
GET /users # => UsersController.index -- find all the users GET /users/1 # => UsersController.show -- find a particular user
But I also need something akin to…
GET /users?username=joe&password=mysterio GET /users?email=foo@bar.com
Is it conventional to add additional routes and actions beyond index and show?
Or is it more common to put conditional logic in the show action to look at the params and detect whether we’re finding by one thing or another?
There’s a similar issue with PUT requests. In one case I need to set a User to be ‘active’ (user.active = true), and in another case I just need to do a general form-based editing operation.
Thanks guys. Eventually I’m going to figure out this REST stuff.
I don’t know how much of this is convention, but this is what I would do. I would add another action, as long as it’s specifically related to that resource. In your example, show is a find by userid, so it makes sense as another action on UsersController. You can turn it into a sentence that makes sense, ‘get me the user with this email address’
For the other one,
GET /users?username=joe&password=mysterio, I would do that as another resource. I assume you’re thinking that action would log in the user if the password were correct. The verb GET doesn’t make sense in that context.You probably want a ‘session’ resource (BTW, this is how restful_auth works). So you would say ‘create me a session for this user’, or something like
POST /sessionswhere the body of the post is the username & password for the user. This also has the good side effect of not saving the password in the history or letting someone capture it on the HTTP proxy.So your controller code would look something like this:
You would set up your routes like this:
That will get you URLs like
/users/byemail?email=foo@example.com. There are issues with encoding the email directly in the URL path, rails sees the ‘.com’ at the end and by default translates that into the :format. There’s probably a way around it, but this is what I had working.Also like cletus says, there are ways to make your route match based on the format of the parts of the URL, like all numbers or alphanumeric, but I don’t know off hand how to make that work with the dots in the url.