开发者

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:

Rails 3 routing with resources under an optional scope

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.

  1. 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 to show and I realized the mistake was that I had the :format in parens, and the match should be a get. Now it reads:

    get '/sounds/:id/:format' => 'sounds#show'
    
  2. 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 to

    sound_path(:id => @sound.id)
    

    worked like a charm.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