curly-templates 0.8.0 → 0.9.0
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/CHANGELOG.md +9 -0
- data/README.md +123 -8
- data/curly-templates.gemspec +4 -2
- data/lib/curly.rb +1 -1
- data/lib/curly/presenter.rb +21 -0
- data/lib/curly/template_handler.rb +2 -0
- data/lib/rails/projections.json +16 -0
- data/spec/template_handler_spec.rb +16 -0
- metadata +5 -3
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -22,6 +22,24 @@ or [Handlebars](http://handlebarsjs.com/), Curly is different in some key ways:
|
|
22
22
|
object methods that are in turn used by the template.
|
23
23
|
|
24
24
|
|
25
|
+
|
26
|
+
### Is it ready to use in production?
|
27
|
+
|
28
|
+
Yes! While still a young project, it's being used in a rather large Rails app
|
29
|
+
at Zendesk, where it performs admirably.
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
### Table of Contents
|
34
|
+
|
35
|
+
1. [Installing](#installing)
|
36
|
+
2. [How to use Curly](#how-to-use-curly)
|
37
|
+
3. [Presenters](#presenters)
|
38
|
+
1. [Layouts and Content Blocks](#layouts-and-content-blocks)
|
39
|
+
1. [Examples](#examples)
|
40
|
+
4. [Caching](#caching)
|
41
|
+
|
42
|
+
|
25
43
|
Installing
|
26
44
|
----------
|
27
45
|
|
@@ -87,17 +105,114 @@ render collection: post.comments
|
|
87
105
|
```
|
88
106
|
|
89
107
|
|
90
|
-
|
91
|
-
|
108
|
+
Presenters
|
109
|
+
----------
|
92
110
|
|
93
|
-
|
94
|
-
|
111
|
+
Presenters are classes that inherit from `Curly::Presenter` – they're usually placed in
|
112
|
+
`app/presenters/`, but you can put them anywhere you'd like. The name of the presenter
|
113
|
+
classes match the virtual path of the view they're part of, so if your controller is
|
114
|
+
rendering `posts/show`, the `Posts::ShowPresenter` class will be used. Note that Curly
|
115
|
+
is only used to render a view if a template can be found – in this case, at
|
116
|
+
`app/views/posts/show.html.curly`.
|
117
|
+
|
118
|
+
Presenters can declare a list of accepted parameters using the `presents` method:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
class Posts::ShowPresenter < Curly::Presenter
|
122
|
+
presents :post
|
123
|
+
end
|
124
|
+
```
|
125
|
+
|
126
|
+
A parameter can have a default value:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
class Posts::ShowPresenter < Curly::Presenter
|
130
|
+
presents :post
|
131
|
+
presents :comment, default: nil
|
132
|
+
end
|
133
|
+
```
|
134
|
+
|
135
|
+
Any public method defined on the presenter is made available to the template:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
class Posts::ShowPresenter < Curly::Presenter
|
139
|
+
presents :post
|
140
|
+
|
141
|
+
def title
|
142
|
+
@post.title
|
143
|
+
end
|
144
|
+
|
145
|
+
def author_link
|
146
|
+
# You can call any Rails helper from within a presenter instance:
|
147
|
+
link_to author.name, profile_path(author), rel: "author"
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
# Private methods are not available to the template, so they're safe to
|
153
|
+
# use.
|
154
|
+
def author
|
155
|
+
@post.author
|
156
|
+
end
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
Presenter methods can even take an argument. Say your Curly template has the content
|
161
|
+
`{{t.welcome_message}}`, where `welcome_message` is an I18n key. The following presenter
|
162
|
+
method would make the lookup work:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
def t(key)
|
166
|
+
translate(key)
|
167
|
+
end
|
168
|
+
```
|
169
|
+
|
170
|
+
That way, simple ``functions'' can be added to the Curly language. Make sure these do not
|
171
|
+
have any side effects, though, as an important part of Curly is the idempotence of the
|
172
|
+
templates.
|
173
|
+
|
174
|
+
|
175
|
+
### Layouts and Content Blocks
|
176
|
+
|
177
|
+
Both layouts and content blocks (see [`content_for`](http://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html#method-i-content_for))
|
178
|
+
use `yield` to signal that content can be inserted. Curly works just like ERB, so calling
|
179
|
+
`yield` with no arguments will make the view usable as a layout, while passing a Symbol
|
180
|
+
will make it try to read a content block with the given name:
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
# Given you have the following Curly template in app/views/layouts/application.html.curly
|
184
|
+
#
|
185
|
+
# <html>
|
186
|
+
# <head>
|
187
|
+
# <title>{{title}}</title>
|
188
|
+
# </head>
|
189
|
+
# <body>
|
190
|
+
# <div id="sidebar">{{sidebar}}</div>
|
191
|
+
# {{body}}
|
192
|
+
# </body>
|
193
|
+
# </html>
|
194
|
+
#
|
195
|
+
class ApplicationLayout < Curly::Presenter
|
196
|
+
def title
|
197
|
+
"You can use methods just like in any other presenter!"
|
198
|
+
end
|
199
|
+
|
200
|
+
def sidebar
|
201
|
+
# A view can call `content_for(:sidebar) { "some HTML here" }`
|
202
|
+
yield :sidebar
|
203
|
+
end
|
204
|
+
|
205
|
+
def body
|
206
|
+
# The view will be rendered and inserted here:
|
207
|
+
yield
|
208
|
+
end
|
209
|
+
end
|
210
|
+
```
|
95
211
|
|
96
212
|
|
97
|
-
Examples
|
98
|
-
--------
|
213
|
+
### Examples
|
99
214
|
|
100
|
-
Here is a simple Curly template
|
215
|
+
Here is a simple Curly template – it will be looked up by Rails automatically.
|
101
216
|
|
102
217
|
```html
|
103
218
|
<!-- app/views/posts/show.html.curly -->
|
@@ -205,7 +320,7 @@ end
|
|
205
320
|
### Static Caching
|
206
321
|
|
207
322
|
Static caching will only be enabled for presenters that define a non-nil `#cache_key`
|
208
|
-
method (see
|
323
|
+
method (see [Dynamic Caching.](#dynamic-caching))
|
209
324
|
|
210
325
|
In order to make a deploy expire the cache for a specific view, set the version of the
|
211
326
|
view to something new, usually by incrementing by one:
|
data/curly-templates.gemspec
CHANGED
@@ -4,8 +4,8 @@ Gem::Specification.new do |s|
|
|
4
4
|
s.rubygems_version = '1.3.5'
|
5
5
|
|
6
6
|
s.name = 'curly-templates'
|
7
|
-
s.version = '0.
|
8
|
-
s.date = '2013-
|
7
|
+
s.version = '0.9.0'
|
8
|
+
s.date = '2013-06-04'
|
9
9
|
|
10
10
|
s.summary = "Free your views!"
|
11
11
|
s.description = "A view layer for your Rails apps that separates structure and logic."
|
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
|
|
28
28
|
|
29
29
|
# = MANIFEST =
|
30
30
|
s.files = %w[
|
31
|
+
CHANGELOG.md
|
31
32
|
Gemfile
|
32
33
|
README.md
|
33
34
|
Rakefile
|
@@ -43,6 +44,7 @@ Gem::Specification.new do |s|
|
|
43
44
|
lib/generators/curly/controller/controller_generator.rb
|
44
45
|
lib/generators/curly/controller/templates/presenter.rb.erb
|
45
46
|
lib/generators/curly/controller/templates/view.html.curly.erb
|
47
|
+
lib/rails/projections.json
|
46
48
|
spec/compiler_spec.rb
|
47
49
|
spec/generators/controller_generator_spec.rb
|
48
50
|
spec/presenter_spec.rb
|
data/lib/curly.rb
CHANGED
data/lib/curly/presenter.rb
CHANGED
@@ -55,6 +55,27 @@ module Curly
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
+
# Sets up the view.
|
59
|
+
#
|
60
|
+
# Override this method in your presenter in order to do setup before the
|
61
|
+
# template is rendered. One use case is to call `content_for` in order
|
62
|
+
# to inject content into other templates, e.g. a layout.
|
63
|
+
#
|
64
|
+
# Example
|
65
|
+
#
|
66
|
+
# class Posts::ShowPresenter < Curly::Presenter
|
67
|
+
# presents :post
|
68
|
+
#
|
69
|
+
# def setup!
|
70
|
+
# content_for :page_title, @post.title
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# Returns nothing.
|
75
|
+
def setup!
|
76
|
+
# Does nothing.
|
77
|
+
end
|
78
|
+
|
58
79
|
# The key that should be used to cache the view.
|
59
80
|
#
|
60
81
|
# Unless `#cache_key` returns nil, the result of rendering the template
|
@@ -0,0 +1,16 @@
|
|
1
|
+
{
|
2
|
+
"app/presenters/*_presenter.rb": {
|
3
|
+
"affinity": "controller",
|
4
|
+
"command": "presenter",
|
5
|
+
"test": "spec/presenters/%s_presenter_spec.rb",
|
6
|
+
"related": "app/views/%s.html.curly",
|
7
|
+
"template": "class %SPresenter < Curly::Presenter\nend",
|
8
|
+
"keywords": "presents depends_on version"
|
9
|
+
},
|
10
|
+
|
11
|
+
"app/views/*.html.curly": {
|
12
|
+
"affinity": "controller",
|
13
|
+
"test": "spec/views/%s_spec.rb",
|
14
|
+
"related": "app/presenters/%s_presenter.rb"
|
15
|
+
}
|
16
|
+
}
|
@@ -9,6 +9,10 @@ describe Curly::TemplateHandler do
|
|
9
9
|
@cache_duration = options.fetch(:cache_duration, nil)
|
10
10
|
end
|
11
11
|
|
12
|
+
def setup!
|
13
|
+
@context.content_for(:foo, "bar")
|
14
|
+
end
|
15
|
+
|
12
16
|
def foo
|
13
17
|
"FOO"
|
14
18
|
end
|
@@ -47,6 +51,12 @@ describe Curly::TemplateHandler do
|
|
47
51
|
@clock += duration
|
48
52
|
end
|
49
53
|
|
54
|
+
def content_for(key, value = nil)
|
55
|
+
@contents ||= {}
|
56
|
+
@contents[key] = value if value.present?
|
57
|
+
@contents[key]
|
58
|
+
end
|
59
|
+
|
50
60
|
def cache(key, options = {})
|
51
61
|
fragment, expired_at = @cache[key]
|
52
62
|
|
@@ -98,6 +108,12 @@ describe Curly::TemplateHandler do
|
|
98
108
|
output.should be_html_safe
|
99
109
|
end
|
100
110
|
|
111
|
+
it "calls the #setup! method before rendering the view" do
|
112
|
+
template.stub(:source) { "{{foo}}" }
|
113
|
+
output
|
114
|
+
context.content_for(:foo).should == "bar"
|
115
|
+
end
|
116
|
+
|
101
117
|
context "caching" do
|
102
118
|
before do
|
103
119
|
template.stub(:source) { "{{bar}}" }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: curly-templates
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-06-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionpack
|
@@ -109,6 +109,7 @@ executables: []
|
|
109
109
|
extensions: []
|
110
110
|
extra_rdoc_files: []
|
111
111
|
files:
|
112
|
+
- CHANGELOG.md
|
112
113
|
- Gemfile
|
113
114
|
- README.md
|
114
115
|
- Rakefile
|
@@ -124,6 +125,7 @@ files:
|
|
124
125
|
- lib/generators/curly/controller/controller_generator.rb
|
125
126
|
- lib/generators/curly/controller/templates/presenter.rb.erb
|
126
127
|
- lib/generators/curly/controller/templates/view.html.curly.erb
|
128
|
+
- lib/rails/projections.json
|
127
129
|
- spec/compiler_spec.rb
|
128
130
|
- spec/generators/controller_generator_spec.rb
|
129
131
|
- spec/presenter_spec.rb
|
@@ -145,7 +147,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
145
147
|
version: '0'
|
146
148
|
segments:
|
147
149
|
- 0
|
148
|
-
hash:
|
150
|
+
hash: 3268332445838018672
|
149
151
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
152
|
none: false
|
151
153
|
requirements:
|