Step 5) Encapsulation via Partials

As aforementioned, Middleman makes use of the ERB templating language. In so many words, we can embed Ruby code into our HTML in order to do magical things like:

Render partial templates (a.k.a, a way of sharing content across pages to avoid code duplication) Iterate over a set of data (e.g., generate “cards” based on a list of real data from our application)

In our example, we have a card layout with several dynamic elements, including the tweet body, avatar image, and associated hashtags. And we’ve hardcoded a sample card in index.html.erb.

Now, let’s create a file called _card.html.erb inside of our source directory. And let’s cut/paste our hardcoded HTML from above into that file, resulting in a blank index.html.erb file.

Wherever there’s a hard-coded value (e.g., @kittycat, or “You call this cat food…”), we’re going to instead use ERB to tell Middleman: Hey! We’d like this value to be interpreted dynamically whenever the partial is rendered. And so, we get something like this:

<div class="card sm-col-8 md-col-7 lg-col-6 col-11 mx-auto border border-silver bg-white mb2">

<div class="card-body p2">

<div class="media-object clearfix">

<div class="avatar left mr2">

<img src="<%= avatar %>" alt="">

</div>

<div class="tweet overflow-hidden">

<h1 class="m0"><%= name %></h1>

<p class="h3 mt1 mb0"><%= tweet %></p>

</div>

</div>

</div>

<div class="card-footer p2 flex items-center justify-between border-top border-silver">

<ul class="inline-list list-reset m0 gray">

<% hashtags.each do |hashtag| %>

<li class="inline-block mr1"><%= hashtag %></li>

<% end %>

</ul>

<button class="bg-white border-none gray">

<i class="material-icons">favorite_border</i>

</button>

</div>

</div>

Which means whenever we choose to render this partial, we get to pass through — as variables — an avatar, a name, a tweet, and a list of hashtags.

So, inside of your empty index.html.erb write the following code.



:name => '

:avatar => '

:tweet => 'You call this cat food? lick the curtain just to be annoying. Run in circles. Purr while eating a nice warm laptop for me to sit on so kitten is playing with a dead mouse',

:hashtags => ['#catnip', '#kitties', '#mouse']})

%> {:name => ' @kittycat ',:avatar => ' http://placekitten.com/g/80/80' :tweet => 'You call this cat food? lick the curtain just to be annoying. Run in circles. Purr while eating a nice warm laptop for me to sit on so kitten is playing with a dead mouse',:hashtags => ['#catnip', '#kitties', '#mouse']})%>

Save, refresh, and pat yourself on the back for encapsulating your card component via a partial.

Uhh, it looks exactly the same, you ask? That’s the point.

There are many benefits to this approach. Reducing code duplication is an immediate and obvious one, but one that has deeper ramifications. With an encapsulated component, if we’d like to adjust a particular style or attribute (e.g., change the font size of the tweet body), we only have to tweak one line of code in one single file.

On a more meta level, this example illustrates how code offers a lovely convention for expressing the intent behind our design decisions: that is, by allowing us to abstract away our various design decisions and implementation details, and surfacing a name that is descriptive of the component we’ve built.

Step 6) Iteration

Here comes the fun part.

Earlier, I scribbled a list of the elements that were dynamic, or interchangeable from card to card. This exercise was helpful in identifying which values were to become variables in our partial template.

We can take this one step further by imagining for a brief moment that we’re building out a real web application, where we need to show a dynamic list of tweets on the page.