I am building a simple json API in Rails 3.1. I created a controller that has two functions:
class Api::DogsController < ActionController::Base
respond_to :json, :xml
def index
respond_with({:msg => "success"})
end
def create
respond_with({:msg => "success"})
end
end
In routes.rb I have
namespace :api do
resources :dogs
end
When I make a get request to http://localhost:3000/api/dogs I get the correct json from above. When I make a post to the same url, I get a rails exception:
ArgumentError in Api::DogsController#create
Nil location provided. Can't build URI.
actionpack (3.1.0) lib/action_dispatch/routing/polymorphic_routes.rb:183:in `build_named_route_call`
actionpack (3.1.0) lib/action_dispatch/routing/polymorphic_routes.rb:120:in `polymorphic_url'
actionpack (3.1.0) lib/action_dispatch/routing/url_for.rb:145:in `url_for'
But if I change the create code to
def create
respond_with do |format|
format.json { render :json => {:msg => "success"}}
end
end
it returns the json just fine.
Can someone explain what is going on here?
After coming across this issue myself and overcoming it, I believe I can supply an answer.
When you simply say:
def create
respond_with({:msg => "success"})
end
What rails tries to do is "guess" a url that the newly created resource is available at, and place it in the HTTP location header. That guess fails miserably for a hash object (the location it deduces is nil, which leads to the error message you are seeing).
To overcome this issue, then, you would need to do the following:
def create
respond_with({:msg => "success"}, :location => SOME_LOCATION)
end
Assuming that you know where the new resource is located. You can even specify "nil" as "SOME_LOCATION" and that will work (somewhat absurdly).
I had the problem myself.
It is, like Aubergine says, something related with the http location header.
Actually, rails seems to build this location using by default the show route.
If you don't have a show action, -which is weird in an API, but can happen (i think)`, then you have to set a location by yourself. I have no idea what is the standard in this case.
If it happens that you need a show route, then code it, and everything should work fine.
Cheers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With