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