5

I have a resource defined like so:

resources :referrals, :except => [:show, :edit, :destroy]

and I'd like to replace (not just add a named route) a default route that Rails produces, specifically the one for the update action.

Here is my rake routes:

referrals    GET  /referrals(.:format)     {:action=>"index", :controller=>"referrals"}
             POST /referrals(.:format)     {:action=>"create", :controller=>"referrals"}
new_referral GET  /referrals/new(.:format) {:action=>"new", :controller=>"referrals"}
referral     PUT  /referrals/:id(.:format) {:action=>"update", :controller=>"referrals"}
share             /share(.:format)         {:controller=>"referrals", :action=>"new"}
special           /special(.:format)       {:controller=>"referrals", :action=>"index"}
thanks            /thanks(.:format)        {:controller=>"pages", :action=>"thanks"}
                  /:shortlink(.:format)    {:controller=>"referrals", :action=>"update"}
                  /:linktext(.:format)     {:controller=>"referrals", :action=>"update"}
root              /(.:format)              {:controller=>"pages", :action=>"home"}

I'd like either the

/:shortlink(.:format)

or

/:linktext(.:format)

to hit the update action, but not the

/referrals/:id(.:format)

This is to implement a form of non-password "security". When the PUT goes to the update action, I want certain things to happen, but I don't want to require authorization to do this, and I don't want to allow easy guessing of the url based on controller name and simple low-numbered ids.

How can I fully replace the default route given by rails?

Bodhi
  • 1,427
  • 1
  • 13
  • 20
  • 3
    The ID in a route doesn't have to be the model ID, it can be any URL encoded attribute, such as a random hashed string. Doing this would save bending rails in a way it was not designed to bend. – Douglas F Shearer Mar 30 '11 at 22:35
  • Thanks @Douglas-F-Shearer! I just used what you're saying by overriding the `to_param` method of Referral model to return the shortlink attribute for params in url construction instead of the model ID. Now by using a `find_by_shortlink(params[:id])` I can do what I want, while preventing the simple number ids from working – Bodhi Mar 30 '11 at 22:51
  • Interestingly, the `to_param` override was only necessary to make things like `referral_url` work correctly (which is certainly a good thing to be able to do). Strictly speaking, I could have done what I was asking in my question purely with my `find_by_shortlink(params[:id])` in my controller. – Bodhi Mar 30 '11 at 22:58
  • Yeah, `to_param` is only a nicety to save so you can type `referral_path(@referral)` instead of `referral_path(@referral.shortlink)`. Handy to know though. Glad this helped. – Douglas F Shearer Mar 31 '11 at 09:07

1 Answers1

2

resources :referrals, :except => [:show, :edit, :destroy, :update]

match "/whatever_you_want/:variable_here" => "referrals#updated", :as=> the_link, :via=> :put

then in your controller you will access the param with

params[:variable_here]

here the param is whatever you want to compare against in the db, and the path will be create like this:

the_link_path or the_link_url

the :via part will constrain the path per HTTP method so only put request will match

more info here http://guides.rubyonrails.org/routing.html

radha
  • 458
  • 4
  • 9