lsegal-tadpole 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +22 -0
- data/README.html +222 -0
- data/README.markdown +259 -0
- metadata +55 -0
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2008 Loren Segal
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.html
ADDED
@@ -0,0 +1,222 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Tadpole: A Small but Extensible Templating Engine</title>
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<div id='page'>
|
8
|
+
<div id='title'>
|
9
|
+
<h1>Tadpole: A Small but Extensible Templating Engine for Ruby</h1>
|
10
|
+
|
11
|
+
<p><em>Created by <a href="http://www.gnuu.org">Loren Segal</a> in 2008</em></p>
|
12
|
+
</div>
|
13
|
+
<div id='content'>
|
14
|
+
<ol>
|
15
|
+
<li id='#<Tadpole::SectionProviders::TemplateProvider:0x5bba6c>'>
|
16
|
+
<h2>Quick How-To's</h2>
|
17
|
+
|
18
|
+
<h3>Create a Template</h3>
|
19
|
+
|
20
|
+
<p>Creating a template is literally as easy as 1-2-3:</p>
|
21
|
+
|
22
|
+
<ol>
|
23
|
+
<li><p>Create your templates in a directory. All directories are templates and all templates
|
24
|
+
are directories. The directory name will be the (or part of) the name of your template.
|
25
|
+
Example for template <code>mytemplate</code>:</p>
|
26
|
+
|
27
|
+
<pre><code>templates/
 mytemplate/
 setup.rb
 section1.erb
 section2.haml
 copyright.html
</code></pre></li>
|
28
|
+
<li><p>Setup the "<em>table of contents</em>" of your sections in the <code>setup.rb</code>:</p>
|
29
|
+
|
30
|
+
<pre><code>def init
 super
 sections 'section1', 'section2', 'copyright'
end
</code></pre>
|
31
|
+
|
32
|
+
<p>Your sections can include another template (directory). This will call whatever
|
33
|
+
sections were part of that other template.</p>
|
34
|
+
|
35
|
+
<p>A directory does not <em>require</em> a <code>section.rb</code>. If it is not supplied, it will inherit
|
36
|
+
the setup file from its parent (including its sections).</p></li>
|
37
|
+
<li><p>Register the <code>templates</code> path as your root template directory and run the template:</p>
|
38
|
+
|
39
|
+
<pre><code>require 'tadpole'
Tadpole.register_template_path 'path/to/templates'
Tadpole('mytemplate').run
</code></pre></li>
|
40
|
+
</ol>
|
41
|
+
|
42
|
+
<h3>Override a Template</h3>
|
43
|
+
|
44
|
+
<p>You can override templates by simply registering another template_path and creating
|
45
|
+
a template of the same name in the new path. Using the <code>mytemplate</code> example from above
|
46
|
+
we can now make a directory:</p>
|
47
|
+
|
48
|
+
<pre><code>custom_templates/
 mytemplate/
 setup.rb
 header.erb
</code></pre>
|
49
|
+
|
50
|
+
<p>This template will <em>inherit</em> from the template above. Our <code>setup.rb</code> will therefore
|
51
|
+
contain:</p>
|
52
|
+
|
53
|
+
<pre><code>def init
 super
 sections.unshift 'header'
end
</code></pre>
|
54
|
+
|
55
|
+
<p>And to run this file all we need to do is:</p>
|
56
|
+
|
57
|
+
<pre><code>require 'tadpole'
Tadpole.register_template_path 'path/to/templates' # Register base template path
Tadpole.register_template_path 'path/to/custom_templates' # Register overridden template path

