0

I am using form_for in the _form.html.erb view in order to create my form for both the edit and new actions, as per a standard scaffold.

I have a model Owner which has_many pets.

I would like to put an html link on my views/owners/show.html.erb to create a new pet for said owner. This link will point to the new action of pets_controller.rb which when accessed will render the view in pets/new.html.erb

What I want to happen is for the the owner_id to be passed with the link in the url to the new action of pets_controller.rb and then be used as the default for a collection_select in pets/new.html.erb

So I have a link to create a new pet but because that link was on a specific owner page, I want the form to create a new pet to have that owner already set, so the user does not have to select from the list.

This has to be done without changing the behaviour of the edit action/view in pets.

I know that I can pass GET arguments then access them in the controller via params, then create variables in the action which are passed to the view. I can then manually check for a default and set it in the view. I do not need assistance in coding if this is the only solution.

Is there is a better way to do this? A format with which I can pass the params such that the view will just pick them up? Without manually editing my controllers and views?

coderz
  • 4,847
  • 11
  • 47
  • 70
Axiombadger
  • 161
  • 10
  • I suppose you could throw that `Owner` data in the session or a cookie and grab it on the `form` page via AJAX lookup. Seems roundabout though and I would go with the solution you provided. – Joe Essey Apr 29 '15 at 14:48

2 Answers2

2

While my personal inclination would be to do as you said and pass a parameter in the link helper and then access the params array in the pets view, you may find that this is the perfect opportunity to explore Nested Resources. Essentially, you could declare owners/:owner_id/pets/:pet_id route with:

resources :owners do
  resources :pets
end

You could then link to this route, and reference :owner_id without having to append the query string to the URI (making somewhat cleaner for reuse).

This is likely more work for you, but also potentially more extensible (and certainly more inline with the Rails way of doing things).

REVISION

Added the following regarding link helpers to the comments, but wanted to reflect it in the answer as well.

To show a pet should be:

<%= link_to owner_pet_path( owner_variable, pet_variable) %>

To view pets' index index should be:

<%= link_to owner_pet_path( owner_variable ) %>

The answer given to this question is fantastic.

Community
  • 1
  • 1
ConnorCMcKee
  • 1,625
  • 1
  • 11
  • 23
  • Thanks, this looks interesting. I will try it. – Axiombadger Apr 29 '15 at 16:40
  • Am I correct in thinking that it should be `resources :owners do` though? – Axiombadger Apr 29 '15 at 16:51
  • Yes, my apologies (amending answer now) – ConnorCMcKee Apr 29 '15 at 16:52
  • This is all working exactly as I needed so thank you. One final part if I may, what is the correct way to use link_to for this nested route? – Axiombadger Apr 29 '15 at 19:37
  • 1
    Glad to hear it! To show a pet should be: `<%= link_to owner_pet_path( owner_variable, pet_variable) %>` To view pets' index index should be: `<%= link_to owner_pet_path( owner_variable ) %>` The answer given [to this question](http://stackoverflow.com/questions/1548009/rails-link-to-routes-and-nested-resources) is fantastic. I hope that clears up any questions! – ConnorCMcKee Apr 29 '15 at 20:10
1

As @ConnorCMcKee suggests it would be wise to consider nesting your routes. However, if you are a beginner as myself I found that it helped my learning to simply nest my second controller into the first (i.e. nest PetsController into OwnersController) as a first step. Then afterwards I would continue with the routes.

The method would be something like:

1./ In owners/index.html.erb:

Links to PetsController index action

The key to make this work is to send the :owner_id in your link parameters. Then that Pets index action will have access to that :owner_id and know which :owner_id called it.

2./ In PetsController you would then be able to find that Owner using that id, like so:

params[:owner_id]

Then your actions can start to take advantage of knowing what Owner called them. Remember though that all your redirects inside your PetsController need to preserve params[:owner_id]. That is because once you are inside that nested structure you have to maintain it and stay inside it and always know which :owner_id you are working with.

ljnissen
  • 139
  • 1
  • 12
  • Thanks for taking the time to reply. I will keep this method in mind in case something else crops up although for this simple example the answer by @ConnorCMcKee above has solved my issue. – Axiombadger Apr 30 '15 at 00:51