Pat S
Pat S

Reputation: 490

Trying to get two actions to have different views, but the same URL

I have an app with shepherds (i.e. the users) and each shepherd has a set of animals. I am trying to make it so that if the logged in shepherd tries to view one of their animals it takes them to a view controlled by the edit action. Alternatively, if the shepherd tries to view another shepherd's animals it gives them a view controlled by the show action. I'd prefer to not have URLs with */edit - I want them to look the same for edit and show. In my routes.rb file I have this...

get '/shepherds/:username/:eartag', to: 'animals#show', as: :shepherd_animal_show
get '/shepherds/:username/:eartag', to: 'animals#edit', as: :shepherd_animal_edit

In the shepherd's show view I create a link to their animals like this...

<% if animal.shepherd == current_shepherd %>
    <a href="<%= shepherd_animal_edit_path(username: animal.shepherd.username, eartag: animal.eartag) %>"
<% else %>
    <a href="<%= shepherd_animal_show_path(username: animal.shepherd.username, eartag: animal.eartag) %>"
<% end %>

I can see that when I'm logged in and try to access my animals, it goes into the block with the shepherd_animal_edit_path, but it directs me to the show view rather than the edit view. Here's part of the output of the routes...

shepherd_animal_show GET    /shepherds/:username/:eartag(.:format)  animals#show
shepherd_animal_edit GET    /shepherds/:username/:eartag(.:format)  animals#edit

I'm a bit of a beginner at Rails and would really appreciate any help people can offer.

Upvotes: 0

Views: 52

Answers (1)

soupdog
soupdog

Reputation: 335

I think you should be using the show action for both, and just rendering a different template depending on the animal ownership. I.e.:

def show
  ...
  render 'edit' if animal.shepherd == current_shepherd
  # the show template will be rendered automatically if `render` wasn't explicitly called
end

Then in your view, you can unconditionally link to the show action, and the controller will take care of deciding which view template to render.

Also, FWIW, I would probably define the routes as follows:

resources :shepherds, shallow: true do
  resources :animals
end

And then use the link_to helper in the view instead of hard-coding HTML tags:

<%= link_to animal_path(animal) %>

But that would then allow you to do other things like:

link_to shepherd_animals_path(@shepherd) # link to the `index` action of `AnimalsController`, with `params[:shepherd_id]` set to `@shepherd.id`. 

That would then allow you to render (or not render) other controls for the shepherd to manage his/her own flock if current_shepherd.id == params[:shepherd_id] (or current_shepherd == Shepherd.find(params[:shepherd_id])).

Upvotes: 1

Related Questions