Design pattern for side bar with dynamic content in Rails
Asked Answered
S

3

5

I would like to have a right side bar with content changes for each page. For example, when I am in Friends page, the side bar should display New Friends. When I am in Account page, the side bar should display Recent Activities.

How should I go about this to respect Rails design patterns? I heard about Cells gem, but I am not sure if I use it.

Succeed answered 24/12, 2011 at 17:4 Comment(0)
D
8

here is one way, in your layout add a named yield section

<div id="main-content">
    <%= yield %>
</div>
<div id="side-content">
    <%= yield(:side_bar) %>
</div>

Then in your views put content into the named yield using content_for

# friends view ....
<% content_for(:side_bar) do %>
    <%= render :partial => "shared/new_friends" %>
<% end %>

# account view ....
<% content_for(:side_bar) do %>
    <%= render :partial => "shared/recent_activity" %>
<% end %>    

this requires you to be explicit about what content appears in the side bar for every view, maybe having it do it dynamically is better? probably depends on the specific situation and your preference

see also - http://guides.rubyonrails.org/layouts_and_rendering.html#understanding-yield

Demimonde answered 25/12, 2011 at 18:54 Comment(0)
S
6

I came by this question in a moment of a big design change in our views. After thinking about the sidebar problem a bit, I realized that there's no best solution (as always). There are better solutions for each case.

I'll compare 3 solutions here:

  1. using content_for(:sidebar) and yield(:sidebar)
  2. using the partials approach
  3. using the Cells gem

1. Using content_for(:sidebar) and yield(:sidebar)

This is good for cases when each link (each controller action) you access renders a different sidebar. In this case, each view you access will have the content_for(:sidebar) part.

If your sidebar view depends only on the state of some variable in the session, for example, the sidebar should not be rendered for every link you access. Then you should use a good caching system like turbolinks, to avoid rendering many times the same thing, or use something like the Cells gem with a javascript to render only the main part of the layout.

2. Using partials

Using partials is always good to eliminate duplication. If your sidebar is very simple and is changed for every controller, you can render it as a partial. But if you're rendering different partials in the same controller, according to some state, it may be an indication that you have business logic in your views, which should be avoided.

3. Using the Cells gem

Very good design pattern when you have to render your sidebar from a different controller than the rest of the view each time.

It takes a lot of business logic out of the view, which sure is a good practice.

Here you have an action calling a view. Inside that view, there is a statement render_cell(:sidebar, params). This statement will do some business logic and render the view of the sidebar. It's as if the first action called other controller actions to render specific parts of your view (called cells)

If you make changes to the sidebar only, you may have to create other simple action, so that a javascript will request it. This action will call the render_cell(:sidebar) method again to respond with the view.

It's a very interesting approach.


Other ideas:

  • Your sidebar could be rendered only with javascript from the same action.
  • Your sidebar could be rendered by an angular controller, and rails sends jsons with the sidebar objects. (look for "One page apps")
Selfloading answered 21/5, 2015 at 13:40 Comment(0)
M
2

try something like this

<div class="sidebar">
    <% if current_page?(controller => "friends", :action => "show") %>
        <h4>New Friends</h4>
    <% elseif current_page?(controller => "accounts", :action => "show") %>
        <h4>Recent Activities</h4>
    <% end %>
</div>

If the above code fits what you are trying to do(looks like this is what you want to achieve), then stick with it, else it may be beneficial to go with some gems. Also checkout helper page on how to use current_page? method. Hope it helps

Makebelieve answered 24/12, 2011 at 20:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.