Pregunta

I'm trying to POST some data to my Rails 4 API.

The resource:

App.factory 'House', ['$resource', ($resource) ->
  $resource '/api/v1/houses/:id', { id: '@id' }
]

The JSON representation of the resource:

newHouse = {
  "owner_id": "30",
  "name": "test",
  "address_attributes": {
    "street": "somewhere",
    "city": "on",
    "region": "earth"
  }
}

On House.save(null, $scope.newHouse), the server logs give me this:

Processing by Api::V1::HouseController#create as JSON
Parameters: {"owner_id"=>"34", "name"=>"test", "address_attributes"=>{"street"=>"somewhere", "city"=>"on", "region"=>"earth"}, "house"=>{"name"=>"test", "owner_id"=>"34"}}

Which is underisable, to say the least.

  1. owner_id and name appear directly bellow root, and below "house" - I would expect only below "house"
  2. address_attributes appears only directly bellow root - I would expect it to be below house

Basically I want this:

Processing by Api::V1::HouseController#create as JSON
Parameters: {"house"=>{"name"=>"test", "owner_id"=>"34", "address_attributes"=>{"street"=>"somewhere", "city"=>"on", "region"=>"earth"}}}

Any help?


EDIT

Rails controller action:

def create
  house = House.new house_params
  if house.save
    head 200
  else
    render json: {
      "error" => "validation errors",
      "detail" => house.errors.messages
      }, status: 422
  end
end
def house_params
  fields = [:name, :owner_id, address_attributes: [:street, :city, :region, :country, :postal_code ]]
  params.require(:house).permit(fields)
end

The model House has:

has_one :address
accepts_nested_attributes_for :address

I don't want to change the way the server handles the data. Many backends expect parameters to be held in the format I want, and even jQuery does it in its AJAX calls. AngularJS should be the one to change, or at least allow ways to configure.

¿Fue útil?

Solución

I am not sure you are using your $resource correctly.

EDIT: I am not sure why your class method behaves like this, the requests made should be equal./EDIT

One example of an alternative way to do it would be this: Lets say your newHouse model is this:

{
  "owner_id": "30",
  "name": "test",
  "address_attributes": {
    "street": "somewhere",
    "city": "on",
    "region": "earth"
  }
} 

In your html you would write something like:

<span class="btn btn-danger" ng-click="createNewHouse(newHouse)">Create new house</span>

Your Controller would bind createNewHouse() method to $scope:

$scope.createNewHouse= function(newHouse){
    var newHouseInstance = new House();
    newHouseInstance.house = newHouse;
    newHouseInstance.$save();
}

Above code gave me a POST request with this payload (direct copy from Chrome developer console):

Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/api/v1/houses
Request Method:POST
Request Payload:

{"house":{"owner_id":"30", "name":"test", "address_attributes":{"street":"somewhere", "city":"on", "region":"earth"}}}

This will nicely translate to what you need back at the server.

Good luck!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top