|
| 1 | +--- |
| 2 | +title: Sinatra layouts |
| 3 | +--- |
| 4 | + |
| 5 | +One of the most important principles in software engineering is to stay [DRY](http://en.wikipedia.org/wiki/Don't_repeat_yourself): **don't repeat yourself**. |
| 6 | + |
| 7 | +The basic idea is that you don't want to be copying and pasting the same code into multiple places. If you're doing this, you're making a lot of work for yourself should you ever decide to change that code. |
| 8 | + |
| 9 | +One way of staying DRY that we'll meet soon is writing functions: if there's a task that you do repeatedly, write a function to put the logic for that task in one place and then call the function when you need to do the task. |
| 10 | + |
| 11 | +Another way, that we'll be looking at today, is in the form of layouts. |
| 12 | + |
| 13 | +### The Problem |
| 14 | + |
| 15 | +In the exercise today, you've been using a lot of erb view templates. You have 4 different templates, which all share the same basic outline: |
| 16 | + |
| 17 | +{% highlight html %} |
| 18 | +<!-- in views/index.erb --> |
| 19 | +<!DOCTYPE html> |
| 20 | +<html> |
| 21 | +<head> |
| 22 | + <title>Event Manager 2.0</title> |
| 23 | +</head> |
| 24 | +<body> |
| 25 | + |
| 26 | + <h1>Picture Unveiling Evening - Event Managment</h1> |
| 27 | + |
| 28 | + <ul> |
| 29 | + <li><a href='/todos'>Todo list</a></li> |
| 30 | + <li><a href='/schedule'>Event schedule</a></li> |
| 31 | + <li><a href='/rsvps'>RSVPs</a></li> |
| 32 | + </ul> |
| 33 | + |
| 34 | +</body> |
| 35 | +</html> |
| 36 | +{% endhighlight %} |
| 37 | + |
| 38 | +{% highlight html %} |
| 39 | +<!-- in views/todo.erb --> |
| 40 | +<!DOCTYPE html> |
| 41 | +<html> |
| 42 | +<head> |
| 43 | + <title>Event Manager 2.0</title> |
| 44 | +</head> |
| 45 | +<body> |
| 46 | + <h1>Todo list</h1> |
| 47 | + |
| 48 | + <ul> |
| 49 | + <% @todos.each do |todo| %> |
| 50 | + <li><%= todo %></li> |
| 51 | + <% end %> |
| 52 | + </ul> |
| 53 | + |
| 54 | +</body> |
| 55 | +</html> |
| 56 | +{% endhighlight %} |
| 57 | + |
| 58 | +These files are almost the same - a lot of copy and paste has gone on. |
| 59 | + |
| 60 | +### The solution |
| 61 | + |
| 62 | +Sinatra gets round this problem by allowing you to have a `layout.erb` file in your `views` folder: |
| 63 | + |
| 64 | +{% highlight html %} |
| 65 | +<!-- views/layout.erb --> |
| 66 | +<!DOCTYPE html> |
| 67 | +<html> |
| 68 | +<head> |
| 69 | + <title>Event Manager 2.0</title> |
| 70 | +</head> |
| 71 | +<body> |
| 72 | + |
| 73 | + <%= yield %> |
| 74 | + |
| 75 | +</body> |
| 76 | +</html> |
| 77 | +{% endhighlight %} |
| 78 | + |
| 79 | +You can then write only the bits that change in the other two views: |
| 80 | + |
| 81 | +{% highlight html %} |
| 82 | +<!-- in views/index.erb --> |
| 83 | +<h1>Picture Unveiling Evening - Event Managment</h1> |
| 84 | + |
| 85 | +<ul> |
| 86 | + <li><a href='/todos'>Todo list</a></li> |
| 87 | + <li><a href='/schedule'>Event schedule</a></li> |
| 88 | + <li><a href='/rsvps'>RSVPs</a></li> |
| 89 | +</ul> |
| 90 | +{% endhighlight %} |
| 91 | + |
| 92 | +{% highlight html %} |
| 93 | +<!-- in views/todo.erb --> |
| 94 | +<h1>Todo list</h1> |
| 95 | + |
| 96 | +<ul> |
| 97 | + <% @todos.each do |todo| %> |
| 98 | + <li><%= todo %></li> |
| 99 | + <% end %> |
| 100 | +</ul> |
| 101 | +{% endhighlight %} |
| 102 | + |
| 103 | +Sinatra knows that if you have a file called `layout.erb` it should use that as a layout. If you call `erb :index`: |
| 104 | + |
| 105 | +* It takes the `layout.erb` file. |
| 106 | +* It finds the bit where it says `<%= yield %>`. |
| 107 | +* It inserts `index.erb` at that point. |
| 108 | + |
| 109 | +You can find more about Sinatra layouts on [the internet](http://lmgtfy.com/?q=sinatra+layouts). |
| 110 | + |
| 111 | + |
| 112 | +<div class="panel panel-primary"> |
| 113 | + <div class="panel-heading"> |
| 114 | + <h3 class="panel-title">Sinatra conventions</h3> |
| 115 | + </div> |
| 116 | + <div class='panel-body'> |
| 117 | + <ol> |
| 118 | + <li>If you have a file <code>views/layout.erb</code> Sinatra will treat it as a layout file: whenever it renders another template, it will try and insert the output into the <code><%= yield %></code> part of the layout file.</li> |
| 119 | + <li>Files inside the <code>public</code> folder will be served at the root of the site. This is where you should put your own stylesheets/images etc.</li> |
| 120 | + <li>You call a template with the line <code>erb :template_name</code>.</li> |
| 121 | + <li>For this to work, you will need a template called <code>template_name.erb</code> in the <code>views</code> folder.</li> |
| 122 | + <li>Instance variables (ones that start with <code>@</code>) will be shared with the template.</li> |
| 123 | + <li>You use these shared instance variables in the template by putting them inside an erb tag: <code><%= @my_variable %></code> </li> |
| 124 | + </ol> |
| 125 | + </div> |
| 126 | +</div> |
| 127 | + |
| 128 | +{% exercise %} |
| 129 | +*Refactor* your views: |
| 130 | + |
| 131 | +1. Create a layout file, containing the shared material from each view. |
| 132 | +2. Remove the shared material from each view. |
| 133 | +3. Check that the screens still look the same! |
| 134 | +{% endexercise %} |
0 commit comments