How to declare a rails resource with a parameter f

2019-02-16 15:09发布

问题:

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 ?

回答1:

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.



回答2:

Rails has a route helper called path_names that does this:

resources :entrees, path_names: { new: 'new/:id' }


回答3:

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.



回答4:

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


回答5:

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