Use a namespace only as param - ruby-on-rails

At the moment my routes are looking like this:
search_index GET /search(.:format) search#index
But I want to get routes like these:
search_index GET /topic1/search(.:format) search#index
search_index GET /topic2/search(.:format) search#index
As you can see, I don't want to introduce namespaces. The "topic" part of the url shall only be transported as a param.

in your routes.rb append:
match '/:topic_name/search' => 'search#show', via: :get
this will add topic_name to your params, accessible in controller - params[:topic_name]

Related

Rails route appears in routes but throws a 404

I'm trying to add a simple route to an existing controller/action but strangely I'm getting a 404 error even though the route appears to exist.
Here's the relevant section of my routes.rb:
# Wines
scope 'wine' do
get '/', to: 'wines#index', as: 'wine_index'
get '/:collection', to: 'wines#collection_detail', as: 'collection_detail'
get '/:collection/:slug', to: 'wines#wine_detail', as: 'wine_detail'
get '/:style', to: 'wines#style_detail', as: 'style_detail'
end
It seems correct because here's what I see when I check:
$ rake routes
=>
Prefix Verb URI Pattern Controller#Action
wine_index GET /wine(.:format) wines#index
collection_detail GET /wine/:collection(.:format) wines#collection_detail
wine_detail GET /wine/:collection/:slug(.:format) wines#wine_detail
style_detail GET /wine/:style(.:format) wines#style_detail
GET|POST /*path(.:format) pages#error404
I also see an expected response in the console:
2.3.1 :003 > app.style_detail_path('semi-dry')
=> "/wine/semi-dry"
Yet, when I try to visit /wine/semi-sweet/ (Semi-sweet is a style "slug" which I use to search in the action) I get a 404 error.
What could I me missing? I've searched dozens of similar questions on S.O. and none of the solutions apply to my situation.
It seems you need to specify constraints. When you say 'wines/semi-sweet', how would the router decide whether it's a style_detail path or a colletion_detail path? They both have the same mask '/wines/:something'
It should be something like:
scope 'wine' do
get '/', to: 'wines#index', as: 'wine_index'
get '/:style', to: 'wines#style_detail', as: 'style_detail', constraints: proc { |r| Style.include?(r.params[:style]) }
get '/:collection', to: 'wines#collection_detail', as: 'collection_detail'
get '/:collection/:slug', to: 'wines#wine_detail', as: 'wine_detail'
end
This way the router will match predefined words (could be an array too) with wine styles, all the other strings will be considered as wine collections.
But it would be best to change the mask for these two paths, just to be safe, for example:
get '/:style', to: 'wines#style_detail', as: 'style_detail'
get '/c/:collection', to: 'wines#collection_detail', as: 'collection_detail'

Rails Routes: How to match Rails routes based on a pattern

I have some routes like:
get 'route1' => 'controller#route1', as: 'route1'
get 'route2' => 'controller#route2', as: 'route2'
get 'route3' => 'controller#route3', as: 'route3'
How can I match more routes automatically with this pattern, e.g. 4, 5...
I am not sure how you can handle as part of route. But you can write this code in another way. You can create a route that handle all such routes at the end of your primary route as below:
get '/:route' => 'controller#route_for_all_views'
In your controller you should have this route_for_all_views action, which can handle all pages.
class SomeController < ApplicationController
def route_for_all_views
# handle your views and code with params[:route] here
end
end
I think you can do something like this:
get "/:action", to: "controller", constraints: {action: /route\d+/}
Please see dynamic segments for routes.
(also note that this would raise an exception if your controller doesn't have the method so you might need to use something like method_missing)
This may be a messy solution, but you could also do something like this, which will give you the *_path and *_url url helpers, that you get when you use the :as option.
%w{ route1 route2 route3 route4 route5 }.each do |route|
get route, to: "controller##{route}", as: route
end

Rails routing /forum/[category_id]/[topic_id]

I would like to create nested routes for my forum, where a topic belongs to a category.
I'm not liking the default nested routes
resources :forum_category do
resources :forum_topic
end
which would give me something like /forum_category/[forum_category_id]/forum_topic/[forum_topic_id]
What I want:
I'm looking to create the following rules (leaving out POST, PATCH, PUT routes)
/forum => forum_topic#index
/forum/new => forum_topic#new
/forum/[forum_category_id] => forum_topic#index
/forum/[forum_category_id]/[forum_topic_id] => forum_topic#show
So /forum is my index, forum/open-mic is my index limited to category with seo slug open mic and finally /forum/open-mic/lets-talk-about-fun would be my forum topic lets-talk-about-fun which is categorized under open-mic.
Is there any solution for this build into Rails?
If you're just looking for GET requests you can do this:
get '/forum', to: "forum_topic#index", as: :forum_topics
get '/forum/new', to: "forum_topics#new", as: :new_forum_topic
get '/forum/:forum_category_id', to: "forum_topics#show", as: :forum_topic_category
get '/forum/:forum_category_id/:forum_topic_id', to: "forum_topic#show_topic", as: :show_forum_topic_category
You could map the last two to the same controller action and redirect based on params, but I'd recommend setting up two separate actions for readability.
you can do like this for customize routes:
match "<your-url>", to:"<controller>#<action>", as: "<path-name>", via: :<your method-like GET,POST,DELETE>
for example to GET:
match "forum_category/:forum_category_id/forum_topic/:forum_topic_id", to: "forum_topic#show", as: "show_topic", via: :get
and for POST:
match "forum_category/:forum_category_id/forum_topic", to: "forum_topic#update", as: "update_topic", via: :post
in your controller you have this params:
param[:forum_category_id] and param[:forum_topic_id]

Custom url in ruby on rails

I know rails uses the controller action style urls like www.myapp.com/home/index for example
I would like to have a url like this on my rails app, www.myapp.com/my_page_here is this possible and if so how would I go about this?
You just use a get outside of any resources or namespace block in your routes.rb file:
get 'my_page_here ', :to => 'home#index'
Assuming you are using Rails 3+, do NOT use match. It can be dangerous, because if a page accepts data from a form, it should take POST requests. match would allow GET requests on an action with side-effects - which is NOT good.
Always use get, put, post or these variants where possible.
To get a path helper, try:
get 'my_page_here ', :to => 'home#index', :as => :my_page
That way, in your views, my_page_path will equal http://{domain}/my_page_here
you just need to make a routing rule to match that url
in this case it will be something like
match 'my_page_here' => 'your_controller#your_action'
your controller and action will specify the behavior of that page
so you could do
match 'my_page_here' => 'home#index'
or
get 'my_page_here', :to => 'home#index'
as suggested in other responses.
for index action in home controller if you have such a controller
see http://guides.rubyonrails.org/routing.html for more details
also see Ruby on Rails Routes - difference between get and match

Ruby on Rails 3: Change default controller and parameter order in routing

I have a Rails app that has a controller called domain which has a nested controller called subdomain and stats. I have defined them in routes.rb:
resources :domains do
resources :subdomains, :stats
end
I have changed the to_param of the domain and subdomain models to use the name of the domain, e.g.: the routing I get is http://site/domains/foo/subdomains/bar.
I would like to tidy it up to so that instead of using http://site/domains/foo/subdomains/bar I could access it with just http://site/foo/subdomains/bar. I have tried the following in routes.rb:
match "/:id/" => "domains#show", :as => :domain
Which works fine, but it only gives me the ability to use the path http://site/foo but for example http://site/foo/subdomains/bar doesn't. I could create match lines for every respective model and nested model but that does nothing to other helpers besides domain_url - i.e. edit_domain_url points to /domains/foo/edit/ instead of /foo/edit.
Is there a way to change the routing so that the resources generates helpers that point to the root url without the 'domains' part?
The single match in your routes creates only one route. Resource helpers create many routes at once. Luckily there are a lot of options for customisation. If you want to omit /domains/ from your paths, it's as simple as:
resources :domains, :path => "/" do
resources :subdomains, :stats
end
With the above in config/routes.rb, running rake routes says the following:
domain_subdomains GET /:domain_id/subdomains(.:format)
domain_subdomains POST /:domain_id/subdomains(.:format)
new_domain_subdomain GET /:domain_id/subdomains/new(.:format)
edit_domain_subdomain GET /:domain_id/subdomains/:id/edit(.:format)
domain_subdomain GET /:domain_id/subdomains/:id(.:format)
domain_subdomain PUT /:domain_id/subdomains/:id(.:format)
domain_subdomain DELETE /:domain_id/subdomains/:id(.:format)
domain_stats GET /:domain_id/stats(.:format)
domain_stats POST /:domain_id/stats(.:format)
new_domain_stat GET /:domain_id/stats/new(.:format)
edit_domain_stat GET /:domain_id/stats/:id/edit(.:format)
domain_stat GET /:domain_id/stats/:id(.:format)
domain_stat PUT /:domain_id/stats/:id(.:format)
domain_stat DELETE /:domain_id/stats/:id(.:format)
domains GET /(.:format)
domains POST /(.:format)
new_domain GET /new(.:format)
edit_domain GET /:id/edit(.:format)
domain GET /:id(.:format)
domain PUT /:id(.:format)
domain DELETE /:id(.:format)
Looks like all the routes you need!

Resources