Rails 3 routing with resources under an optional scope
I have setup my versioned API like this with only a small tweak for backwards compatibility. In my routes I have:
scope '(api(/:version))', :module => :api, :version => /v\d+?/ do
…
scope '(categories/:category_id)', :category_id => /\d+/ do
…
resources :sounds
…
end
end
with the successful goal already reached of having the following URL's reach the same place
/api/v1/categories/1/sounds/2
/api/categories/1/sounds/2
/categories/1/sounds/2
/sounds/2
My directory structure is like this:
The problem I am seeing is in my link generations in my views. For example, on the sound show page I have a button_to
to delete the sound
<%= button_to 'Delete', @sound, :confirm => 'Are you sure?', :method => :delete %>
Which generates the following url in the form action
:
"/api/sounds/1371?version=1371"
And furthermore, the delete
method is not working, instead it is being sent as a POST
The interesting parts of rake routes
are:
sounds GET (/api(/:version))(/categories/:category_id)/sounds(.:format) {:controller=>"api/sounds", :version=>/v\d+?/, :action=>"index", :category_id=>/\d+/}
POST (/api(/:version))(/categories/:category_id)/sounds(.:format) {:controller=>"api/sounds", :version=>/v\d+?/, :action=>"create", :category_id=>/\d+/}
new_sound GET (/api(/:version))(/categories/:category_id)/sounds/new(.:format) {:controller=>"api/sounds", :version=>/v\d+?/, :action=>"new", :category_id=>/\d+/}
edit_sound GET (/api(/:version))(/categories/:category_id)/sounds/:id/edit(.:format) {:controller=>"api/sounds", :version=>/v\d+?/, :action=>"edit", :categor开发者_如何学运维y_id=>/\d+/}
sound GET (/api(/:version))(/categories/:category_id)/sounds/:id(.:format) {:controller=>"api/sounds", :version=>/v\d+?/, :action=>"show", :category_id=>/\d+/}
PUT (/api(/:version))(/categories/:category_id)/sounds/:id(.:format) {:controller=>"api/sounds", :version=>/v\d+?/, :action=>"update", :category_id=>/\d+/}
DELETE (/api(/:version))(/categories/:category_id)/sounds/:id(.:format) {:controller=>"api/sounds", :version=>/v\d+?/, :action=>"destroy", :category_id=>/\d+/}
and the server logs show:
Started POST "/api/sounds/1371?version=1371" for 127.0.0.1 at Fri May 06 23:28:27 -0400 2011
Processing by Api::SoundsController#show as HTML
Parameters: {"authenticity_token"=>"W+QlCKjONG5i/buIgLqsrm3IHi5gdQVzFGYGREpmWYs=", "id"=>"1371", "version"=>371}
I am using JQuery as my UJS and have the most recent version of rails.js for JQuery:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script> <!-- must be >= 1.4.4 for the rails 3 link js to work—>
<script src="/javascripts/jquery-ujs/src/rails.js?1304736923" type="text/javascript"></script>
I know this is tl;dr
but my question is: "What do I need to put in my button_to link_to and other view tags to make the url helpers generate the correct path for my setup?" I have tried just about every combination I can think of but can never get them to end up in the right place.Turns out the solution was an easy one. I had two mistakes here that caused the wrong route to generate and the url to append params.
above the
resources :sounds
route, I mistakenly had this line:match '/sounds/:id(/:format)' => 'sounds#show'
I have this line so that
sounds/123/xml
can be page cached. This caused all the routing toshow
and I realized the mistake was that I had the:format
in parens, and the match should be aget
. Now it reads:get '/sounds/:id/:format' => 'sounds#show'
Next, in the
button_to
link, I was placing the@sound
object as my second param. Rails was trying to be intelligent an extrapolate the right url from this, but was failing with the optional api:version
param. Changing it tosound_path(:id => @sound.id)
worked like a charm.
精彩评论