draper 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme.markdown +27 -47
- data/lib/draper/base.rb +1 -0
- data/lib/draper/version.rb +1 -1
- data/spec/base_spec.rb +5 -0
- metadata +1 -1
data/Readme.markdown
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
2. Run `rails g draper:decorator YourModel`
|
9
9
|
3. Edit `app/decorators/[your_model]_decorator.rb` using:
|
10
10
|
1. `h` to proxy to Rails/application helpers like `h.current_user`
|
11
|
-
2. `
|
11
|
+
2. `[your_model]` to access the wrapped object like `article.created_at`
|
12
12
|
4. Put common decorations in `app/decorators/application.rb`
|
13
13
|
5. Wrap models in your controller with the decorator using:
|
14
14
|
1. `.find` automatic lookup & wrap
|
@@ -20,6 +20,17 @@
|
|
20
20
|
6. Output the instance methods in your view templates
|
21
21
|
ex: `@article_decorator.created_at`
|
22
22
|
|
23
|
+
## What's New
|
24
|
+
|
25
|
+
### Version 0.9.1
|
26
|
+
|
27
|
+
* Automatically generate a named accessor for the wrapped object, so now inside of `ArticleDecorator` you can use `article` instead of just `model`
|
28
|
+
* Removed the `lazy_helpers` method to favor using `include Draper::LazyHelpers`
|
29
|
+
* Refactored how methods are selected for delegation to the wrapped model
|
30
|
+
* Fixed how the view context is stored in the `Thread.current` to resolve cross-request issues
|
31
|
+
* Decorated collections now return a collection proxy instead of an array, which fixes many compatibility issues
|
32
|
+
* Automatically generate `RSpec` stub for decorators [PENDING: Make this work properly for `Test::Unit` -- help?]
|
33
|
+
|
23
34
|
## Goals
|
24
35
|
|
25
36
|
This gem makes it easy to apply the decorator pattern to domain models in a Rails application. This pattern gives you three wins:
|
@@ -38,8 +49,8 @@ A decorator wraps an object with presentation-related accessor methods. For inst
|
|
38
49
|
class ArticleDecorator < ApplicationDecorator
|
39
50
|
decorates :article
|
40
51
|
def published_at
|
41
|
-
date = h.content_tag(:span,
|
42
|
-
time = h.content_tag(:span,
|
52
|
+
date = h.content_tag(:span, article.published_at.strftime("%A, %B %e").squeeze(" "), :class => 'date')
|
53
|
+
time = h.content_tag(:span, article.published_at.strftime("%l:%M%p"), :class => 'time').delete(" ")
|
43
54
|
h.content_tag :span, date + time, :class => 'created_at'
|
44
55
|
end
|
45
56
|
end
|
@@ -63,7 +74,7 @@ class ArticleDecorator < ApplicationDecorator
|
|
63
74
|
|
64
75
|
def to_json
|
65
76
|
attr_set = h.current_user.admin? ? ADMIN_VISIBLE_ATTRIBUTES : PUBLIC_VISIBLE_ATTRIBUTES
|
66
|
-
|
77
|
+
article.to_json(:only => attr_set)
|
67
78
|
end
|
68
79
|
end
|
69
80
|
```
|
@@ -122,36 +133,7 @@ Add the dependency to your `Gemfile`:
|
|
122
133
|
gem "draper"
|
123
134
|
```
|
124
135
|
|
125
|
-
|
126
|
-
|
127
|
-
```
|
128
|
-
bundle
|
129
|
-
```
|
130
|
-
|
131
|
-
#### Disable Rails Helper Generation (Optional)
|
132
|
-
|
133
|
-
When you generate a scaffold, Rails will create a matching helper file. If you're using decorators, this is probably unnecessary. You can disable the helper file creation by adding this to your `config/application.rb`
|
134
|
-
|
135
|
-
```ruby
|
136
|
-
config.generators do |g|
|
137
|
-
g.helper false
|
138
|
-
end
|
139
|
-
```
|
140
|
-
If you want a helper, you can still call `rails generate helper` directly.
|
141
|
-
|
142
|
-
|
143
|
-
#### Add DecoratorGenerator to ActiveRecord Generator (Optional)
|
144
|
-
|
145
|
-
Add the following to your `config/application.rb`
|
146
|
-
|
147
|
-
```ruby
|
148
|
-
config.generators do |g|
|
149
|
-
g.orm :decorator, :invoke_after_finished => "active_record:model"
|
150
|
-
end
|
151
|
-
```
|
152
|
-
|
153
|
-
From now on, every model you generate will first invoke the DecoratorGenerator. The Decorator will then invoke the active_record:model Generator.
|
154
|
-
|
136
|
+
Then run `bundle` from the project directory.
|
155
137
|
|
156
138
|
### Generate the Decorator
|
157
139
|
|
@@ -163,14 +145,14 @@ rails generate draper:decorator Article
|
|
163
145
|
|
164
146
|
### Writing Methods
|
165
147
|
|
166
|
-
Open the decorator model (ex: `app/decorators/article_decorator.rb`) and add normal instance methods. To access the wrapped source object, use the `
|
148
|
+
Open the decorator model (ex: `app/decorators/article_decorator.rb`) and add normal instance methods. To access the wrapped source object, use a method named after the `decorates` argument:
|
167
149
|
|
168
150
|
```ruby
|
169
151
|
class ArticleDecorator < ApplicationDecorator
|
170
152
|
decorates :article
|
171
153
|
|
172
154
|
def author_name
|
173
|
-
|
155
|
+
article.author.first_name + " " + article.author.last_name
|
174
156
|
end
|
175
157
|
end
|
176
158
|
```
|
@@ -184,8 +166,8 @@ class ArticleDecorator < ApplicationDecorator
|
|
184
166
|
decorates :article
|
185
167
|
|
186
168
|
def published_at
|
187
|
-
date = h.content_tag(:span,
|
188
|
-
time = h.content_tag(:span,
|
169
|
+
date = h.content_tag(:span, article.published_at.strftime("%A, %B %e").squeeze(" "), :class => 'date')
|
170
|
+
time = h.content_tag(:span, article.published_at.strftime("%l:%M%p"), :class => 'time').delete(" ")
|
189
171
|
h.content_tag :span, date + time, :class => 'created_at'
|
190
172
|
end
|
191
173
|
end
|
@@ -201,8 +183,8 @@ class ArticleDecorator < ApplicationDecorator
|
|
201
183
|
include Draper::LazyHelpers
|
202
184
|
|
203
185
|
def published_at
|
204
|
-
date = content_tag(:span,
|
205
|
-
time = content_tag(:span,
|
186
|
+
date = content_tag(:span, article.published_at.strftime("%A, %B %e").squeeze(" "), :class => 'date')
|
187
|
+
time = content_tag(:span, article.published_at.strftime("%l:%M%p"), :class => 'time').delete(" ")
|
206
188
|
content_tag :span, date + time, :class => 'created_at'
|
207
189
|
end
|
208
190
|
end
|
@@ -222,7 +204,7 @@ ArticleDecorator.new(Article.find(params[:id]))`
|
|
222
204
|
|
223
205
|
```ruby
|
224
206
|
ArticleDecorator.decorate(Article.first) # Returns one instance of ArticleDecorator
|
225
|
-
ArticleDecorator.decorate(Article.all) # Returns an
|
207
|
+
ArticleDecorator.decorate(Article.all) # Returns an enumeration proxy of ArticleDecorator instances
|
226
208
|
```
|
227
209
|
|
228
210
|
* Call `.find` to do automatically do a lookup on the `decorates` class:
|
@@ -274,8 +256,8 @@ Now open up the created `app/decorators/article_decorator.rb` and you'll find an
|
|
274
256
|
|
275
257
|
```ruby
|
276
258
|
def published_at
|
277
|
-
date = h.content_tag(:span,
|
278
|
-
time = h.content_tag(:span,
|
259
|
+
date = h.content_tag(:span, article.published_at.strftime("%A, %B %e").squeeze(" "), :class => 'date')
|
260
|
+
time = h.content_tag(:span, article.published_at.strftime("%l:%M%p").delete(" "), :class => 'time')
|
279
261
|
h.content_tag :span, date + time, :class => 'published_at'
|
280
262
|
end
|
281
263
|
```
|
@@ -303,8 +285,8 @@ class ArticleDecorator < ApplicationDecorator
|
|
303
285
|
decorates :article
|
304
286
|
|
305
287
|
def published_at
|
306
|
-
date = h.content_tag(:span,
|
307
|
-
time = h.content_tag(:span,
|
288
|
+
date = h.content_tag(:span, article.published_at.strftime("%A, %B %e").squeeze(" "), :class => 'date')
|
289
|
+
time = h.content_tag(:span, article.published_at.strftime("%l:%M%p"), :class => 'time').delete(" ")
|
308
290
|
h.content_tag :span, date + time, :class => 'published_at'
|
309
291
|
end
|
310
292
|
end
|
@@ -317,8 +299,6 @@ end
|
|
317
299
|
* Add information about the `.decorator` method
|
318
300
|
* Make clear the pattern of overriding accessor methods of the wrapped model
|
319
301
|
* Build sample Rails application(s)
|
320
|
-
* Add a short screencast
|
321
|
-
* Add YARD documentation to source
|
322
302
|
* Add a section about contributing
|
323
303
|
* Generators
|
324
304
|
* Implement hook so generating a controller/scaffold generates a decorator
|
data/lib/draper/base.rb
CHANGED
data/lib/draper/version.rb
CHANGED
data/spec/base_spec.rb
CHANGED
@@ -40,6 +40,11 @@ describe Draper::Base do
|
|
40
40
|
BusinessDecorator.model_class.should == Business
|
41
41
|
end.should_not raise_error
|
42
42
|
end
|
43
|
+
|
44
|
+
it "creates a named accessor for the wrapped model" do
|
45
|
+
pd = ProductDecorator.new(source)
|
46
|
+
pd.send(:product).should == source
|
47
|
+
end
|
43
48
|
end
|
44
49
|
|
45
50
|
context(".model / .to_model") do
|