# Running our template will now add our 'header' file to the output
Tadpole('mytemplate').run
</code></pre>
|
58
|
+
|
59
|
+
<h3>Heirarchical Sections</h3>
|
60
|
+
|
61
|
+
<p>Sometimes you may need to encapsulate the output of some sections inside another one. An HTML
|
62
|
+
template, for example, will usually contain the page body inside the body tag of a more general
|
63
|
+
"header" template. To set this up, you use the following <code>sections</code> call:</p>
|
64
|
+
|
65
|
+
<pre><code>sections 'header', ['section1', 'section2', 'copyright']
</code></pre>
|
66
|
+
|
67
|
+
<p>You can then call these from your <code>header.erb</code> file as simple yields. Each yield renders
|
68
|
+
one section in the sub-list:</p>
|
69
|
+
|
70
|
+
<pre><code><html>
 <body>
 <h1>Section 1</h1>
 <%= yield %>

 <h1>Section 2</h1>
 <%= yield %>

 <h1>Copyright</h1>
 <%= yield %>
 </body>
</html>
</code></pre>
|
71
|
+
|
72
|
+
<p>Alternatively you can yield all sub-sections with the convenience call <code>all_sections</code>
|
73
|
+
(in the following <a href="http://haml.hamptoncatlin.com">Haml</a> example, yield param 's'
|
74
|
+
contains the section name which would serve as the li's id attribute):</p>
|
75
|
+
|
76
|
+
<pre><code>%html
 %body
 %ol
 - all_sections do |s|
 %li{:id => s}= yield
</code></pre>
|
77
|
+
</li>
|
78
|
+
<li id='#<Tadpole::SectionProviders::FileProvider:0x5a7f1c>'>
|
79
|
+
<h2>What is Tadpole?</h2>
|
80
|
+
|
81
|
+
<p><strong>Tadpole</strong> is a small templating engine that attempts to solve a problem that
|
82
|
+
no other templating engine does: <em>extensibility</em>. When dealing with templates,
|
83
|
+
most engines focus on the formatting of the output content while forgetting about
|
84
|
+
the important task a developer faces of hooking all these 'views' together. While
|
85
|
+
it may seem trivial and worth ignoring, in reality, many templates become plagued
|
86
|
+
with complexity and coupling due to the lack of support beyond the mere presentation
|
87
|
+
of a single file.</p>
|
88
|
+
|
89
|
+
<p><strong>Tadpole</strong> deals not with the formatting or translation or markup, but rather
|
90
|
+
with the organization of the data as it is outputted. In fact, <strong>Tadpole</strong> is not
|
91
|
+
markup at all, nor does it care what markup you use, having out of the box support
|
92
|
+
for the obvious template languages in Ruby (ERB, <a href="http://www.haml.hamptoncatlin.com">Haml</a>,
|
93
|
+
<a href="http://code.whytheluckystiff.net/markaby">Markaby</a>, <a href="http://builder.rubyforge.org">Builder</a>)
|
94
|
+
and the ability to add more. <strong>Tadpole is all about information organization, not formatting</strong>.</p>
|
95
|
+
|
96
|
+
<p>If you need a good visualization of what <strong>Tadpole</strong> is, think of it as <em>the table of</em>
|
97
|
+
<em>contents for your views</em>. Just as it is important to designing each view and partial of
|
98
|
+
your template, it is important to decide in what order these views will ultimately be
|
99
|
+
organized. <strong>Tadpole</strong>'s job is to store nothing but your table of contents, and then
|
100
|
+
spit it out when you're ready to show it to the world. This technique becomes very
|
101
|
+
powerful in some potentially familiar scenarios. (<em>See the "Real World Examples"</em>)</p>
|
102
|
+
</li>
|
103
|
+
<li id='#<Tadpole::SectionProviders::FileProvider:0x5a76c0>'>
|
104
|
+
<h2>Why Tadpole?</h2>
|
105
|
+
|
106
|
+
<p>Sufficed to say, you might be wondering what the <em>big deal</em> is. I mean, you're
|
107
|
+
probably getting along just fine without this new concept of tables of contents
|
108
|
+
...<em>or so you think</em>. The truth is that there are a lot of real-world scenarios
|
109
|
+
where the old-style template production simply doesn't cut it. I can say this
|
110
|
+
because <strong>Tadpole</strong> was <a href="http://www.github.com/lsegal/yard">born from one of them</a>.</p>
|
111
|
+
|
112
|
+
<p>I'll be honest, <strong>Tadpole</strong> does not meet every use-case scenario, and it probably
|
113
|
+
never will. But if you're writing a <em>blog app</em>, <em>CMS</em>, customizable <em>forum software</em> or
|
114
|
+
anything that will eventually support <em>customizable templates</em> or <em>theming</em>,
|
115
|
+
<em><strong>Tadpole</strong> was made for you</em>. Even if you're just dealing with a lot of <em>template</em>
|
116
|
+
<em>coupling</em> or <em>internationalization code</em>, there's a good chance you're looking at the
|
117
|
+
right tool as well.</p>
|
118
|
+
|
119
|
+
<h3>Good With Customizable Themes, You Say?</h3>
|
120
|
+
|
121
|
+
<p>Anyone who writes customizable software knows that it requires a lot of de-coupled code.
|
122
|
+
While templates are sometimes considered support files rather than actual software, the
|
123
|
+
same law holds true for them. Coupled templates are bad for theming because your users
|
124
|
+
can't get at the data they want.</p>
|
125
|
+
|
126
|
+
<p>The standard solution to this problem is to split your templates up into many 'partials'.
|
127
|
+
That way, any user can just go into the right partial and easily edit what they need
|
128
|
+
without copying <em>all</em> of the template data, right? <strong>Wrong</strong>. The problem starts when a
|
129
|
+
user wants to start adding or removing partials altogether. In fact, it's actually the
|
130
|
+
smallest changes that cause the biggest problems. Everytime they add one line to every
|
131
|
+
new partial, they pull in another entire file. Once <em>you</em> update that file, the changes
|
132
|
+
no longer sync to the user. Fixed a typo in your template? Your user may never get the
|
133
|
+
memo if he pulled in the file you touched. However, because <strong>Tadpole</strong> never actually
|
134
|
+
deals with template <em>data</em>, the same setup in <strong>Tadpole</strong> would not be problematic.
|
135
|
+
Using <strong>Tadpole</strong>, the user would never even have to touch your templates given a good
|
136
|
+
set of insertion points.</p>
|
137
|
+
|
138
|
+
<p>The lesson is, when it comes to customization, there is no partial that is partial enough.
|
139
|
+
<strong>Tadpole</strong> inevitably suffers from this problem as well. However, once you start thinking
|
140
|
+
in terms of template organization you'll find that it's much harder to decide what part
|
141
|
+
of a view deserves a 'partial' than it is to simply split your template up into a series
|
142
|
+
of cohesive "<em>sections</em>".</p>
|
143
|
+
</li>
|
144
|
+
<li id='#<Tadpole::SectionProviders::FileProvider:0x5a7094>'>
|
145
|
+
<h2>Some <em>Theoretically</em>-Real-World Examples of Tadpole in Action</h2>
|
146
|
+
|
147
|
+
<ol>
|
148
|
+
<li><p><em>Bob</em> made a Blogging application called <em>"Boblog"</em> and distributed it under the
|
149
|
+
MIT license over the internet. <em>Janet</em> found this application and decided to
|
150
|
+
use it to power her upcoming "100 Carrot Recipes" blog. She was mostly happy with
|
151
|
+
the provided themes but wanted to customize the look of the sidebar by adding a
|
152
|
+
"Favourite Recipes" links section and writing a tidbit about herself. Now "Boblog"
|
153
|
+
was a simplistic blog tool and did not support a multitude of plugins, but did use
|
154
|
+
<strong>Tadpole</strong> for theming. Janet read about the way customization was done using "Boblog"
|
155
|
+
and got to work making her changes. Janet went into her custom templates directory and
|
156
|
+
created her own new template <code>janet</code> because she had a bad feeling about directly playing
|
157
|
+
with the existing template files (<em>and "Boblog" docs said she didn't need to</em>). Inside
|
158
|
+
that directory she created her new files <code>fav_recipes.html</code> and <code>about.html</code> where she
|
159
|
+
inserted her links to various world renowned Carrot Chefs and a story about her dreams
|
160
|
+
of one day meeting them. Now, she wanted her about section to go at the top of the sidebar,
|
161
|
+
but she wanted her own links section to go beneath the regular links section (already
|
162
|
+
provided by "Boblog"). So, as per the docs, she continued to add a <code>setup.rb</code> file which
|
163
|
+
would connect her new files together with the template. In this file, she simply wrote:</p>
|
164
|
+
|
165
|
+
<pre><code>inherits 'default_theme'


def init
 super
 sections.unshift 'about'
 sections.place('fav_recipes').before('links')
end
</code></pre>
|
166
|
+
|
167
|
+
<p>She then went into "Boblog"'s administration interface and selected the new <code>janet</code>
|
168
|
+
theme. Voila, her dream of tasty success would finally come true.</p>
|
169
|
+
|
170
|
+
<p>Three days later, <em>Bob</em> got word from an anonymous tipster of a nasty bug in his software
|
171
|
+
that could potentially lead to harmful attacks if left unfixed. Guess what, that bug was
|
172
|
+
in the sidebar template that Janet was using! He quickly patched the bug and released a
|
173
|
+
fix, notifying all of his users of the changes (Janet was on his mailing list). Because
|
174
|
+
Janet never edited any of the files belonging to "Boblog", all she had to do was download
|
175
|
+
the patch and restart the application without ever having to remake all of her ever-so-
|
176
|
+
important theming changes to her blog.</p></li>
|
177
|
+
<li><p>Midget Inc. is working on a colourful new site redesign for their mobile widget business.
|
178
|
+
They sell mobile widgets to customers all across the globe and have very strict legal
|
179
|
+
procedures they need to follow when advertising their mobile widgets. In one specific
|
180
|
+
region, they are required by law to show a disclaimer above any advertising images they
|
181
|
+
display. Rather than place region specific logic inside a partial view, they decide to
|
182
|
+
use <strong>Tadpole</strong> to handle their templating system. They decide to use a folder structure
|
183
|
+
of the following to display their advertising page:</p>
|
184
|
+
|
185
|
+
<pre><code>advertising/
 setup.rb
 content.erb
 images.erb
 fr/
 setup.rb
 disclaimer.erb
</code></pre>
|
186
|
+
|
187
|
+
<p><code>advertising/setup.rb</code> contains the following:</p>
|
188
|
+
|
189
|
+
<pre><code>def init; super; sections 'content', 'images' end
</code></pre>
|
190
|
+
|
191
|
+
<p>The <code>fr/</code> subdirectory contains the specific content they need for the law-requiring region
|
192
|
+
and the logic to render this template only in that region is controlled by the controller.
|
193
|
+
Because the <code>fr/</code> template automatically inherits its sections from its parent, all they need
|
194
|
+
to do to set up this new logic is put the following in the <code>fr/setup.rb</code>:</p>
|
195
|
+
|
196
|
+
<pre><code>def init
 super
 sections.place('disclaimer').before('images')
end
</code></pre>
|
197
|
+
|
198
|
+
<p>And the templates can be rendered with:</p>
|
199
|
+
|
200
|
+
<pre><code>Tadpole('advertising').run
Tadpole('advertising/fr').run
</code></pre>
|
201
|
+
|
202
|
+
<p>Respectively.</p></li>
|
203
|
+
</ol>
|
204
|
+
</li>
|
205
|
+
<li id='#<Tadpole::SectionProviders::FileProvider:0x5a6aa4>'>
|
206
|
+
<h2>You Should Also Know</h2>
|
207
|
+
|
208
|
+
<p>That this <code>README</code> was generated by <strong>Tadpole</strong>. Try it:</p>
|
209
|
+
|
210
|
+
<pre><code>ruby examples/example2/run.rb markdown/readme
</code></pre>
|
211
|
+
</li>
|
212
|
+
</ol>
|
213
|
+
</div>
|
214
|
+
<div id='copyright'>
|
215
|
+
<h2>Copyright & Licensing Information</h2>
|
216
|
+
|
217
|
+
<p><em>Copyright 2008 Loren Segal.</em>
|
218
|
+
<em>All code licensed under the MIT License.</em></p>
|
219
|
+
</div>
|
220
|
+
</div>
|
221
|
+
</body>
|
222
|
+
</html>
|
data/README.markdown
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
Tadpole: A Small but Extensible Templating Engine for Ruby
|
2
|
+
==========================================================
|
3
|
+
|
4
|
+
_Created by [Loren Segal](http://www.gnuu.org) in 2008_
|
5
|
+
|
6
|
+
Quick How-To's
|
7
|
+
--------------
|
8
|
+
|
9
|
+
### Create a Template
|
10
|
+
|
11
|
+
Creating a template is literally as easy as 1-2-3:
|
12
|
+
|
13
|
+
1. Create your templates in a directory. All directories are templates and all templates
|
14
|
+
are directories. The directory name will be the (or part of) the name of your template.
|
15
|
+
Example for template `mytemplate`:
|
16
|
+
|
17
|
+
templates/
|
18
|
+
mytemplate/
|
19
|
+
setup.rb
|
20
|
+
section1.erb
|
21
|
+
section2.haml
|
22
|
+
copyright.html
|
23
|
+
|
24
|
+
2. Setup the "_table of contents_" of your sections in the `setup.rb`:
|
25
|
+
|
26
|
+
def init
|
27
|
+
super
|
28
|
+
sections 'section1', 'section2', 'copyright'
|
29
|
+
end
|
30
|
+
|
31
|
+
Your sections can include another template (directory). This will call whatever
|
32
|
+
sections were part of that other template.
|
33
|
+
|
34
|
+
A directory does not _require_ a `section.rb`. If it is not supplied, it will inherit
|
35
|
+
the setup file from its parent (including its sections).
|
36
|
+
|
37
|
+
3. Register the `templates` path as your root template directory and run the template:
|
38
|
+
|
39
|
+
require 'tadpole'
|
40
|
+
Tadpole.register_template_path 'path/to/templates'
|
41
|
+
Tadpole('mytemplate').run
|
42
|
+
|
43
|
+
### Override a Template
|
44
|
+
|
45
|
+
You can override templates by simply registering another template_path and creating
|
46
|
+
a template of the same name in the new path. Using the `mytemplate` example from above
|
47
|
+
we can now make a directory:
|
48
|
+
|
49
|
+
custom_templates/
|
50
|
+
mytemplate/
|
51
|
+
setup.rb
|
52
|
+
header.erb
|
53
|
+
|
54
|
+
This template will _inherit_ from the template above. Our `setup.rb` will therefore
|
55
|
+
contain:
|
56
|
+
|
57
|
+
def init
|
58
|
+
super
|
59
|
+
sections.unshift 'header'
|
60
|
+
end
|
61
|
+
|
62
|
+
And to run this file all we need to do is:
|
63
|
+
|
64
|
+
require 'tadpole'
|
65
|
+
Tadpole.register_template_path 'path/to/templates' # Register base template path
|
66
|
+
Tadpole.register_template_path 'path/to/custom_templates' # Register overridden template path
|
67
|
+
|
68
|
+
# Running our template will now add our 'header' file to the output
|
69
|
+
Tadpole('mytemplate').run
|
70
|
+
|
71
|
+
### Hierarchical Sections
|
72
|
+
|
73
|
+
Sometimes you may need to encapsulate the output of some sections inside another one. An HTML
|
74
|
+
template, for example, will usually contain the page body inside the body tag of a more general
|
75
|
+
"header" template. To set this up, you use the following `sections` call:
|
76
|
+
|
77
|
+
sections 'header', ['section1', 'section2', 'copyright']
|
78
|
+
|
79
|
+
You can then call these from your `header.erb` file as simple yields. Each yield renders
|
80
|
+
one section in the sub-list:
|
81
|
+
|
82
|
+
<html>
|
83
|
+
<body>
|
84
|
+
<h1>Section 1</h1>
|
85
|
+
<%= yield %>
|
86
|
+
|
87
|
+
<h1>Section 2</h1>
|
88
|
+
<%= yield %>
|
89
|
+
|
90
|
+
<h1>Copyright</h1>
|
91
|
+
<%= yield %>
|
92
|
+
</body>
|
93
|
+
</html>
|
94
|
+
|
95
|
+
Alternatively you can yield all sub-sections with the convenience call `all_sections`
|
96
|
+
(in the following [Haml](http://haml.hamptoncatlin.com) example, yield param 's'
|
97
|
+
contains the section name which would serve as the li's id attribute):
|
98
|
+
|
99
|
+
%html
|
100
|
+
%body
|
101
|
+
%ol
|
102
|
+
- all_sections do |s|
|
103
|
+
%li{:id => s}= yield
|
104
|
+
|
105
|
+
|
106
|
+
What is Tadpole?
|
107
|
+
----------------
|
108
|
+
|
109
|
+
**Tadpole** is a small templating engine that attempts to solve a problem that
|
110
|
+
no other templating engine does: _extensibility_. When dealing with templates,
|
111
|
+
most engines focus on the formatting of the output content while forgetting about
|
112
|
+
the important task a developer faces of hooking all these 'views' together. While
|
113
|
+
it may seem trivial and worth ignoring, in reality, many templates become plagued
|
114
|
+
with complexity and coupling due to the lack of support beyond the mere presentation
|
115
|
+
of a single file.
|
116
|
+
|
117
|
+
**Tadpole** deals not with the formatting or translation or markup, but rather
|
118
|
+
with the organization of the data as it is outputted. In fact, **Tadpole** is not
|
119
|
+
markup at all, nor does it care what markup you use, having out of the box support
|
120
|
+
for the obvious template languages in Ruby (ERB, [Haml](http://www.haml.hamptoncatlin.com),
|
121
|
+
[Markaby](http://code.whytheluckystiff.net/markaby), [Builder](http://builder.rubyforge.org))
|
122
|
+
and the ability to add more. **Tadpole is all about information organization, not formatting**.
|
123
|
+
|
124
|
+
If you need a good visualization of what **Tadpole** is, think of it as _the table of_
|
125
|
+
_contents for your views_. Just as it is important to designing each view and partial of
|
126
|
+
your template, it is important to decide in what order these views will ultimately be
|
127
|
+
organized. **Tadpole**'s job is to store nothing but your table of contents, and then
|
128
|
+
spit it out when you're ready to show it to the world. This technique becomes very
|
129
|
+
powerful in some potentially familiar scenarios. (_See the "Real World Examples"_)
|
130
|
+
|
131
|
+
Why Tadpole?
|
132
|
+
------------
|
133
|
+
|
134
|
+
Sufficed to say, you might be wondering what the _big deal_ is. I mean, you're
|
135
|
+
probably getting along just fine without this new concept of tables of contents
|
136
|
+
..._or so you think_. The truth is that there are a lot of real-world scenarios
|
137
|
+
where the old-style template production simply doesn't cut it. I can say this
|
138
|
+
because **Tadpole** was [born from one of them](http://www.github.com/lsegal/yard).
|
139
|
+
|
140
|
+
I'll be honest, **Tadpole** does not meet every use-case scenario, and it probably
|
141
|
+
never will. But if you're writing a _blog app_, _CMS_, customizable _forum software_ or
|
142
|
+
anything that will eventually support _customizable templates_ or _theming_,
|
143
|
+
_**Tadpole** was made for you_. Even if you're just dealing with a lot of _template_
|
144
|
+
_coupling_ or _internationalization code_, there's a good chance you're looking at the
|
145
|
+
right tool as well.
|
146
|
+
|
147
|
+
### Good With Customizable Themes, You Say?
|
148
|
+
|
149
|
+
Anyone who writes customizable software knows that it requires a lot of de-coupled code.
|
150
|
+
While templates are sometimes considered support files rather than actual software, the
|
151
|
+
same law holds true for them. Coupled templates are bad for theming because your users
|
152
|
+
can't get at the data they want.
|
153
|
+
|
154
|
+
The standard solution to this problem is to split your templates up into many 'partials'.
|
155
|
+
That way, any user can just go into the right partial and easily edit what they need
|
156
|
+
without copying _all_ of the template data, right? __Wrong__. The problem starts when a
|
157
|
+
user wants to start adding or removing partials altogether. In fact, it's actually the
|
158
|
+
smallest changes that cause the biggest problems. Everytime they add one line to every
|
159
|
+
new partial, they pull in another entire file. Once _you_ update that file, the changes
|
160
|
+
no longer sync to the user. Fixed a typo in your template? Your user may never get the
|
161
|
+
memo if he pulled in the file you touched. However, because **Tadpole** never actually
|
162
|
+
deals with template _data_, the same setup in **Tadpole** would not be problematic.
|
163
|
+
Using **Tadpole**, the user would never even have to touch your templates given a good
|
164
|
+
set of insertion points.
|
165
|
+
|
166
|
+
The lesson is, when it comes to customization, there is no partial that is partial enough.
|
167
|
+
**Tadpole** inevitably suffers from this problem as well. However, once you start thinking
|
168
|
+
in terms of template organization you'll find that it's much harder to decide what part
|
169
|
+
of a view deserves a 'partial' than it is to simply split your template up into a series
|
170
|
+
of cohesive "_sections_".
|
171
|
+
|
172
|
+
Some _Theoretically_-Real-World Examples of Tadpole in Action
|
173
|
+
-----------------------------------------------------------
|
174
|
+
|
175
|
+
1. _Bob_ made a Blogging application called _"Boblog"_ and distributed it under the
|
176
|
+
MIT license over the internet. _Janet_ found this application and decided to
|
177
|
+
use it to power her upcoming "100 Carrot Recipes" blog. She was mostly happy with
|
178
|
+
the provided themes but wanted to customize the look of the sidebar by adding a
|
179
|
+
"Favourite Recipes" links section and writing a tidbit about herself. Now "Boblog"
|
180
|
+
was a simplistic blog tool and did not support a multitude of plugins, but did use
|
181
|
+
**Tadpole** for theming. Janet read about the way customization was done using "Boblog"
|
182
|
+
and got to work making her changes. Janet went into her custom templates directory and
|
183
|
+
created her own new template `janet` because she had a bad feeling about directly playing
|
184
|
+
with the existing template files (_and "Boblog" docs said she didn't need to_). Inside
|
185
|
+
that directory she created her new files `fav_recipes.html` and `about.html` where she
|
186
|
+
inserted her links to various world renowned Carrot Chefs and a story about her dreams
|
187
|
+
of one day meeting them. Now, she wanted her about section to go at the top of the sidebar,
|
188
|
+
but she wanted her own links section to go beneath the regular links section (already
|
189
|
+
provided by "Boblog"). So, as per the docs, she continued to add a `setup.rb` file which
|
190
|
+
would connect her new files together with the template. In this file, she simply wrote:
|
191
|
+
|
192
|
+
inherits 'default_theme'
|
193
|
+
|
194
|
+
def init
|
195
|
+
super
|
196
|
+
sections.unshift 'about'
|
197
|
+
sections.place('fav_recipes').before('links')
|
198
|
+
end
|
199
|
+
|
200
|
+
She then went into "Boblog"'s administration interface and selected the new `janet`
|
201
|
+
theme. Voila, her dream of tasty success would finally come true.
|
202
|
+
|
203
|
+
Three days later, _Bob_ got word from an anonymous tipster of a nasty bug in his software
|
204
|
+
that could potentially lead to harmful attacks if left unfixed. Guess what, that bug was
|
205
|
+
in the sidebar template that Janet was using! He quickly patched the bug and released a
|
206
|
+
fix, notifying all of his users of the changes (Janet was on his mailing list). Because
|
207
|
+
Janet never edited any of the files belonging to "Boblog", all she had to do was download
|
208
|
+
the patch and restart the application without ever having to remake all of her ever-so-
|
209
|
+
important theming changes to her blog.
|
210
|
+
|
211
|
+
2. Midget Inc. is working on a colourful new site redesign for their mobile widget business.
|
212
|
+
They sell mobile widgets to customers all across the globe and have very strict legal
|
213
|
+
procedures they need to follow when advertising their mobile widgets. In one specific
|
214
|
+
region, they are required by law to show a disclaimer above any advertising images they
|
215
|
+
display. Rather than place region specific logic inside a partial view, they decide to
|
216
|
+
use **Tadpole** to handle their templating system. They decide to use a folder structure
|
217
|
+
of the following to display their advertising page:
|
218
|
+
|
219
|
+
advertising/
|
220
|
+
setup.rb
|
221
|
+
content.erb
|
222
|
+
images.erb
|
223
|
+
fr/
|
224
|
+
setup.rb
|
225
|
+
disclaimer.erb
|
226
|
+
|
227
|
+
`advertising/setup.rb` contains the following:
|
228
|
+
|
229
|
+
def init; super; sections 'content', 'images' end
|
230
|
+
|
231
|
+
The `fr/` subdirectory contains the specific content they need for the law-requiring region
|
232
|
+
and the logic to render this template only in that region is controlled by the controller.
|
233
|
+
Because the `fr/` template automatically inherits its sections from its parent, all they need
|
234
|
+
to do to set up this new logic is put the following in the `fr/setup.rb`:
|
235
|
+
|
236
|
+
def init
|
237
|
+
super
|
238
|
+
sections.place('disclaimer').before('images')
|
239
|
+
end
|
240
|
+
|
241
|
+
And the templates can be rendered with:
|
242
|
+
|
243
|
+
Tadpole('advertising').run
|
244
|
+
Tadpole('advertising/fr').run
|
245
|
+
|
246
|
+
Respectively.
|
247
|
+
|
248
|
+
You Should Also Know
|
249
|
+
--------------------
|
250
|
+
|
251
|
+
That this `README` was generated by **Tadpole**. Try it:
|
252
|
+
|
253
|
+
ruby examples/example2/run.rb markdown/readme
|
254
|
+
|
255
|
+
Copyright & Licensing Information
|
256
|
+
---------------------------------
|
257
|
+
|
258
|
+
_Copyright 2008 Loren Segal._
|
259
|
+
_All code licensed under the MIT License._
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lsegal-tadpole
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Loren Segal
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-09 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: lsegal@soen.ca
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- LICENSE
|
26
|
+
- README.html
|
27
|
+
- README.markdown
|
28
|
+
has_rdoc: false
|
29
|
+
homepage: http://www.soen.ca
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: "0"
|
40
|
+
version:
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
version:
|
47
|
+
requirements: []
|
48
|
+
|
49
|
+
rubyforge_project: tadpole
|
50
|
+
rubygems_version: 1.2.0
|
51
|
+
signing_key:
|
52
|
+
specification_version: 2
|
53
|
+
summary: A Small but Extensible Templating Engine for Ruby
|
54
|
+
test_files: []
|
55
|
+
|