Search code examples
ruby-on-railsruby-on-rails-3nested-resources

How do I setup the views for nested resources that are displayed as tabs within their parent resource in Rails?


I have a resource Company that has many Projects and People. The index action for the companies displays each company in a table. The show action shows some additional information about it, and then what I'd like to show is another table, with tabs "Projects" and "People".

When I click on the "People" tab, I should go to URL "companies/:id/people", and likewise for the "Projects" tab. I'm not worried about AJAX or pre-loading all of this information into the @company variable during the show action. A simple nested resource is fine.

Now when I'm at "companies/:id/people", it will use PeopleController#index, but I want to show that view (which is JUST it's table, I suppose?) nested within the company's show view. So that when I switch between "companies/:id/people" and "companies/:id/projects", the only thing changing is the table, not the company information around the outside.

Is this sort of thing easily do-able? If Rails isn't build to handle this sort of thing easily, I don't mind using something else. I just don't have much experience with the view layer, so I don't know much about it since I primarily work with JSON.


Solution

  • Basic Example:

    ProjectsController && PeopleController:

    layout :current_layout
    
    def current_layout
      if @company && @company.persisted? && request.path_parameters[:action] == "index" # i prefer helper 'current_action'
        "company"
      else
        "application"
      end
    end
    

    Helper:

    def parent_layout(layout)
      @view_flow.set(:layout, self.output_buffer)
      self.output_buffer = render(:file => "layouts/#{layout}")
    end
    

    Company layout:

    #views/layouts/company.html.erb
    
    <h1><%= @company %></h1>
    <ul class="tabs">
     <li>Info</li>
     <li>Info</li>
     <li>Info</li>
    </ul>
    <%= yield %>
    <%= parent_layout(:application) %>
    

    People template:

    # views/people/index.html.erb
    
    <% if current_layout == "company" %> # just table
      <%= render "people_table" %>
    <% else %>
      <h1>People controller</h3>
      <%= render @people %>
    <% end %>
    

    Projects template:

    # views/projects/index.html.erb
    
    <% if current_layout == "company" %> # just table
      <%= render "projects_table" %>
    <% else %>
      <h1>Projects controller</h3>
      <%= render @projects %>
    <% end %>