0

Usually the recommended solution is content_for in the parent layout file. But this results in having to specify it in every view since the default becomes not displaying it if the content is not present in the child view partial.

For example, if I have a sidebar that I want to hide in authentication pages, but have it everywhere else, I now have to specify content of the sidebar in every view file except the authentication pages. Not DRY.

This is much more cumbersome and not dry than before, where I could render a sidebar partial in the layouts and be done with it (but not have the benefit of choosing where it does or doesn't render).

It would be nice if you could somehow specify in the layouts template that calls the sidebar partial to not tender if it's a session controller or devise controller.

Is there any way to do this? I've tried using

unless devise_controller?
  render "layouts/sidebar"

But this doesn't seem to work as intended.


Taking an example with Devise, I have an application.html.slim file like so

.row
  main
    .col-sm-9
      = yield
    - unless devise_controller?
      .col-sm-3
        == render 'layouts/sidebar'

Ignore the columns for a moment. The main point is that the =yield renders normal templates as well as the devise templates. So I can't selectively disable the sidebar in one DRY stroke. I would have to put the sidebar render call in every view file, but not include it in my devise views. That's no better or DRYer than using content_for in every non-devise view file.

And getting back to the columns, I would like to have the yielded devise views full width of 12 columns, not 9 columns. But that's just bonus, not the main question.

ahnbizcad
  • 10,491
  • 9
  • 59
  • 85
  • 1
    You can have a special layout for auth pages where you will not render the sidebar, no? – Sergio Tulentsev Oct 07 '14 at 13:32
  • If you're referring to the devise view files, I think not. I have a `=yield` in the application.html file, which renders the devise view templates. So the devise views are subject to the styling of its parent. Let me put some more code in the OP. – ahnbizcad Oct 07 '14 at 13:35
  • Can you provide me some specifics for what you're talking about? @Sergio Tulentsev? I don't know which file it is, or what design pattern you have in mind. – ahnbizcad Oct 07 '14 at 13:41
  • You can subclass devise controller and specify a custom layout, I think. – Sergio Tulentsev Oct 07 '14 at 13:42
  • 1
    https://github.com/plataformatec/devise/wiki/How-To:-Create-custom-layouts – Sergio Tulentsev Oct 07 '14 at 13:43

2 Answers2

1

If you insist on checking the controller name you can do this:

<% if controller.controller_name == 'devise' %>
...
<% else %>
  <%= render 'sidebar' %>
<% end %>
NM Pennypacker
  • 6,704
  • 11
  • 36
  • 38
  • I only insist on having one dry `if` condition. It seems a bit more straight forward than doing a devise layout. Maybe I'm overestimating the complexity. – ahnbizcad Oct 07 '14 at 14:01
  • That code isn't working for me. It must be the same reason why `devise_controller?` isn't working either. – ahnbizcad Oct 07 '14 at 14:43
  • 1
    You might have to tweak the == 'devise part'. Have you tried just outputting the controller name like this <%= controller.controller_name %> and checking against that. Also, it might be registrations controller. Play around with it a bit. – NM Pennypacker Oct 07 '14 at 14:57
1

I simply implemented the verbose way of doing things. I'll use a complex example since it might be more helpful.

Here, I set up the full cases, depending on whether I want a sidebar or not, mainly because of the way bootstrap columns and rows work. If you're using bootstrap, you'll notice that once you prevent the sidebar from rendering, you'll be left with the rest of the main content not taking the space that the sidebar no longer takes. This is because you previously had to put the sidebar and main content in a specific column width, and those in a row (so that they appear side by side). Since you want the main content to fill and take the full width when the sidebar is gone, you have to apply completely different column widths in that case. Hence the full if - else statement.

Thus, implement it like so, making sure to include .rows and .col-*-* in each of your main yielded view files.

application.html

  - if hide_sidebar?
    main
      = yield
  - else
    .row
      .col-xs-12.col-sm-9
        main
          = yield
      .col-xs-12.col-sm-3
        == render 'layouts/sidebar'

If the list of pages you wish to have or not have a sidebar becomes more complex than simply all of the actions of a certain controller, implement a separate helper method specifying all the conditions.

This is one way to do it, in the controller. In my example, I want to hide the sidebar when it's the registrations controller and when it's the show action of the users controller. I just || each out in the helper method.

application_helper.rb

def want_sidebar?
  (controller_name == 'registrations') || ( (controller_name == 'users') && action_name == 'show' )
end
ahnbizcad
  • 10,491
  • 9
  • 59
  • 85