views:

467

answers:

2

I am dealing with a very simple RESTful Rails application. There is a User model and I need to update it. Rails coders like to do:

if @user.update_attributes(params[:user])
...

And from what I understand about REST, this URL request should work:

curl -d "first_name=tony&last_name=something2&v=1.0&_method=put" http://localhost:3000/users/1.xml

However, it's quite obvious that will not work because each URL parameter will be parsed to the variable "params" and not "params[:user]"

I have a hackish fix for now, but I wanted to know how people usually handle this.

Thanks

+4  A: 

It's just a matter of how Rails parses parameters. You can nest parameters in a hash using square brackets. Something like this should work:

curl -d "user[first_name]=tony&user[last_name]=something2&v=1.0&_method=put" http://localhost:3000/users/1.xml

This should turn into

{:user=>{:last_name=>"something", :first_name=>"tony"}}

in your params hash. This is how Rails form helpers build the params hash as well, they use the square brackets in the form input tag name attribute.

chrisdinn
ok, i am actually aware of this concept but I thought there might be a better way.
Tony
+1  A: 

It's a tradeoff; You can have slightly ugly urls, but very simple controller/models. Or you can have nice urls but slightly ugly controller/models (for making custom parsing of parameters).

For example, you could add this method on your User model:

class User < ActiveRecord::Base

  #class method
  def self.new_from_params(params)
    [:action, :method, :controller].each{|m| params.delete(m)}
    # you might need to do more stuff nere - like removing additional params, etc
    return new(params)
  end
end

Now on your controller you can do this:

class UsersController < ApplicationController
  def create
    #handles nice and ugly urls
    if(params[:user]) @user=User.new(params[:user])
    else @user = User.new_from_params(params)
    end

    if(@user.valid?)
    ... etc
    end
  end
end

This will handle your post nicely, and also posts coming from forms.

I usually have this kind of behaviour when I need my clients to "copy and paste" urls around (i.e. on searches that they can send via email).

egarcia
This doesn't seem like the best way to go about it because you would need a different function for each UPDATE and NEW action. It seems like you could write one function to extract the parameters that don't actually belong to the models and use that for UPDATE and NEW for every model. Maybe I am missing something...
Tony
I didn't want to imply that this is the best way to go. In most cases the best thing is rail's default behaviour. I was proposing a solution for those (rare) cases in which you *need* nice parameters. In my particular case, fixing the CREATE function was enough, but your mileage might vary.
egarcia