Ruby on Rails choosing wrong controller action -


today came across strange (and inconvenient) ruby on rails behavior persistent combing of net did not yield satisfying answer to. note: translated method , route names easier read in english, , hope did not introduce inconsistencies.

situation

environment

ruby on rails 4.2.0 executing under ruby 2.0 (also tested under ruby 2.2.0)

relevant code

consider controller these actions, among others:

class assignmentscontroller < applicationcontroller   def update     ...   end    def takeover_confirmation     ...   end end 

routes.rb

since use lot of manually defined routes, did not use resources in routes.rb. routes in question defined follows:

... post 'assignments/:id' => 'assignments#update', as: 'assignment' post 'assignments/takeover_confirmation' => 'assignments#takeover_confirmation' ... 

the relevant output of rake routes:

assignment post  /assignments/:id(.:format)  assignments#update assignments_takeover_confirmation  post  /assignments/takeover_confirmation(.:format) assignments#takeover_confirmation 

problem

when post assignments_takeover_confirmation_path, rails routes update method instead. server log:

started post "/assignments/takeover_confirmation" ::1 @ ... processing assignmentscontroller#update html 

mitigation

if put update route definition after takeover_confirmation one, works intended (didn't check post update though).

furthermore, after writing found out used wrong request type update method in routes.rb (post instead of patch). doing in routes.rb indeed solve problem:

patch 'assignments/:id' => 'assignments#update', as: 'assignment' 

however, when defining post, rails should not direct post request existing path "/assignments/takeover_confirmation" different action, should it? fear next time use 2 post routes same controller same thing again.

it seems have severe misconception of rails routing, cannot lay finger on it...

edit: solution

as katafrakt explained, above request /assignments/takeover_confirmation matched route assignments/:id because rails interpreted "takeover_confirmation" part string , used :id parameter. thus, expected behavior.

working example

for sake of completeness, here working (if minimalistic) route-definition should, inspired chris's comment:

  resources :assignments     collection       post 'takeover_confirmation'     end   end 

in example, manually created route explicitly defined. routes update, show, etc. (that defined manually @ first) implicitly defined resources: :assignments.

corresponding excerpt rake routes:

... takeover_confirmation_assignments  post  /assignments/takeover_confirmation(.:format) assignments#takeover_confirmation ... assignment    /assignments/:id(.:format)  assignments#show            patch  /assignments/:id(.:format)  assignments#update            put    /assignments/:id(.:format)  assignments#update            delete /assignments/:id(.:format)  assignments#destroy .... 

thanks help!

however, when defining post, rails should not direct post request existing path "/assignments/takeover_confirmation" different action, should it?

it should. rails routing matched in exact same order defined in routes.rb file (from top bottom). if matches rule (and /assignments/takeover_confirmation matches assignments/:id rule) stops processing routing.

this behaviour simple , efficient. imagine kind of "smart" matching best route result in cumbersome , unexpected results.

btw that's why catch-all route used defined @ bottom of routing file.


Comments

Popular posts from this blog

node.js - Mongoose: Cast to ObjectId failed for value on newly created object after setting the value -

[C++][SFML 2.2] Strange Performance Issues - Moving Mouse Lowers CPU Usage -

ios - Possible to get UIButton sizeThatFits to work? -