Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 357 lines (234 sloc) 8.371 kB
f0857e5 @defunkt rtemplate => mustache
defunkt authored
1 Mustache
6ee6bcf @defunkt first draft
defunkt authored
2 =========
3
02edd2c @defunkt 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 @defunkt first draft
defunkt authored
6
b32c566 @defunkt 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 @defunkt docs
defunkt authored
9
0b217cf @defunkt talk about tags first. they're important.
defunkt authored
10
3aad2f3 @defunkt docs
defunkt authored
11 Overview
12 --------
13
f0857e5 @defunkt rtemplate => mustache
defunkt authored
14 Think of Mustache as a replacement for your views. Instead of views
3aad2f3 @defunkt 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 @defunkt whitespace
defunkt authored
24 but reference methods in your view.
3aad2f3 @defunkt 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 @defunkt talk about tags first. they're important.
defunkt authored
29
1d6dfee @defunkt 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 @defunkt 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 @defunkt docs
defunkt authored
49 We've got an `examples` folder but here's the canonical one:
50
f0857e5 @defunkt rtemplate => mustache
defunkt authored
51 class Simple < Mustache
3aad2f3 @defunkt 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 @defunkt `render` is the new `to_html`
defunkt authored
83 Simple.render
3aad2f3 @defunkt 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 @defunkt 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 @defunkt whitespace
defunkt authored
108 `{{{name}}}`.
0b217cf @defunkt 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 @defunkt whitespace
defunkt authored
126 the section is repeated as the enumerable is iterated over.
0b217cf @defunkt 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 @defunkt whitespace
defunkt authored
152
0b217cf @defunkt 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 @defunkt 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
515de91 @defunkt Dict example uses Winner to be more explicit, less confusing
defunkt authored
172 processor. Mustache supports a similar concept. Feel free to mix the
173 class-based and this more procedural style at your leisure.
04e852b @defunkt explain the dict style
defunkt authored
174
515de91 @defunkt Dict example uses Winner to be more explicit, less confusing
defunkt authored
175 Given this template (winner.html):
04e852b @defunkt explain the dict style
defunkt authored
176
177 Hello {{name}}
178 You have just won ${{value}}!
179
180 We can fill in the values at will:
d5258f3 @defunkt whitespace
defunkt authored
181
515de91 @defunkt Dict example uses Winner to be more explicit, less confusing
defunkt authored
182 view = Winner.new
183 view[:name] = 'George'
184 view[:value] = 100
185 view.render
04e852b @defunkt explain the dict style
defunkt authored
186
187 Which returns:
d5258f3 @defunkt whitespace
defunkt authored
188
04e852b @defunkt 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
515de91 @defunkt Dict example uses Winner to be more explicit, less confusing
defunkt authored
194 view[:name] = 'Tony'
195 view.render
04e852b @defunkt explain the dict style
defunkt authored
196 Hello Tony
197 You have just won $100!
198
0b217cf @defunkt talk about tags first. they're important.
defunkt authored
199
671f6aa @defunkt 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 @defunkt whitespace
defunkt authored
208
3291a2d @defunkt document template_extension in the README
defunkt authored
209 You can set the search path using `Mustache.template_path`. It can be set on a
671f6aa @defunkt document template options and make template_file configurable
defunkt authored
210 class by class basis:
211
f0857e5 @defunkt rtemplate => mustache
defunkt authored
212 class Simple < Mustache
3291a2d @defunkt document template_extension in the README
defunkt authored
213 self.template_path = File.dirname(__FILE__)
671f6aa @defunkt document template options and make template_file configurable
defunkt authored
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 @judofyr Compile into a Proc (for speed). This required more changes:
judofyr authored
221 `Mustache.template_file` directly:
671f6aa @defunkt document template options and make template_file configurable
defunkt authored
222
5b3b4c3 @judofyr Compile into a Proc (for speed). This required more changes:
judofyr authored
223 Simple.template_file = './blah.html'
d5258f3 @defunkt whitespace
defunkt authored
224
3291a2d @defunkt document template_extension in the README
defunkt authored
225 Mustache also allows you to define the extension it'll use.
226
227 Simple.template_extension = 'xml'
228
229 Given all other defaults, the above line will cause Mustache to look
230 for './blah.xml'
231
232 Feel free to set the template directly:
671f6aa @defunkt document template options and make template_file configurable
defunkt authored
233
5b3b4c3 @judofyr Compile into a Proc (for speed). This required more changes:
judofyr authored
234 Simple.template = 'Hi {{person}}!'
235
3291a2d @defunkt document template_extension in the README
defunkt authored
236 Or set a different template for a single instance:
5b3b4c3 @judofyr Compile into a Proc (for speed). This required more changes:
judofyr authored
237
671f6aa @defunkt document template options and make template_file configurable
defunkt authored
238 Simple.new.template = 'Hi {{person}}!'
239
240 Whatever works.
241
0b217cf @defunkt talk about tags first. they're important.
defunkt authored
242
70af848 @defunkt helpers?!
defunkt authored
243 Helpers
244 -------
245
246 What about global helpers? Maybe you have a nifty `gravatar` function
d5258f3 @defunkt whitespace
defunkt authored
247 you want to use in all your views? No problem.
70af848 @defunkt helpers?!
defunkt authored
248
249 This is just Ruby, after all.
250
251 module ViewHelpers
252 def gravatar(email, size = 30)
253 gravatar_id = Digest::MD5.hexdigest(email.to_s.strip.downcase)
254 gravatar_for_id(gravatar_id, size)
255 end
256
257 def gravatar_for_id(gid, size = 30)
258 "#{gravatar_host}/avatar/#{gid}?s=#{size}"
259 end
260
261 def gravatar_host
262 @ssl ? 'https://secure.gravatar.com' : 'http://www.gravatar.com'
263 end
264 end
265
d5258f3 @defunkt whitespace
defunkt authored
266 Then just include it:
70af848 @defunkt helpers?!
defunkt authored
267
f0857e5 @defunkt rtemplate => mustache
defunkt authored
268 class Simple < Mustache
70af848 @defunkt helpers?!
defunkt authored
269 include ViewHelpers
270
271 def name
272 "Chris"
273 end
274
275 def value
276 10_000
277 end
278
279 def taxed_value
280 value - (value * 0.4)
281 end
282
283 def in_ca
284 true
285 end
286 end
287
288 Great, but what about that `@ssl` ivar in `gravatar_host`? There are
289 many ways we can go about setting it.
290
f0857e5 @defunkt rtemplate => mustache
defunkt authored
291 Here's on example which illustrates a key feature of Mustache: you
70af848 @defunkt helpers?!
defunkt authored
292 are free to use the `initialize` method just as you would in any
293 normal class.
294
f0857e5 @defunkt rtemplate => mustache
defunkt authored
295 class Simple < Mustache
70af848 @defunkt helpers?!
defunkt authored
296 include ViewHelpers
297
298 def initialize(ssl = false)
299 @ssl = ssl
300 end
301
302 ... etc ...
303 end
304
305 Now:
306
9b245dd @defunkt `render` is the new `to_html`
defunkt authored
307 Simple.new(request.ssl?).render
70af848 @defunkt helpers?!
defunkt authored
308
309 Convoluted but you get the idea.
310
311
d7d6f66 @defunkt mention sinatra integration in README
defunkt authored
312 Sinatra
313 -------
314
315 Mustache ships with Sinatra integration. Please see
316 `lib/mustache/sinatra.rb` or
317 <http://defunkt.github.com/mustache/classes/Mustache/Sinatra.html> for
318 complete documentation.
319
ca40124 @defunkt reference the mustache-sinatra-example
defunkt authored
320 An example Sinatra application is also provided:
321 <http://github.com/defunkt/mustache-sinatra-example>
322
d7d6f66 @defunkt mention sinatra integration in README
defunkt authored
323
b6e396f @defunkt add installation and docs
defunkt authored
324 Installation
325 ------------
326
327 ### [Gemcutter](http://gemcutter.org/)
328
329 $ gem install mustache
d5258f3 @defunkt whitespace
defunkt authored
330
b6e396f @defunkt add installation and docs
defunkt authored
331 ### [Rip](http://hellorip.com)
332
333 $ rip install git://github.com/defunkt/mustache.git
334
335
05bedeb @defunkt acknowledgements
defunkt authored
336 Acknowledgements
337 ----------------
338
339 Thanks to [Tom Preston-Werner](http://github.com/mojombo) for showing
340 me ctemplate and [Leah Culver](http://github.com/leah) for the name "Mustache."
341
342
190b84d @defunkt project meta info in the readme (issue tracker, mailing list, etc)
defunkt authored
343 Meta
344 ----
141fa9a @defunkt partials docs
defunkt authored
345
190b84d @defunkt project meta info in the readme (issue tracker, mailing list, etc)
defunkt authored
346 * Code: `git clone git://github.com/defunkt/mustache.git`
a289c2b @defunkt add Home link
defunkt authored
347 * Home: <http://github.com/defunkt/mustache>
b6e396f @defunkt add installation and docs
defunkt authored
348 * Docs: <http://defunkt.github.com/mustache>
190b84d @defunkt project meta info in the readme (issue tracker, mailing list, etc)
defunkt authored
349 * Bugs: <http://github.com/defunkt/mustache/issues>
350 * List: <http://groups.google.com/group/mustache-rb>
ff3cb6d @defunkt add runcoderun link
defunkt authored
351 * Test: <http://runcoderun.com/defunkt/mustache>
48b933c @defunkt add Gems link
defunkt authored
352 * Gems: <http://gemcutter.org/gems/mustache>
190b84d @defunkt project meta info in the readme (issue tracker, mailing list, etc)
defunkt authored
353 * Boss: Chris Wanstrath :: <http://github.com/defunkt>
02edd2c @defunkt references make the first paragraph it read easier
defunkt authored
354
355 [1]: http://code.google.com/p/google-ctemplate/
356 [2]: http://www.ivan.fomichev.name/2008/05/erlang-template-engine-prototype.html
Something went wrong with that request. Please try again.