2
votes

I have a layout with common elements in the side bar per page (some of the elements are common to most pages, some are unique for some pages).

--------------------------------
|                   | side box |
|                   |          |
|                   |__________|
|                   | side box |
|                   |          |
|                   |__________|
|                   | side box |
|                   |          |
|                   |          |
--------------------------------

Right now the way I do it is include a shared/sidebar_type partial from the views. The sidebar partial further includes the individual box partials that type of page should display.

1) What's the best way to segment and include these partials and customize which boxes of content are shown on the side page based on each page?

2) Best practice for setting objects and passing them onto those partials (the sidebar boxes) for output

For data used by the side boxes I'm referring to here. Should it go in a master controller as global variables which all other controllers inherit? etc.

I'm new to Rails from the PHP world and proper organization of these shared partials is slightly confusing. The way I'm currently passing objects to those box partials seems half-assed.

2

2 Answers

2
votes

Well. Just an idea: You could have a _side_bar partial which, in turn, includes all the _side_box partials determined in an array initialized in the controller method. So you could have something like this:

Controller:

...
def some_method
    @side_boxes = ["side_box_1", "side_box_2", "side_box_3"]
    ...
end
...

some_method.html.erb (or in layouts/application.html.erb if you want it in all pages):

...
<%= render :partial => 'shared/side_bar' %>
...

_side_bar.html.erb:

...
<% @side_boxes.each do |partial_name| %>
    <%= render :partial => "shared/#{parial_name}" %>
<% end %>
...

Then you'd have to have _side_box_1.html.erb, _side_box_2.html.erb, etc...

To answer the second part of your question: if you want to pass arguments to a partial, you can give the hash parameter :locals to the render function. Like so:

<%= render :partial => 'foo/bar', :locals => {:arg_1 => "argument1", :arg_2 => "argument2"} %>

Then you can use those parameters in the _bar.html.erb partial like local variables:

<%= arg_1 + " " + arg_2 %>
#=> argument1 argument2

Hope this helps!

EDIT

If the sidebars are going to be rendered throughout the site, you might want to have a method get_side_boxes in your ApplicationHelper (app/helpers/application_helper.rb). This way, you just put this in your layouts/application.html.erb:

<% @side_boxes = get_side_boxes %>

and it'll be called every time a page loads. Then in your ApplicationHelper, you'd have to define the behavior of that function so it gets the side_boxes for the specific controller action you're rendering. It would be something like this:

ApplicationHelper

def get_side_boxes
   action = params[:action]
   controller = params[:controller]
   model = controller.classify #This will return the class name corresponding to that controller
   model.constantize.get_side_boxes(action) #This will return whatever the CurrentModelName.get_side_boxes returns
end

Then in each model (or at least the ones that have controllers that render side_boxes), you'd have to implement a get_side_boxes method that returns the appropriate array of partial names depending on the action that is passed to it. Something like

SomeModel

def self.get_side_boxes(action)
    side_boxes = Array.new
    case action
        when "index"
            side_boxes = ["side_box_1", "side_box_2"]
        when "new"
            side_boxes = ["side_box_3"]
        when "edit"
            ...
        ...
    end
    side_boxes
end

Then you wouldn't have to call anything in the controllers.

1
votes

I'm about to do something similar in my own app right now but came on here to procrastinate a little first. I'm going to use Cells for creating the sidebars. And I will also need some logic to ensure that the Latest News cell doesn't appear on the News Index, or that the Recent Images cell doesn't appear on the Images page etc.. I will post my results later but something like this will do that:

- ["videos", "podcasts", "news", "mixes"].each do |cell|
  = render_cell cell, :recent unless controller.controller_name == cell