Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 350 lines (230 sloc) 8.2 kb
f0857e5 Chris Wanstrath rtemplate => mustache
defunkt authored
1 Mustache
6ee6bcf Chris Wanstrath first draft
defunkt authored
2 =========
3
02edd2c Chris Wanstrath references make the first paragraph it read easier
defunkt authored
4 Inspired by [ctemplate][1] and [et][2], Mustache is a
5 framework-agnostic way to render logic-free views.
6ee6bcf Chris Wanstrath first draft
defunkt authored
6
b32c566 Chris Wanstrath quote ctemplates
defunkt authored
7 As ctemplates says, "It emphasizes separating logic from presentation:
8 it is impossible to embed application logic in this template language."
3aad2f3 Chris Wanstrath docs
defunkt authored
9
0b217cf Chris Wanstrath talk about tags first. they're important.
defunkt authored
10
3aad2f3 Chris Wanstrath docs
defunkt authored
11 Overview
12 --------
13
f0857e5 Chris Wanstrath rtemplate => mustache
defunkt authored
14 Think of Mustache as a replacement for your views. Instead of views
3aad2f3 Chris Wanstrath docs
defunkt authored
15 consisting of ERB or HAML with random helpers and arbitrary logic,
16 your views are broken into two parts: a Ruby class and an HTML
17 template.
18
19 We call the Ruby class the "view" and the HTML template the
20 "template."
21
22 All your logic, decisions, and code is contained in your view. All
23 your markup is contained in your template. The template does nothing
d5258f3 Chris Wanstrath whitespace
defunkt authored
24 but reference methods in your view.
3aad2f3 Chris Wanstrath docs
defunkt authored
25
26 This strict separation makes it easier to write clean templates,
27 easier to test your views, and more fun to work on your app's front end.
28
0b217cf Chris Wanstrath talk about tags first. they're important.
defunkt authored
29
1d6dfee Chris Wanstrath why?
defunkt authored
30 Why?
31 ----
32
33 I like writing Ruby. I like writing HTML. I like writing JavaScript.
34
35 I don't like writing ERB, Haml, Liquid, Django Templates, putting Ruby
36 in my HTML, or putting JavaScript in my HTML.
37
38
3aad2f3 Chris Wanstrath docs
defunkt authored
39 Usage
40 -----
41
debca50 Quick example.
Francesc Esplugas authored
42 Quick example:
43
44 >> require 'mustache'
45 => true
46 >> Mustache.render("Hello {{planet}}", :planet => "World!")
47 => "Hello World!"
48
3aad2f3 Chris Wanstrath docs
defunkt authored
49 We've got an `examples` folder but here's the canonical one:
50
f0857e5 Chris Wanstrath rtemplate => mustache
defunkt authored
51 class Simple < Mustache
3aad2f3 Chris Wanstrath docs
defunkt authored
52 def name
53 "Chris"
54 end
55
56 def value
57 10_000
58 end
59
60 def taxed_value
61 value - (value * 0.4)
62 end
63
64 def in_ca
65 true
66 end
67 end
68
69 We simply create a normal Ruby class and define methods. Some methods
70 reference others, some return values, some return only booleans.
71
72 Now let's write the template:
73
74 Hello {{name}}
75 You have just won ${{value}}!
76 {{#in_ca}}
77 Well, ${{taxed_value}}, after taxes.
78 {{/in_ca}}
79
80 This template references our view methods. To bring it all together,
81 here's the code to render actual HTML;
82
9b245dd Chris Wanstrath `render` is the new `to_html`
defunkt authored
83 Simple.render
3aad2f3 Chris Wanstrath docs
defunkt authored
84
85 Which returns the following:
86
87 Hello Chris
88 You have just won $10000!
89 Well, $6000.0, after taxes.
90
91 Simple.
92
0b217cf Chris Wanstrath talk about tags first. they're important.
defunkt authored
93
94 Tag Types
95 ---------
96
97 Tags are indicated by the double mustaches. `{{name}}` is a tag. Let's
98 talk about the different types of tags.
99
100 ### Variables
101
102 The most basic tag is the variable. A `{{name}}` tag in a basic
103 template will try to call the `name` method on your view. If there is
104 no `name` method, an exception will be raised.
105
106 All variables are HTML escaped by default. If you want, for some
107 reason, to return unescaped HTML you can use the triple mustache:
d5258f3 Chris Wanstrath whitespace
defunkt authored
108 `{{{name}}}`.
0b217cf Chris Wanstrath talk about tags first. they're important.
defunkt authored
109
110 ### Boolean Sections
111
112 A section begins with a pound and ends with a slash. That is,
113 `{{#person}}` begins a "person" section while `{{/person}}` ends it.
114
115 If the `person` method exists and calling it returns false, the HTML
116 between the pound and slash will not be displayed.
117
118 If the `person` method exists and calling it returns true, the HTML
119 between the pound and slash will be rendered and displayed.
120
121 ### Enumerable Sections
122
123 Enumerable sections are syntactically identical to boolean sections in
124 that they begin with a pound and end with a slash. The difference,
125 however, is in the view: if the method called returns an enumerable,
d5258f3 Chris Wanstrath whitespace
defunkt authored
126 the section is repeated as the enumerable is iterated over.
0b217cf Chris Wanstrath talk about tags first. they're important.
defunkt authored
127
128 Each item in the enumerable is expected to be a hash which will then
129 become the context of the corresponding iteration. In this way we can
130 construct loops.
131
132 For example, imagine this template:
133
134 {{#repo}}
135 <b>{{name}}</b>
136 {{/repo}}
137
138 And this view code:
139
140 def repo
141 Repository.all.map { |r| { :name => r.to_s } }
142 end
143
144 When rendered, our view will contain a list of all repository names in
145 the database.
146
147 ### Comments
148
149 Comments begin with a bang and are ignored. The following template:
150
151 <h1>Today{{! ignore me }}.</h1>
d5258f3 Chris Wanstrath whitespace
defunkt authored
152
0b217cf Chris Wanstrath talk about tags first. they're important.
defunkt authored
153 Will render as follows:
154
155 <h1>Today.</h1>
156
157 ### Partials
158
159 Partials begin with a less than sign, like `{{< box}}`.
160
161 If a partial's view is loaded, we use that to render the HTML. If
162 nothing is loaded we render the template directly using our current context.
163
164 In this way partials can reference variables or sections the calling
165 view defines.
166
167
04e852b Chris Wanstrath explain the dict style
defunkt authored
168 Dict-Style Views
169 ----------------
170
171 ctemplate and friends want you to hand a dictionary to the template
f0857e5 Chris Wanstrath rtemplate => mustache
defunkt authored
172 processor. Naturally Mustache supports a similar concept. Feel free
04e852b Chris Wanstrath explain the dict style
defunkt authored
173 to mix the class-based and this more procedural style at your leisure.
174
175 Given this template (dict.html):
176
177 Hello {{name}}
178 You have just won ${{value}}!
179
180 We can fill in the values at will:
d5258f3 Chris Wanstrath whitespace
defunkt authored
181
04e852b Chris Wanstrath explain the dict style
defunkt authored
182 dict = Dict.new
183 dict[:name] = 'George'
184 dict[:value] = 100
9b245dd Chris Wanstrath `render` is the new `to_html`
defunkt authored
185 dict.render
04e852b Chris Wanstrath explain the dict style
defunkt authored
186
187 Which returns:
d5258f3 Chris Wanstrath whitespace
defunkt authored
188
04e852b Chris Wanstrath explain the dict style
defunkt authored
189 Hello George
190 You have just won $100!
191
192 We can re-use the same object, too:
193
194 dict[:name] = 'Tony'
9b245dd Chris Wanstrath `render` is the new `to_html`
defunkt authored
195 dict.render
04e852b Chris Wanstrath explain the dict style
defunkt authored
196 Hello Tony
197 You have just won $100!
198
0b217cf Chris Wanstrath talk about tags first. they're important.
defunkt authored
199
671f6aa Chris Wanstrath document template options and make template_file configurable
defunkt authored
200 Templates
201 ---------
202
203 A word on templates. By default, a view will try to find its template
204 on disk by searching for an HTML file in the current directory that
205 follows the classic Ruby naming convention.
206
207 TemplatePartial => ./template_partial.html
d5258f3 Chris Wanstrath whitespace
defunkt authored
208
f0857e5 Chris Wanstrath rtemplate => mustache
defunkt authored
209 You can set the search path using `Mustache.path`. It can be set on a
671f6aa Chris Wanstrath document template options and make template_file configurable
defunkt authored
210 class by class basis:
211
f0857e5 Chris Wanstrath rtemplate => mustache
defunkt authored
212 class Simple < Mustache
671f6aa Chris Wanstrath document template options and make template_file configurable
defunkt authored
213 self.path = File.dirname(__FILE__)
214 ... etc ...
215 end
216
217 Now `Simple` will look for `simple.html` in the directory it resides
218 in, no matter the cwd.
219
220 If you want to just change what template is used you can set
5b3b4c3 Magnus Holm Compile into a Proc (for speed). This required more changes:
judofyr authored
221 `Mustache.template_file` directly:
671f6aa Chris Wanstrath document template options and make template_file configurable
defunkt authored
222
5b3b4c3 Magnus Holm Compile into a Proc (for speed). This required more changes:
judofyr authored
223 Simple.template_file = './blah.html'
d5258f3 Chris Wanstrath whitespace
defunkt authored
224
671f6aa Chris Wanstrath document template options and make template_file configurable
defunkt authored
225 You can also go ahead and set the template directly:
226
5b3b4c3 Magnus Holm Compile into a Proc (for speed). This required more changes:
judofyr authored
227 Simple.template = 'Hi {{person}}!'
228
229 You can also set a different template for only a single instance:
230
671f6aa Chris Wanstrath document template options and make template_file configurable
defunkt authored
231 Simple.new.template = 'Hi {{person}}!'
232
233 Whatever works.
234
0b217cf Chris Wanstrath talk about tags first. they're important.
defunkt authored
235
70af848 Chris Wanstrath helpers?!
defunkt authored
236 Helpers
237 -------
238
239 What about global helpers? Maybe you have a nifty `gravatar` function
d5258f3 Chris Wanstrath whitespace
defunkt authored
240 you want to use in all your views? No problem.
70af848 Chris Wanstrath helpers?!
defunkt authored
241
242 This is just Ruby, after all.
243
244 module ViewHelpers
245 def gravatar(email, size = 30)
246 gravatar_id = Digest::MD5.hexdigest(email.to_s.strip.downcase)
247 gravatar_for_id(gravatar_id, size)
248 end
249
250 def gravatar_for_id(gid, size = 30)
251 "#{gravatar_host}/avatar/#{gid}?s=#{size}"
252 end
253
254 def gravatar_host
255 @ssl ? 'https://secure.gravatar.com' : 'http://www.gravatar.com'
256 end
257 end
258
d5258f3 Chris Wanstrath whitespace
defunkt authored
259 Then just include it:
70af848 Chris Wanstrath helpers?!
defunkt authored
260
f0857e5 Chris Wanstrath rtemplate => mustache
defunkt authored
261 class Simple < Mustache
70af848 Chris Wanstrath helpers?!
defunkt authored
262 include ViewHelpers
263
264 def name
265 "Chris"
266 end
267
268 def value
269 10_000
270 end
271
272 def taxed_value
273 value - (value * 0.4)
274 end
275
276 def in_ca
277 true
278 end
279 end
280
281 Great, but what about that `@ssl` ivar in `gravatar_host`? There are
282 many ways we can go about setting it.
283
f0857e5 Chris Wanstrath rtemplate => mustache
defunkt authored
284 Here's on example which illustrates a key feature of Mustache: you
70af848 Chris Wanstrath helpers?!
defunkt authored
285 are free to use the `initialize` method just as you would in any
286 normal class.
287
f0857e5 Chris Wanstrath rtemplate => mustache
defunkt authored
288 class Simple < Mustache
70af848 Chris Wanstrath helpers?!
defunkt authored
289 include ViewHelpers
290
291 def initialize(ssl = false)
292 @ssl = ssl
293 end
294
295 ... etc ...
296 end
297
298 Now:
299
9b245dd Chris Wanstrath `render` is the new `to_html`
defunkt authored
300 Simple.new(request.ssl?).render
70af848 Chris Wanstrath helpers?!
defunkt authored
301
302 Convoluted but you get the idea.
303
304
d7d6f66 Chris Wanstrath mention sinatra integration in README
defunkt authored
305 Sinatra
306 -------
307
308 Mustache ships with Sinatra integration. Please see
309 `lib/mustache/sinatra.rb` or
310 <http://defunkt.github.com/mustache/classes/Mustache/Sinatra.html> for
311 complete documentation.
312
ca40124 Chris Wanstrath reference the mustache-sinatra-example
defunkt authored
313 An example Sinatra application is also provided:
314 <http://github.com/defunkt/mustache-sinatra-example>
315
d7d6f66 Chris Wanstrath mention sinatra integration in README
defunkt authored
316
b6e396f Chris Wanstrath add installation and docs
defunkt authored
317 Installation
318 ------------
319
320 ### [Gemcutter](http://gemcutter.org/)
321
322 $ gem install mustache
d5258f3 Chris Wanstrath whitespace
defunkt authored
323
b6e396f Chris Wanstrath add installation and docs
defunkt authored
324 ### [Rip](http://hellorip.com)
325
326 $ rip install git://github.com/defunkt/mustache.git
327
328
05bedeb Chris Wanstrath acknowledgements
defunkt authored
329 Acknowledgements
330 ----------------
331
332 Thanks to [Tom Preston-Werner](http://github.com/mojombo) for showing
333 me ctemplate and [Leah Culver](http://github.com/leah) for the name "Mustache."
334
335
190b84d Chris Wanstrath project meta info in the readme (issue tracker, mailing list, etc)
defunkt authored
336 Meta
337 ----
141fa9a Chris Wanstrath partials docs
defunkt authored
338
190b84d Chris Wanstrath project meta info in the readme (issue tracker, mailing list, etc)
defunkt authored
339 * Code: `git clone git://github.com/defunkt/mustache.git`
a289c2b Chris Wanstrath add Home link
defunkt authored
340 * Home: <http://github.com/defunkt/mustache>
b6e396f Chris Wanstrath add installation and docs
defunkt authored
341 * Docs: <http://defunkt.github.com/mustache>
190b84d Chris Wanstrath project meta info in the readme (issue tracker, mailing list, etc)
defunkt authored
342 * Bugs: <http://github.com/defunkt/mustache/issues>
343 * List: <http://groups.google.com/group/mustache-rb>
ff3cb6d Chris Wanstrath add runcoderun link
defunkt authored
344 * Test: <http://runcoderun.com/defunkt/mustache>
48b933c Chris Wanstrath add Gems link
defunkt authored
345 * Gems: <http://gemcutter.org/gems/mustache>
190b84d Chris Wanstrath project meta info in the readme (issue tracker, mailing list, etc)
defunkt authored
346 * Boss: Chris Wanstrath :: <http://github.com/defunkt>
02edd2c Chris Wanstrath references make the first paragraph it read easier
defunkt authored
347
348 [1]: http://code.google.com/p/google-ctemplate/
349 [2]: http://www.ivan.fomichev.name/2008/05/erlang-template-engine-prototype.html
Something went wrong with that request. Please try again.