Dumb views?

Hello again! I’ve another “what would you do in this situation”
question.

You’ve got 6 controllers, one named base. The other 5 controllers extend
base. Currently they share one layout.

Your layout displays navigation. However, there are two actions inside
base
for which you do not want navigation displayed (index, new).

Do you…

a) Add logic to your layout telling it to conditionally display the
navigation.
b) Create an entirely different layout with no navigation and have the
actions in question arbitrarily render that layout.

Let’s hear it! :slight_smile:

  • Rabbit

On Aug 1, 2006, at 1:53 PM, Rabbit wrote:

Do you…

a) Add logic to your layout telling it to conditionally display the
navigation.
b) Create an entirely different layout with no navigation and have
the actions in question arbitrarily render that layout.

Let’s hear it! :slight_smile:

What about:
c) have navigation() be a helper function called from the layout that
can be over-ridden in the appropriate helper class or controller
method (just remember to make it protected)

-Mat

Hmm… I had thought about making a helper method for navigation, but
thought it was too much like option A - logic in the view.

However, I kinda dig your idea of overwriting it for specific parts of
the
application. And I suppose if it were in a helper then I could define
which
“tab” is the active one. I’ll try that.

Thanks Mat. :slight_smile:

  • Rabbit

Here’s what I’ve got for a first-run:
http://rafb.net/paste/results/myCYgs62.html

For some reason, it feels very PHP-ish. Any thoughts?

  • Rabbit

What’s bottom posting? I’m accessing the list via Gmail… I just
checked
out what the thread looks like on Ruby Forum and it doesn’t look
confusing
to me. =/ (Or are you suggesting I quote what I’m referring to?)

Anyway, yeah that’s a lot, but it’s also wicked. Sadly I’ve never
thought
about calling render() from a helper. :slight_smile:

I’ll spend some time on your suggestions and let you know how it turns
out.

Thanks again Mat, you rock! :slight_smile:

  • Daniel

On Aug 1, 2006, at 2:53 PM, Rabbit wrote:

Here’s what I’ve got for a first-run:
http://rafb.net/paste/results/myCYgs62.html

For some reason, it feels very PHP-ish. Any thoughts?

  • Rabbit

First thought: bottom post :slight_smile:

The first things we can try to get rid of is that “tabs” variable.
Sadly, the pattern isn’t exactly consistent so we have to get
tricky. But we do have a little bit of patterning going on in
everything except calendar.

You can factor that out (at it’s simplest idea) by adding a method
like so
[‘Calendar’, ‘Schedules’, ‘Blackouts’, ‘Ticket Templates’, ‘Venue
Layout’].each do |tab|
if current_page?(location_for_name(tab))
…link to…
else
…link to…
end
end

location_for_name would turn ‘Ticket Templates’ into
‘ticket_templates’ by string manipulation (there may already be a
method somewhere for this) and have a special case for Calendar.

Finally, I dislike html in methods, so you might want to consider
embedding this logic into a layout partial with some imbedded code.
The final function might be something like:

def navigation
@tabs = ‘Calendar’, ‘Schedules’, ‘Blackouts’, ‘Ticket Templates’,
‘Venue Layout’]
render :template => ‘layouts/navigation’
end

def location_for_name tab_name
if tab_name == ‘Calendar’
{ :controller => ‘tickets’, :action => ‘calendar’ }
else
{:controller => tab_name.gsub(’ ', ‘_’).downcase, :action => ‘index’ }
end
end

def link_for_name tab_name
if current_page?(location_for_name(tab))
link_to tab_name, location_for_name(tab_name), {:class => “active”}
else
link_to tab_name, location_for_name(tab_name), {:class => “active”}
end
end

with navigation.rhtml being

    <% for tab in @tabs do %>
  • <%= link_for_name tab %>
  • <% end %>

The moral of the story is: Ruby makes introducing new functions easy
and quick. So do it.

To make this even cooler and more ruby-ish, we could make all the
controllers subclasses of some parent that had an inherited()
function defined and kept track of it’s children. Then instead of
loose functions, we can call .as_link or .title or .location on the
controller classes themselves. Doing this would yield a
naviation.rhtml like:
<% for controller in MainController.children do %>

  • <%= controller.to_link %>

  • <% end %>

    MainController then contains the munging functions and the Tickets
    controller (the oddball) overrides .name and .location with it’s own
    idea of what a tab should be.

    Wow… that was a lot. Sorry if I’m confusing you.

    -Mat

    On Aug 1, 2006, at 4:36 PM, Rabbit wrote:

    Thanks again Mat, you rock! :slight_smile:

    I like to help. And it was an issue I tackled not long ago. As for
    bottom posting…

    See how I’m placing messages under the quoted text? That’s bottom
    posting. You’re top posting. What you’re reading on google is also
    a mailing list, so bottom posting helps list subscribers (like me)
    follow the conversation more easily.

    An example that cracked me up:

    A: Indeed it does!
    On Aug 1, 2006, at 12:00 PM, A Dude wrote:

    Q: Does top posting suck?

    I’m sure you can see, it’s much easier to read the question first,
    then the answer, rather than the reverse.
    -Mat

    On Aug 1, 2006, at 4:36 PM, Rabbit wrote:
    See how I’m placing messages under the quoted text?

    Yes. :slight_smile:

    You’re top posting.

    Not anymore!

    • Daniel

    Alright. Let’s see…

    First up, in my base controller I’m already using a before_filter. So
    I’ve defined my tabs there… (I hope all this code comes out okay)

    productions.rhtml (layout)


    <%= navigation %>

    base_controller.rb (controller)

    def load_production
    @tabs = [ ‘Calendar’, ‘Schedules’, ‘Blackouts’, ‘Ticket Templates’,
    ‘Venue Layout’ ]
    session[:production_id] = params[:id] if params[:id]
    @production = Production.find(session[:production_id])
    rescue
    flash[:negative] = %{Oops, couldn’t find a valid production.}
    redirect_to(:controller => ‘base’)
    end

    base_helper.rb (helper)

    def link_to_tab(tab)
    if current_page?(path_for_tab(tab))
    # Active tab.
    link_to(tab, path_for_tab(tab), { :class => ‘active’ })
    else
    link_to(tab, path_for_tab(tab))
    end
    end

    def path_for_tab(tab)
    case tab
    when ‘Calendar’
    { :controller => ‘tickets’, :action => ‘calendar’ }
    else
    { :controller => tab.to_id, :action => ‘index’ }
    end
    end

    def navigation
    html = ‘

      @tabs.each do |tab|
      html << %{

    • } << link_to_tab(tab) << %{
    • }
      end

      html << ‘


    end

    (I injected a bit of html in my helper, shoot me! :slight_smile:

    The #to_id method is an extension of string I wrote. (With inspiration
    from this very mailing list.)

    class String

    def to_id
    downcase.gsub(/\W/, ’ ‘).squeeze.strip.gsub(’ ', ‘_’)
    end

    end

    As a added bonus, using an array instead of a hash lets me arbitrarily
    order the nav items!

    Once again! thanks Mat. :slight_smile:

    • Daniel