3
votes

I have a couple of views I'd like to have appear on every view that is rendered, but short of duplicating code or breaking the specifications, I can't seem to find a way to accomplish this.

Here's my current code, putting calls in every view:

def ImOnABoat::Views
  def layout
    html do
      head do title "Petstore" end
      body do yield end
    end
  end

  def navigation
    p "Welcome to our tiny petstore!"
  end

  def poodle
    navigation  # Have to duplicate this in every view
    p "We have a poodle!"
  end

  def fluffy_bunny
    navigation  # Have to duplicate this in every view
    p "Come see-- OH CRAP IT'S A VELOCIRAPTOR!"
  end
end

I can also make it work by allowing the common blocks to render outside the body, but this is against specification and will probably end up horribly breaking some scraper scripts down the road.

def layout
  def head do title "Petstore" end
  nav  # This is not inside <body>!
  def body do yield end
end
2

2 Answers

5
votes

This could be accomplished using rails layouts and rendering partials in the layout. Reducing the need for such 'building' and making management easier.

http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials

2
votes

Remember that this is plain Ruby, so you can simply call the navigation method in the layout:

module ImOnABoat::Views
  def layout
    html do
      head { title "Petstore" }
      body do
        navigation
        yield
      end
    end
  end

  def navigation
    p "Welcome to our tiny petstore!"
  end

  def poodle
    p "We have a poodle!"
  end

  def fluffy_bunny
    p "Come see-- OH CRAP IT'S A VELOCIRAPTOR!"
  end
end