Ok, This seem so simple that I feel kind of dumb for asking, yet I have seen other that asked something similar but no quite the same and their answers does not solve my problem. I have a resource called servicios.
resources :servicios, created the routes for the "default" actions that are in my controller: index, new, create, show, edit, update, destroy. However, I need another action which is search that should map to my view where I'm going to implement an advance search.
How can I do that?
Editing with new info
using this approach: resources :servicios, :collection => {:search => :get}
http://localhost:3000/servicios/search
I was getting error
ActiveRecord::RecordNotFound in ServiciosController#show
Couldn't find Servicio with ID=search
If you are using Rails 3 then the route definitions will look like
resources :servicios do
collection do
get :search
end
end
resources :servicios, :collection => {:search => :get}
Will route /servicios/search to def search...end in the servicios controller.
Or...
match 'search', :to => 'servicios#search'
Related
I have a model named Entree for which the new action needs a parameter, the id of another model named Cave. I don't want to nest Entree in Cave since Cave is already nested.
What I did was declaring the resource Entree as follow in routes.rb:
resources :entrees, :except => [:new]
match "/entrees/new/:id", :to => "Entrees#new", :as => 'new_entree'
That works, but the problem is when there's an error in the create action, I want to display the page again with the invalid input. But since there's no new action, I must do a redirect_to new_entree_path, which does not keep the user input.
I have tried the following (simplest) route:
resources :entrees
But then the path http://localhost:3000/entrees/new/32 returns an error:
No route matches [GET] "/entrees/new/32"
The question is, how can I declare the Entree resource in the routes file with a parameter for the new action ?
I'm not sure if that's a hack or not, but the following works and seems cleaner than 2-levels nesting.
resources :entrees, :except => [:new] do
collection do
get 'new/:id', :to => "entrees#new", :as => 'new'
end
end
Now I can do a render "new" instead of a redirect_to.
I must say that I must have asked my question wrongly, my bad.
Rails has a route helper called path_names that does this:
resources :entrees, path_names: { new: 'new/:id' }
To improve gwik 's solution (which in fact didn't work for me):
resources :things, except: [:new] do
new do
get ':param', to: 'things#new', as: ''
end
end
It gets you new_thing_* helpers (instead of new_things_*) for free.
If you want to use Rails resource routes, you will have to nested them according to how they work
resources :caves do
resources :entrees
end
to get the route /caves/70/entrees/new
Otherwise, you are in a world of creating manual match routes.
match "/entrees/new/:id", :to => "entrees#new", :as => 'new_entrees'
I do not understand why you are forced to use a redirect? The new_entrees route is valid. You will not be able to use the form_for helper, since it is not a resource, but the form_tag helper will work.
UPDATE: Render and Route
The Route does not directly change what view is rendered in the Controller. That is determined by the controller itself. Render examples:
render :new will render the new action's view
render 'entrees/new' will render the entrees/new template
I found this generates the correct new_thing_path method not new_things_path as Antoine's solution.
resources :things, :except => [:new] do
with_scope_level(:new) do
get 'new/:param', :to => "things#new", :as => ''
end
end
First off, I'm using rails 3.0.8 with friendly_id 3.2.1.1.
I'd like to be able to view the posts at website.com/:title, so drop the "/posts".
But I'd also like to have an /admin view. From there, a user should be able to create/edit/destroy posts. I already have a admin.html.erb view with links to various actions.
Right now my routes file look like:
MyApp::Application.routes.draw do
root :to => 'posts#index'
resources :posts
match "/:id" => "posts#show"
match "/admin" => "posts#admin"
end
This works for website.com/:title, but for website.com/admin I get an error:
Couldn't find Post with ID=admin
.... which makes sense. But I'm not sure how to solve this problem.
The rules are run through top to bottom. So put your admin rule on top of the resource definition.
If you put /admin first then it will work (as noted by cellcortex). You can also use :constraints if you can neatly separate your :id from 'admin'; for example, if your :id values are numeric, then something like this should work:
match '/:id' => 'posts#show', :constraints => { :id => /\d+/ }
match '/admin' => 'posts#admin'
In a simple case like yours, putting things in the right order will work fine. However, if your routing is more complicated, then the :constraints approach might work better and avoid a some confusion and chaos.
Use this
resource :posts, :path => '/'
with this all of your article will be directly under root
So in Posts Class you may add this:
def to_param
"#{id}-#{title.parameterize}"
end
I would like to pass an extra parameter to a member route of a resource
something like:
resources :events do
member do
get 'register/:participant_type_id'
end
end
I could only accomplish it using a static match statement
Looking around the internet I saw that this might be possible in Rails 3.0.2. I'm using 3.0.1 and it certanlly is not.
Am I doing something wrong? or is it really not possible?
thanks
Try this:
resources :events do
member do
get 'register/:participant_type_id', :action => 'register'
end
end
Just to complete the answer with my little findings. It also confused me for quite a while.
In Rails3, the member route with parameters will not have the automatic generated xx_yy_path helper. You need to add it providing the :as => part, omitted the resources name.
Regarding the example provided, to get register_event_path and register_event_url, you need to define it like the following:
resources :events do
member do
get 'register/:participant_type_id', :action => 'register', :as => 'register'
end
end
I've read the documentation, but I'm still not sure I understand everything.
Especially why there's a :new parameter. As far as I understand, it could be replaced with the :collection parameter.
So what's the difference between those three types of routes?
The difference is the URL generated.
Let's guess three resources :
map.resources :users, :collection => { :rss => :get }
map.resources :users, :member => { :profile => :get }
map.resources :users, :new => { :draft => :get }
The first route will create :
/users/rss
With nothing between the controller name and the action name. We don't need any other parameter to get the user's list rss feed.
The second one will create the action "profile" as a member of the object. So we'll have :
/users/1/profile
The "1" is the user's to_param. We need a user's id to display a profile.
The third one will create the action "draft" as a member of the new action. So we'll have :
/users/new/draft
The "draft" action displays a draft of the user before accepting its creation.
So that's the difference between :collection, :member and :new. Every of them creates different routes, each one with their own purpose.
:member creates path with pattern /:controller/:id/:your_method
:collection creates path with the pattern /:controller/:your_method
:new creates path with the pattern /:controller/:your_method/new (please note that the last element of the path i.e. new is constant)
New differs from Collection mainly on the ideological layer. That's how REST gurus see the creation of the REST "subresource" within the bigger resource.
Damiens explanation is mostly right except for the section about :new
Have a really good read of the ruby on rails routing guide at http://guides.rubyonrails.org/routing.html It explains routing from the inside out, and then back again. Section 3.11.3 (Adding New Routes) describes what :new does, and it is very different to :member and :collection.
Basically map.resources :photos, :new => { :upload => :post } will create /photos/upload using the POST HTTP verb.
I'm struggling here with a problem:
I have a controller questions which has action new.
Whenever I need to create new question, I'm typing
/questions/new
What changes to routes.rb should I make to change the URI to
/questions/ask
Thank you.
Valve.
Try this:
map.ask_question '/questions/ask', :controller => 'questions', :action => 'new'
Then you'll have a named route and you can:
link_to "Ask a question", ask_question_path
If you are using RESTful routes maybe you'd like to use map.resources for your questions.
To rename the action urls you may do this:
map.resources :questions, :path_names => { :new => 'ask', :delete => 'withdraw' }
(I added delete for the sake of the example)
Which version of rails?
Generally the default route should catch anything like /:controller/:action, so you could just create an ask method in your questions controller. Take a look at the api documentation for named_route and map_resource if you want something a bit smoother to work with.