Format constraint in wildcard route - ruby-on-rails

I have a CMS style application where the user can set a custom url and it routes to our "content_pages" controller.
To support this we have 3 wildcard routes defined.
I'm trying to constrain these wildcards so that they only respond to requests where the format is html, json, or xml and nothing else. This stems out of a problem where a missing favicon.ico results in a series of queries and web requests because it routes to the content_pages controller and then 404s.
Here's what I have so far but the constraint simply doesn't work. (favicon still routes)
get "/:id/edit", to: "content_pages#edit", :constraints => {:id => /.*/, :format => "[html|xml|json]"}, as: :edit_content_page
put "/:id", to: "content_pages#update", :constraints => {:id => /.*/, :format => "[html|xml|json]"}, as: :content_page
get "/:id", to: "content_pages#show", :constraints => {:id => /.*/, :format => "[html|xml|json]"}, as: :content_page
I also tried putting this into a custom constraint class but then the actions on content_pages that arent included here (like /content_pages which routes to index) don't render.
Here's the earlier resource statement that wires up the other actions.
resources :content_pages, except: [:get, :edit, :update] do
collection do
get :get_url
end
end
Any thoughts on how i can make this constraint apply without breaking our other, non-constrained actions?

If the only file type you want to exclude is .ico, then you could update your :id constraint to explicitly exclude it:
get "/:id", to: "content_pages#show", :constraints => {:id => /.+?(?<!ico)/, :format => /(html|xml|json)/}, as: :content_page

The simplest solution to this is to put a blank favicon.ico in your public directory.
This has the side benefit of allowing you to tidy up the routes:
get "/:id/edit", to: "content_pages#edit", as: :edit_content_page
put "/:id", to: "content_pages#update", as: :content_page
get "/:id", to: "content_pages#show", as: :content_page

Related

Rails route to get a resource using query string

