curly-templates 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ ### Unreleased
2
+
3
+ ### Curly 0.9.0 (June 4, 2013)
4
+
5
+ * Allow running setup code before rendering a Curly view. Simply add a `#setup!`
6
+ method to your presenter – it will be called by Curly just before the view is
7
+ rendered.
8
+
9
+ *Daniel Schierbeck*
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
- Is it ready to use in production?
91
- ---------------------------------
108
+ Presenters
109
+ ----------
92
110
 
93
- Yes! While still a young project, it's being used in a rather large Rails app
94
- at Zendesk, where it performs admirably.
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 -- it will be looked up by Rails automatically.
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 "Dynamic Caching.")
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:
@@ -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.0'
8
- s.date = '2013-05-22'
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
@@ -26,7 +26,7 @@
26
26
  # See Curly::Presenter for more information on presenters.
27
27
  #
28
28
  module Curly
29
- VERSION = "0.8.0"
29
+ VERSION = "0.9.0"
30
30
 
31
31
  # Compiles a Curly template to Ruby code.
32
32
  #
@@ -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
@@ -42,6 +42,8 @@ class Curly::TemplateHandler
42
42
  #{source}
43
43
  end
44
44
 
45
+ presenter.setup!
46
+
45
47
  if key = presenter.cache_key
46
48
  @output_buffer = ActiveSupport::SafeBuffer.new
47
49
 
@@ -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.8.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-05-22 00:00:00.000000000 Z
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: 2436310145351861333
150
+ hash: 3268332445838018672
149
151
  required_rubygems_version: !ruby/object:Gem::Requirement
150
152
  none: false
151
153
  requirements: