Make collection route generic - ruby-on-rails

I'm working with Rails 3.2 in a project, and I need to create a route for all controllers.
For now, the route is:
resources :people do
collection do
get 'search_for'
end
end
I need thsi "search_for" action for all controllers in application.
Thanks.

you can use this route
match "/:controller/search_for" => redirect("/%{controller}/search_for")
UPDATE: the route above will not work and will cause a redirect loop error simply because it causes a 301 redirect to the same route. solution is to just use
match "/:controller/search_for"
be sure to place this route above all routes so routes that go to the show action will not override this route like.

Simply put this above all routes as:
get ':controller/search_for'

Related

Rails Routing: Set specific controller action to a different path

I am looking to set the show action for a controller to a specific path (a path without the controller prefix). I know this can be done by controller by doing this
resources :items, path: ''
But is there a way to do this on only one specific action within the controller?
My end goal is to be able to say www.example.com/my-item-name and take the user to the item without changing the URL. I tried using a catchall route but redirecting adds the prefix back which I do not want.
Any ideas?
You can specify which controller and action respond to a certain route in your routes.rb file, like this:
get 'something', to: 'controller_name#action_name'
See Rails Routing Guide.
You can define single routes manually with the match, get,post, put, macros:
get :bar, to: 'foos#bar'
get :bar, controller: 'foos' # works the same as above
post :bar, to: 'foos#bar'
You can also use scope if you want to route multiple routes to the same controller more elegantly:
scope controller: 'foos' do
get :bar
get :baz
end

How to display an action when specifying controller url

I was wondering how to display an action when specifying a controller url. For example; say I have DemoController.rb, and views/demo/index.html.erb file. Also I've specified the route in routes.rb
get 'demo/index'
How can I setup the project so that when I type "localhost:3000/demo" it renders the same layout as "localhost:3000/demo/index"?
Currently when I type in "localhost:3000/demo" I get a "no route matches" error.
You need a get 'demo' => 'demo#index' instead for that URL to work.
That said, you might want to use Rails conventions and maybe pluralize the controller and use RESTful routes instead:
resources :demos, only: :index

Rails root permalink routing

In Rails, the standard routing to objects is nested to a Model's name, example.com/model/object_id.
Is it anyhow possible to access objects without the Model part, so example.com/object_id shadowly accesses example.com/model/object_id?
Rails includes routes like you said. You can add constraints to determine object_id is integer or string.
get '/:id', to: 'articles#show', constraints: { id: /^\d/ }
This is for more information about routes constraint.
What you are first describing are the RESTful routes provided by the resources template in the rails router.
You can define different routes in the config/routes.rb file.
And for resources, you can provide a path option, where you can define a path.
resources :models, path: "/"
Will provide models resources at the route path. So a GET request to "/" would fire the "models#index" action and "/1/edit" would delegate to "models#edit"

Rails: in controller, a new view is always rendered by `show`?

I want to implement a search function in the controller, which contains "show, new, create, etc..."
I added in route.rb:
get 'apps/search' => 'apps#search'
and in apps_controller.rb:
def show
#app_info = App.find(params[:id])
end
def search
# get parameter and do search function
end
but each time when i request the /apps/search?xxx=xxx then it will be rendered by show... and then search?xxx=xxx is the parameter for method show...
should I rather create a new controller for search? Or is it possible to implement search as my requirements?
Your routes are incorrectly prioritized - somewhere else in your routes file (before the get 'apps/search' line) you have resources :apps, which defines a route that matches the same regex as apps/search.
Routes match from top to bottom, so if you check the output of rake routes, you'll see that your request to apps/search is actually matching apps/:id - which is the show route of your apps resource.
Either move the apps/search route above the resources :apps declaration, or alternatively declare your search route as part of the apps resource, eg.
resources :apps do
get :search, on: :collection
end
(this will define apps/search in the way you want).
For more information on routing: http://guides.rubyonrails.org/routing.html
I think you should edit route.rb as the following:
get 'apps/search' => 'apps#show'
The Rails' way to "say" search is a new route to the apps controller is using collection. So, for example, supposing you already have a resources :apps, you can do:
resources :apps do
get 'search', on: :collection #or you can use another HTTP verb instead of get
end
And that would give you:
search_apps GET /apps/search(.:format) apps#search

Routing custom action in Rails 3

I have a very simple question.
Trying to figure out what is the simplest way to route the custom action in rails 3.
Let's say i have controller UsersController and action promote_to_premium
Nor
http://localhost:3000/users/#{user_id}/promote_to_premium
neither
http://localhost:3000/users/promote_to_premium/#{user_id}
works.
Should I specify in routes.rb every custom action that differs from new/delete/update/create/ect/....?????
Thank You.
Yes you need to specify in your routes.rb.
Example:
resources :users do
member do
post :promote_to_premium
end
end
This way you can access the route like this:
http://localhost:3000/users/#{user_id}/promote_to_premium
You should use this in routes.rb:
match "/users/:id/promote_to_premium" => "users#promote_to_premium"
You should mention the route in routes.rb file for custom methods in the controller.
You can specify the routes using either get"" or a match""=>"" or a "post"
when you write get "controller/something" something should be an action(method) called by the name "something" in your controller. But in your case you cannot use get"controller/:id" as there is no ":id" method in your controller. So, you should match your controller/:id to some 'action' in your controller.
Hence you need to write
"match users/:id/promote_to_premium"=> "users#promote_to_premium"
But if you are writing something into the database then you should use 'post'. From whatever i know, i think you can try
match 'users/:id/promote_to_premium' => 'users#promote_to_premium', :via => :post
You can study more about routes in the below link:
http://guides.rubyonrails.org/routing.html
Yes you need to specify every route. Actually you define the normal routes too with the resource command.
There is a specific wildcard command to allow access of any action, but it is only for debug purposes, because it allows access to actions you may not want to be accessible:
match ':controller(/:action(/:id(.:format)))'

Resources