I would like to have a custom route querystring based, to access a specified resource. For example:
/opportunities/rent/san-miguel-de-tucuman?id=45045
That route should map to the action OpportunitiesController#show, with the resource id 45045.
Thanks in advance!!!
Updated
This are my current routes:
get 'oportunidades/alquiler/san-miguel-de-tucuman/:id', to: "opportunities#show"
get 'oportunidades/alquiler/san-miguel-de-tucuman', to: "opportunities#index"
So, if I navigate to the /oportunidades/alquiler/san-miguel-de-tucuman?id=123456 route, it go to the Opportunities#index action.
P/S: sorry, I forget to mention that I have a similar route for the index action.
Make your custom routes as:
resources: opportunities, except: :show
get '/opportunities/rent/san-miguel-de-tucuman/:id' => 'opportunities#show', :as => 'opportunities_show'
and pass your 'id' as opportunities_show_path(id)
EDIT
Change your routes as:
get 'oportunidades/alquiler/san-miguel-de-tucuman/:id' => "opportunities#show", :as => 'opportunities_show'
get 'oportunidades/alquiler/san-miguel-de-tucuman' => "opportunities#index", :as => "opportunities_index"
Now when you want to access your show page just use opportunities_show_path(:id =>123456 )
And for index page use opportunities_index_path
Use this
match '/opportunities/rent/san-miguel-de-tucuman/:id', :to => 'opportunities#show', :via => :get
and pass a object to the path so created. Eg:-
something_path(#object), here #object is object that with id which will be passed in routes
Option 1
Query string parameter
// /opportunities/rent/san-miguel-de-tucuman?id=45045
match '/opportunities/rent/san-miguel-de-tucuman', :to => 'opportunities#show', :as => "show_opportunity", :via => :get
Option 2
Add id like new parameter. More friendly.
// /opportunities/rent/san-miguel-de-tucuman/45045
match '/opportunities/rent/san-miguel-de-tucuman/:id', :to => 'opportunities#show', :as => "show_opportunity", :via => :get
In both cases, you need to call the route like this:
show_opportunity_url(:id => 45045)
In your controller you will get the id in params[:id]

Remove the Id from the route definition

this is my routes:
PUT /welcome/:id(.:format) welcome#update
I want remove the :id from the route definition.
in other words, I want to use the update function without sending an id.
so in my routes.rb, I tried to define:
resources :welcome
match '/welcome/:id' => 'welcome#update', :via => :put
then I ran rake routes, but nothing has happened.
Do you really want to use a put request? I think you should use the a custom action to handle this. But in case you want to override the default routing, you can do it this way
match 'welcome/' => 'welcome#update', :via => 'put'
resources :welcome, :except => [:update]
use put '/welcome' => 'welcome#update'before resources :welcome so it takes precedence
UPDATE: formatting
put '/welcome' => 'welcome#update'
resources :welcome

How to name a route in rails

I have some routes looking like this :
match 'hotels/:action(/:id)', :controller => 'hotel', :action => /[a-z]+/i, :id => /[0-9]+/i
And i want to use something like hotels_dislike_path somewhere in my code which refers to /hotels/dislike
How can i do that?
From the routing guide:
3.6 Naming Routes
You can specify a name for any route using the :as option.
match 'exit' => 'sessions#destroy', :as => :logout
So, in your case, that would be:
match 'hotels/:action(/:id)', :controller => 'hotel', :action => /[a-z]+/i, :id => /[0-9]+/i
match 'hotels/dislike(/:id)', :controller => 'hotel', :id => /[0-9]+/i, :as => :hotels_dislike
match 'hotels/like(/:id)', :controller => 'hotel', :id => /[0-9]+/i, :as => :hotels_like
I don't think there's a way to do this dynamically (so you have to define one route for each action, basically). However, you can just define a couple of routes (like above) for the most used actions, and just use hotels_path :action => :really_like for more uncommon actions.
A lot has changed in the world of Rails since 2011 - this is how you would accomplish the same goal in Rails 4.
resources :hotels do
member do
post 'dislike'
post 'like'
end
end
The resulting routes:
dislike_hotel POST /hotels/:id/dislike(.:format) hotels#dislike
like_hotel POST /hotels/:id/like(.:format) hotels#like
hotels GET /hotels(.:format) hotels#index
POST /hotels(.:format) hotels#create
new_hotel GET /hotels/new(.:format) hotels#new
edit_hotel GET /hotels/:id/edit(.:format) hotels#edit
hotel GET /hotels/:id(.:format) hotels#show
PATCH /hotels/:id(.:format) hotels#update
PUT /hotels/:id(.:format) hotels#update
DELETE /hotels/:id(.:format) hotels#destro
Notice thats rails prefixes instead of postfixes the action - dislike_hotel_path not hotels_dislike.

Rails 3: Replace /users/username/something for /username/something

I already have a route to match /username for the users show page. However, when I add another action, for example: followers and following as below:
resources :users, :only => [:show] do
get :following, :followers
end
I get the URL /users/username/following instead of /username/following.
How can I make all the /users/username URL's be matched as /username/etc.. ?
Here's my /username route:
match '/:id' => 'users#show', :constraints => { :id => /[a-zA-Z0-9\-_]*/ }, :as => "user_profile"
thank you.
Edit:
I have fixed this by adding
match '/:id/following' => 'users#show/following', :as => "user_following"
match '/:id/followed' => 'users#show/following', :as => "user_followers"
But I'm not sure if that's the best solution. What I'd really want is a default route that would match all /:id/:action to the appropriate action omitting the /users.
I have fixed this by adding
match '/:id/following' => 'users#show/following', :as => "user_following"
match '/:id/followed' => 'users#show/following', :as => "user_followers"
But I'm not sure if that's the best solution. What I'd really want is a default route that would match all /:id/:action to the appropriate action omitting the /users.
Near the bottom
match ':id/:action', :controller => :users

get, match and resources in routes.rb

I am new to Rails. I found it very strange when I use the resources in routes.rb, after I redirect the page to controller/index, it render the controller/show .
I know GET controller/action is same as match "controller/action", :to => "controller/action"
I think the strange thing happens to me about the redirect, is similar to the GET and Match.
so I wonder what exactly the resources mean, can I use some simple match do the same thing?
resources is a shortcut for generating seven routes needed for a REST interface.
resources :widgets is equivalent to writing
get "widgets" => "widgets#index", :as => 'widgets'
get "widgets/:id" => "widgets#show", :as => 'widget'
get "widgets/new" => "widgets#new", :as => 'new_widget'
post "widgets" => "widgets#create", :as => 'widgets'
get "widgets/:id/edit" => "widgets#edit", :as => 'edit_widget'
patch "widgets/:id" => "widgets#update", :as => 'widget'
put "widgets/:id" => "widgets#update", :as => 'widget'
delete "widgets/:id" => "widgets#destroy", :as => 'widget'
it just saves you the trouble.
By the way, get is not exactly the same as match. get, post, put and delete are shortcuts for limiting the route to a single HTTP verb. The two route definitions below are equivalent.
match 'foo' => 'controller#action', :method => :get
get 'foo' => 'controller#action'

Resources