Question

I am trying to create an ActiveRecord object via a JSON request. However the controller fails to set the variables passed in the parameters in the newly created object. As an example, a person object has two fields: firstname and lastname.

The JSON generated by the JSON.stringify function of the JSON.org library produces:

{"firstname" : "Joe" , "lastname" : "Bloggs"}

However the controller expects the JSON to be in the form:

{ "Person" : {"firstname" : "Joe" , "lastname" : "Bloggs"} }

I am aware that in the normal course of events (for HTTP requests) the parameters for the request are nested under the class name of the model being created.

The create action in the controller is:

def create
    @person = Person.new(params[:person])

    respond_to do |format|
      if @person.save
        flash[:notice] = 'Person was successfully created.'
        format.html { redirect_to(@person) }
        format.xml  { render :xml => @person, :status => :created, :location => @person }
        format.json  { render :json => @person, :status => :created, :location => @person }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @person.errors, :status => :unprocessable_entity }
        format.json  { render :json => @person.errors, :status => :unprocessable_entity }
      end
    end
  end

What would be the neatest way for the controller to process the JSON requests as generated? Or alternatively how do you generate "correct" JSON from Javascript objects for passing to your controllers?

TIA, Adam

Was it helpful?

Solution

If you are just passing a hash of all of the person parameters (rather than a nested-hash with "person" as the key) then you should just be able to do @person = Person.new(params).

OTHER TIPS

As for ActiveRecord 3.0.7, you can just add

self.include_root_in_json = false

to your model (person.rb) to get rid from root ({ "Person" :") part.

Alternately, Person.new(params.reject{|k,v| k != "firstname" || k != "lastname"}) would do in your Ruby.

...

Person.new({:firstname => params[:firstname], :lastname => params[:lastname]}) -- this actually works

Here's a more futureproof solution:

Person.new(params.reject{|k,v| not Person.column_names.include?(k) })

One idea for allowing flat JSON input such as {"firstname": "Joe", "lastname": "Bloggs"} and the nested kind you get with an HTML form would be:

@person = Person.new(params[:person] || params)

respond_to do |format|
  ..
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top