draper 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/CHANGELOG.md +3 -0
  2. data/CONTRIBUTING.md +5 -1
  3. data/Gemfile +23 -9
  4. data/README.md +144 -52
  5. data/Rakefile +1 -0
  6. data/draper.gemspec +1 -1
  7. data/lib/draper.rb +9 -6
  8. data/lib/draper/decoratable.rb +3 -7
  9. data/lib/draper/decoratable/equality.rb +14 -0
  10. data/lib/draper/decorator.rb +4 -7
  11. data/lib/draper/helper_proxy.rb +22 -3
  12. data/lib/draper/test/devise_helper.rb +18 -22
  13. data/lib/draper/test/rspec_integration.rb +4 -0
  14. data/lib/draper/test_case.rb +20 -0
  15. data/lib/draper/version.rb +1 -1
  16. data/lib/draper/view_context.rb +75 -13
  17. data/lib/draper/view_context/build_strategy.rb +48 -0
  18. data/lib/draper/view_helpers.rb +2 -2
  19. data/spec/draper/collection_decorator_spec.rb +169 -196
  20. data/spec/draper/decoratable/equality_spec.rb +10 -0
  21. data/spec/draper/decoratable_spec.rb +107 -132
  22. data/spec/draper/decorated_association_spec.rb +99 -96
  23. data/spec/draper/decorator_spec.rb +408 -434
  24. data/spec/draper/finders_spec.rb +160 -126
  25. data/spec/draper/helper_proxy_spec.rb +38 -8
  26. data/spec/draper/view_context/build_strategy_spec.rb +116 -0
  27. data/spec/draper/view_context_spec.rb +154 -0
  28. data/spec/draper/view_helpers_spec.rb +4 -37
  29. data/spec/dummy/app/controllers/posts_controller.rb +7 -0
  30. data/spec/dummy/app/decorators/post_decorator.rb +26 -2
  31. data/spec/dummy/app/helpers/application_helper.rb +3 -0
  32. data/spec/dummy/app/mailers/post_mailer.rb +10 -0
  33. data/spec/dummy/app/models/admin.rb +5 -0
  34. data/spec/dummy/app/models/mongoid_post.rb +5 -0
  35. data/spec/dummy/app/models/user.rb +5 -0
  36. data/spec/dummy/app/views/posts/_post.html.erb +15 -0
  37. data/spec/dummy/bin/rails +4 -0
  38. data/spec/dummy/config/application.rb +9 -3
  39. data/spec/dummy/config/boot.rb +2 -7
  40. data/spec/dummy/config/environments/development.rb +2 -3
  41. data/spec/dummy/config/environments/production.rb +2 -0
  42. data/spec/dummy/config/environments/test.rb +3 -4
  43. data/spec/dummy/config/initializers/secret_token.rb +1 -0
  44. data/spec/dummy/config/mongoid.yml +80 -0
  45. data/spec/dummy/config/routes.rb +2 -0
  46. data/spec/dummy/fast_spec/post_decorator_spec.rb +38 -0
  47. data/spec/dummy/lib/tasks/test.rake +11 -5
  48. data/spec/dummy/spec/decorators/devise_spec.rb +64 -0
  49. data/spec/dummy/spec/decorators/helpers_spec.rb +21 -0
  50. data/spec/dummy/spec/decorators/post_decorator_spec.rb +26 -6
  51. data/spec/dummy/spec/decorators/spec_type_spec.rb +7 -0
  52. data/spec/dummy/spec/decorators/view_context_spec.rb +22 -0
  53. data/spec/dummy/spec/mailers/post_mailer_spec.rb +10 -6
  54. data/spec/dummy/spec/models/mongoid_post_spec.rb +10 -0
  55. data/spec/dummy/spec/models/post_spec.rb +5 -5
  56. data/spec/dummy/spec/spec_helper.rb +1 -0
  57. data/spec/dummy/test/decorators/minitest/devise_test.rb +64 -0
  58. data/spec/dummy/test/decorators/minitest/helpers_test.rb +21 -0
  59. data/spec/dummy/{mini_test/mini_test_integration_test.rb → test/decorators/minitest/spec_type_test.rb} +9 -3
  60. data/spec/dummy/test/decorators/minitest/view_context_test.rb +24 -0
  61. data/spec/dummy/test/decorators/test_unit/devise_test.rb +64 -0
  62. data/spec/dummy/test/decorators/test_unit/helpers_test.rb +21 -0
  63. data/spec/dummy/test/decorators/test_unit/view_context_test.rb +24 -0
  64. data/spec/dummy/test/minitest_helper.rb +4 -0
  65. data/spec/dummy/test/test_helper.rb +3 -0
  66. data/spec/generators/decorator/decorator_generator_spec.rb +1 -0
  67. data/spec/integration/integration_spec.rb +31 -6
  68. data/spec/spec_helper.rb +32 -25
  69. data/spec/support/shared_examples/decoratable_equality.rb +40 -0
  70. data/spec/support/shared_examples/view_helpers.rb +39 -0
  71. metadata +56 -44
  72. data/spec/dummy/README.rdoc +0 -261
  73. data/spec/dummy/spec/decorators/rspec_integration_spec.rb +0 -19
  74. data/spec/support/action_controller.rb +0 -12
  75. data/spec/support/active_model.rb +0 -7
  76. data/spec/support/active_record.rb +0 -9
  77. data/spec/support/decorators/decorator_with_application_helper.rb +0 -25
  78. data/spec/support/decorators/namespaced_product_decorator.rb +0 -5
  79. data/spec/support/decorators/non_active_model_product_decorator.rb +0 -2
  80. data/spec/support/decorators/product_decorator.rb +0 -23
  81. data/spec/support/decorators/products_decorator.rb +0 -10
  82. data/spec/support/decorators/some_thing_decorator.rb +0 -2
  83. data/spec/support/decorators/specific_product_decorator.rb +0 -2
  84. data/spec/support/decorators/widget_decorator.rb +0 -2
  85. data/spec/support/models/namespaced_product.rb +0 -49
  86. data/spec/support/models/non_active_model_product.rb +0 -3
  87. data/spec/support/models/product.rb +0 -95
  88. data/spec/support/models/some_thing.rb +0 -5
  89. data/spec/support/models/uninferrable_decorator_model.rb +0 -3
  90. data/spec/support/models/widget.rb +0 -2
@@ -2,6 +2,9 @@
2
2
 
3
3
  ## 1.0.0
4
4
 
5
+ Major changes from 0.18.0 to 1.0.0 are outlined [in the wiki](https://github.com/drapergem/draper/wiki/Upgrading-to-1.0).
6
+
7
+
5
8
  * Infer collection decorators. [https://github.com/drapergem/draper/commit/e8253df7dc6c90a542444c0f4ef289909fce4f90](https://github.com/drapergem/draper/commit/e8253df7dc6c90a542444c0f4ef289909fce4f90)
6
9
 
7
10
  * Prevent calls to `scoped` on decorated associations. [https://github.com/drapergem/draper/commit/5dcc6c31ecf408753158d15fed9fb23fbfdc3734](https://github.com/drapergem/draper/commit/5dcc6c31ecf408753158d15fed9fb23fbfdc3734)
@@ -1,4 +1,8 @@
1
- # Contributing to Draper
1
+ ## Filing issues
2
+
3
+ To help us fix the problem you've found, please let us know your versions of Draper and Rails (and any other gems that are relevant to your issue, e.g. RSpec if you're having trouble in your tests).
4
+
5
+ ## Sending a pull request
2
6
 
3
7
  So you want to help us out... thanks! Here's a quick how-to:
4
8
 
data/Gemfile CHANGED
@@ -8,16 +8,30 @@ end
8
8
 
9
9
  platforms :jruby do
10
10
  gem "minitest", ">= 3.0"
11
- gem "activerecord-jdbcsqlite3-adapter", "~> 1.2.2.1"
11
+ gem "activerecord-jdbcsqlite3-adapter"
12
12
  end
13
13
 
14
- case ENV["RAILS_VERSION"]
14
+ version = ENV["RAILS_VERSION"] || "3.2"
15
+
16
+ rails = case version
17
+ when "master"
18
+ {github: "rails/rails"}
19
+ else
20
+ "~> #{version}.0"
21
+ end
22
+
23
+ mongoid = case version
15
24
  when "master"
16
- gem "rails", github: "rails/rails"
17
- when "3.2", nil
18
- gem "rails", "~> 3.2.0"
19
- when "3.1"
20
- gem "rails", "~> 3.1.0"
21
- when "3.0"
22
- gem "rails", "~> 3.0.0"
25
+ {github: "mongoid/mongoid", branch: "4.0.0-dev"}
26
+ when "3.1", "3.2"
27
+ "~> 3.0.0"
23
28
  end
29
+
30
+ devise = case version
31
+ when "3.1", "3.2"
32
+ "~> 2.2"
33
+ end
34
+
35
+ gem "rails", rails
36
+ gem "mongoid", mongoid if mongoid
37
+ gem "devise", devise if devise
data/README.md CHANGED
@@ -3,12 +3,13 @@
3
3
  [![TravisCI Build Status](https://secure.travis-ci.org/drapergem/draper.png?branch=master)](http://travis-ci.org/drapergem/draper)
4
4
  [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/drapergem/draper)
5
5
 
6
- Draper adds a nicely-separated object-oriented layer of presentation logic to your Rails apps. Previously, this logic might have been tangled up in procedural helpers, or contributing to your fat models' weight problems. Now, you can wrap your models up in decorators to organise - and test - this layer of your app much more effectively.
6
+ Draper adds an object-oriented layer of presentation logic to your Rails application.
7
7
 
8
+ Without Draper, this functionality might have been tangled up in procedural helpers or adding bulk to your models. With Draper decorators, you can wrap your models with presentation-related logic to organise - and test - this layer of your app much more effectively.
8
9
 
9
- ## Overview
10
+ ## Why Use a Decorator?
10
11
 
11
- With Draper, your `Article` model has a corresponding `ArticleDecorator`. The decorator wraps the model, and deals only with presentational concerns. In the controller, you simply decorate your article before handing it off to the view.
12
+ Imagine your application has an `Article` model. With Draper, you'd create a corresponding `ArticleDecorator`. The decorator wraps the model, and deals *only* with presentational concerns. In the controller, you decorate the article before handing it off to the view:
12
13
 
13
14
  ```ruby
14
15
  # app/controllers/articles_controller.rb
@@ -17,7 +18,9 @@ def show
17
18
  end
18
19
  ```
19
20
 
20
- In the view, you can use the decorator in exactly the same way as you would have used the model. The difference is, any time you find yourself needing to write a helper, you can implement a method on the decorator instead. For example, this helper:
21
+ In the view, you can use the decorator in exactly the same way as you would have used the model. But whenever you start needing logic in the view or start thinking about a helper method, you can implement a method on the decorator instead.
22
+
23
+ Let's look at how you could convert an existing Rails helper to a decorator method. You have this existing helper:
21
24
 
22
25
  ```ruby
23
26
  # app/helpers/articles_helper.rb
@@ -30,7 +33,19 @@ def publication_status(article)
30
33
  end
31
34
  ```
32
35
 
33
- could be better written as:
36
+ But it makes you a little uncomfortable. `publication_status` lives in a nebulous namespace spread across all controllers and view. Down the road, you might want to display the publication status of a `Book`. And, of course, your design calls for a slighly different formatting to the date for a `Book`.
37
+
38
+ Now your helper method can either switch based on the input class type (poor Ruby style), or you break it out into two methods, `book_publication_status` and `article_publication_status`. And keep adding methods for each publication type...to the global helper namespace. And remember all the names. Ick.
39
+
40
+ Ruby thrives when we use Object-Oriented style. If you didn't know Rails' helpers existed, you'd probably imagine that your view template could feature something like this:
41
+
42
+ ```erb
43
+ <%= @article.publication_status %>
44
+ ```
45
+
46
+ Without a decorator, you'd have to implement the `publication_status` method in the `Article` model. That method is presentation-centric, and thus does not belong in a model.
47
+
48
+ Instead, you implement a decorator:
34
49
 
35
50
  ```ruby
36
51
  # app/decorators/article_decorator.rb
@@ -51,28 +66,28 @@ class ArticleDecorator < Draper::Decorator
51
66
  end
52
67
  ```
53
68
 
54
- Notice that the `published?` method can be called even though `ArticleDecorator` doesn't define it - thanks to `delegate_all`, the decorator delegates missing methods to the source model. However, we can override methods like `published_at` to add presentation-specific formatting, in which case we access the underlying model using the `source` method.
69
+ Within the `publication_status` method we use the `published?` method. Where does that come from? It's a method of the source `Article`, whose methods have been made available on the decorator by the `delegate_all` call above.
55
70
 
56
71
  You might have heard this sort of decorator called a "presenter", an "exhibit", a "view model", or even just a "view" (in that nomenclature, what Rails calls "views" are actually "templates"). Whatever you call it, it's a great way to replace procedural helpers like the one above with "real" object-oriented programming.
57
72
 
58
73
  Decorators are the ideal place to:
59
- * format dates and times using `strftime`,
60
- * define commonly-used representations of an object, like a `name` method that combines `first_name` and `last_name` attributes,
61
- * mark up attributes with a little semantic HTML, like turning a `url` field into a hyperlink.
62
-
74
+ * format complex data for user display
75
+ * define commonly-used representations of an object, like a `name` method that combines `first_name` and `last_name` attributes
76
+ * mark up attributes with a little semantic HTML, like turning a `url` field into a hyperlink
63
77
 
64
78
  ## Installation
65
79
 
66
80
  Add Draper to your Gemfile:
67
81
 
68
82
  ```ruby
69
- gem 'draper', '~> 1.0.0.beta6'
83
+ gem 'draper', '~> 1.0'
70
84
  ```
71
85
 
72
86
  And run `bundle install` within your app's directory.
73
87
 
88
+ If you're upgrading from a 0.x release, the major changes are outlined [in the wiki](https://github.com/drapergem/draper/wiki/Upgrading-to-1.0).
74
89
 
75
- ## Writing decorators
90
+ ## Writing Decorators
76
91
 
77
92
  Decorators inherit from `Draper::Decorator`, live in your `app/decorators` directory, and are named for the model that they decorate:
78
93
 
@@ -85,40 +100,56 @@ end
85
100
 
86
101
  ### Generators
87
102
 
88
- When you generate a resource with `rails generate resource Article`, you get a decorator for free! But if the `Article` model already exists, you can run `rails generate decorator Article` to create the `ArticleDecorator`.
103
+ When you have Draper installed and generate a resource with...
104
+
105
+ ```
106
+ rails generate resource Article
107
+ ```
108
+ ...you'll get a decorator for free!
109
+
110
+ But if the `Article` model already exists, you can run...
111
+
112
+ ```
113
+ rails generate decorator Article
114
+ ```
115
+
116
+ ...to create the `ArticleDecorator`.
89
117
 
90
- ### Accessing helpers
118
+ ### Accessing Helpers
91
119
 
92
- Procedural helpers are still useful for generic tasks like generating HTML, and as such you can access all this goodness (both built-in Rails helpers, and your own) through the `helpers` method:
120
+ Normal Rails helpers are still useful for lots tasks. Both Rails' provided helper and those defined in your app can be accessed via the `h` method:
93
121
 
94
122
  ```ruby
95
123
  class ArticleDecorator < Draper::Decorator
96
124
  def emphatic
97
- helpers.content_tag(:strong, "Awesome")
125
+ h.content_tag(:strong, "Awesome")
98
126
  end
99
127
  end
100
128
  ```
101
129
 
102
- To save your typing fingers it's aliased to `h`. If that's still too much effort, just pop `include Draper::LazyHelpers` at the top of your decorator class - you'll mix in a bazillion methods and never have to type `h.` again... [if that's your sort of thing](https://github.com/garybernhardt/base).
130
+ If writing `h.` frequently is getting you down, you can add...
131
+
132
+ ```
133
+ include Draper::LazyHelpers
134
+ ```
135
+
136
+ ...at the top of your decorator class - you'll mix in a bazillion methods and never have to type `h.` again.
103
137
 
104
138
  ### Accessing the model
105
139
 
106
- Decorators will delegate methods to the model where possible, which means in most cases you can replace a model with a decorator and your view won't notice the difference. When you need to get your hands on the underlying model the `source` method is your friend (and its aliases `model` and `to_source`):
140
+ When writing decorator methods you'll usually need to access the wrapped model. While you may choose to use delegation ([covered below](#delegating-methods)) for convenience, you can always use the `source` (or its alias `model`):
107
141
 
108
142
  ```ruby
109
143
  class ArticleDecorator < Draper::Decorator
110
- delegate_all
111
-
112
144
  def published_at
113
145
  source.published_at.strftime("%A, %B %e")
114
146
  end
115
147
  end
116
148
  ```
117
149
 
150
+ ## Decorating Objects
118
151
 
119
- ## Decorating
120
-
121
- ### Single objects
152
+ ### Single Objects
122
153
 
123
154
  Ok, so you've written a sweet decorator, now you're going to want to put it in action! A simple option is to call the `decorate` method on your model:
124
155
 
@@ -140,10 +171,16 @@ If you have a whole bunch of objects, you can decorate them all in one fell swoo
140
171
 
141
172
  ```ruby
142
173
  @articles = ArticleDecorator.decorate_collection(Article.all)
143
- # or, for scopes (but not `all`)
174
+ ```
175
+
176
+ If your collection is an ActiveRecord query, you can use this:
177
+
178
+ ```ruby
144
179
  @articles = Article.popular.decorate
145
180
  ```
146
181
 
182
+ *Note:* In Rails 3, the `.all` method returns an array and not a query. Thus you _cannot_ use the technique of `Article.all.decorate` in Rails 3. In Rails 4, `.all` returns a query so this techique would work fine.
183
+
147
184
  If you want to add methods to your decorated collection (for example, for pagination), you can subclass `Draper::CollectionDecorator`:
148
185
 
149
186
  ```ruby
@@ -160,9 +197,11 @@ end
160
197
  @articles = ArticlesDecorator.decorate(Article.all)
161
198
  ```
162
199
 
163
- Draper guesses the decorator used for each item from the name of the collection decorator (`ArticlesDecorator` becomes `ArticleDecorator`). If that fails, it falls back to using each item's `decorate` method. Alternatively, you can specify a decorator by overriding the collection decorator's `decorator_class` method.
200
+ Draper infers the decorator used for each item from the name of the collection decorator (`ArticlesDecorator` implies `ArticleDecorator`). If that fails, it falls back to using each item's `decorate` method. Alternatively, you can specify a decorator by overriding the collection decorator's `decorator_class` method.
164
201
 
165
- Some pagination gems add methods to `ActiveRecord::Relation`. For example, [Kaminari](https://github.com/amatsuda/kaminari)'s `paginate` helper method requires the collection to implement `current_page`, `total_pages`, and `limit_value`. To expose these on a collection decorator, you can simply delegate to the `source`:
202
+ #### Using pagination
203
+
204
+ Some pagination gems add methods to `ActiveRecord::Relation`. For example, [Kaminari](https://github.com/amatsuda/kaminari)'s `paginate` helper method requires the collection to implement `current_page`, `total_pages`, and `limit_value`. To expose these on a collection decorator, you can delegate to the `source`:
166
205
 
167
206
  ```ruby
168
207
  class PaginatingDecorator < Draper::CollectionDecorator
@@ -172,9 +211,11 @@ end
172
211
 
173
212
  The `delegate` method used here is the same as that added by [Active Support](http://api.rubyonrails.org/classes/Module.html#method-i-delegate), except that the `:to` option is not required; it defaults to `:source` when omitted.
174
213
 
175
- ### Handy shortcuts
214
+ [will_paginate](https://github.com/mislav/will_paginate) needs you to `delegate :current_page, :per_page, :offset, :total_entries, :total_pages`.
215
+
216
+ ### Decorating Associated Objects
176
217
 
177
- You can automatically decorate associated models:
218
+ You can automatically decorate associated models when the primary model is decorated. Assuming an `Article` model has an associated `Author` object:
178
219
 
179
220
  ```ruby
180
221
  class ArticleDecorator < Draper::Decorator
@@ -182,7 +223,11 @@ class ArticleDecorator < Draper::Decorator
182
223
  end
183
224
  ```
184
225
 
185
- And, if you want, you can add decorated finder methods:
226
+ When `ArticleDecorator` decorates an `Article`, it will also use `AuthorDecorator` to decorate the associated `Author`.
227
+
228
+ ### Decorated Finders
229
+
230
+ You can call `decorates_finders` in a decorator...
186
231
 
187
232
  ```ruby
188
233
  class ArticleDecorator < Draper::Decorator
@@ -190,39 +235,62 @@ class ArticleDecorator < Draper::Decorator
190
235
  end
191
236
  ```
192
237
 
193
- so that you can do:
238
+ ...which allows you to then call all the normal ActiveRecord-style finders on your `ArticleDecorator` and they'll return decorated objects:
194
239
 
195
240
  ```ruby
196
241
  @article = ArticleDecorator.find(params[:id])
197
242
  ```
198
243
 
199
-
200
244
  ## Testing
201
245
 
202
246
  Draper supports RSpec, MiniTest::Rails, and Test::Unit, and will add the appropriate tests when you generate a decorator.
203
247
 
204
248
  ### RSpec
205
249
 
206
- Your specs should live in `spec/decorators` (if not, you need to tag them with `type: :decorator`).
250
+ Your specs are expected to live in `spec/decorators`. If you use a different path, you need to tag them with `type: :decorator`.
207
251
 
208
- In controller specs, you might want to check whether your instance variables are being decorated properly. You can use the handy predicate matchers:
252
+ In a controller spec, you might want to check whether your instance variables are being decorated properly. You can use the handy predicate matchers:
209
253
 
210
254
  ```ruby
211
255
  assigns(:article).should be_decorated
256
+
212
257
  # or, if you want to be more specific
213
258
  assigns(:article).should be_decorated_with ArticleDecorator
214
259
  ```
215
260
 
216
261
  Note that `model.decorate == model`, so your existing specs shouldn't break when you add the decoration.
217
262
 
218
- Spork users should `require 'draper/test/rspec_integration'` in the `Spork.prefork` block.
263
+ #### Spork Users
264
+
265
+ In your `Spork.prefork` block of `spec_helper.rb`, add this:
266
+
267
+ ```ruby
268
+ require 'draper/test/rspec_integration'
269
+ ```
270
+
271
+ ### Isolated tests
272
+
273
+ In tests, Draper needs to build a view context to access helper methods. By default, it will create an `ApplicationController` and then use its view context. If you are speeding up your test suite by testing each component in isolation, you can eliminate this dependency by putting the following in your `spec_helper` or similar:
219
274
 
275
+ ```ruby
276
+ Draper::ViewContext.test_strategy :fast
277
+ ```
278
+
279
+ In doing so, your decorators will no longer have access to your application's helpers. If you need to selectively include such helpers, you can pass a block:
280
+
281
+ ```ruby
282
+ Draper::ViewContext.test_strategy :fast do
283
+ include ApplicationHelper
284
+ end
285
+ ```
220
286
 
221
287
  ## Advanced usage
222
288
 
223
- ### `ApplicationDecorator`
289
+ ### Shared Decorator Methods
290
+
291
+ You might have several decorators that share similar needs. Since decorators are just Ruby objects, you can use any normal Ruby technique for sharing functionality.
224
292
 
225
- If you need common methods in your decorators, you can create an `ApplicationDecorator`:
293
+ In Rails controllers, common functionality is organized by having all controllers inherit from `ApplicationController`. You can apply this same pattern to your decorators:
226
294
 
227
295
  ```ruby
228
296
  # app/decorators/application_decorator.rb
@@ -231,24 +299,47 @@ class ApplicationDecorator < Draper::Decorator
231
299
  end
232
300
  ```
233
301
 
234
- and inherit from it instead of directly from `Draper::Decorator`.
302
+ Then modify your decorators to inherit from that `ApplicationDecorator` instead of directly from `Draper::Decorator`:
235
303
 
236
- ### Enforcing an interface between controllers and views
304
+ ```ruby
305
+ class ArticleDecorator < ApplicationDecorator
306
+ # decorator methods
307
+ end
308
+ ```
309
+
310
+ ### Delegating Methods
237
311
 
238
- The `delegate_all` call at the top of your decorator means that all missing methods will delegated to the source. If you want to strictly control which methods are called in your views, you can choose to only delegate certain methods.
312
+ When your decorator calls `delegate_all`, any method called on the decorator not defined in the decorator itself will be delegated to the decorated source. This is a very permissive interface.
313
+
314
+ If you want to strictly control which methods are called within views, you can choose to only delegate certain methods from the decorator to the source model:
239
315
 
240
316
  ```ruby
241
317
  class ArticleDecorator < Draper::Decorator
242
- delegate :title, :author
318
+ delegate :title, :body
243
319
  end
244
320
  ```
245
321
 
246
- As mentioned above for `CollectionDecorator`, the `delegate` method defaults to using `:source` if the `:to` option is omitted.
322
+ We omit the `:to` argument here as it defaults to the `source` object. You could choose to delegate methods to other places like this:
247
323
 
324
+ ```ruby
325
+ class ArticleDecorator < Draper::Decorator
326
+ delegate :title, :body
327
+ delegate :name, :title, to: :author, prefix: true
328
+ end
329
+ ```
330
+
331
+ From your view template, assuming `@article` is decorated, you could do any of the following:
332
+
333
+ ```ruby
334
+ @article.title # Returns the article's `.title`
335
+ @article.body # Returns the article's `.body`
336
+ @article.author_name # Returns the article's `author.name`
337
+ @article.author_title # Returns the article's `author.title`
338
+ ```
248
339
 
249
340
  ### Adding context
250
341
 
251
- If you need to pass extra data to your decorators, you can use a `context` hash. Methods that create decorators take it as an option, for example
342
+ If you need to pass extra data to your decorators, you can use a `context` hash. Methods that create decorators take it as an option, for example:
252
343
 
253
344
  ```ruby
254
345
  Article.first.decorate(context: {role: :admin})
@@ -264,7 +355,7 @@ class ArticleDecorator < Draper::Decorator
264
355
  end
265
356
  ```
266
357
 
267
- or, if you simply want to modify the parent's context, use a lambda that takes a hash and returns a new hash:
358
+ or, if you want to modify the parent's context, use a lambda that takes a hash and returns a new hash:
268
359
 
269
360
  ```ruby
270
361
  class ArticleDecorator < Draper::Decorator
@@ -273,9 +364,9 @@ class ArticleDecorator < Draper::Decorator
273
364
  end
274
365
  ```
275
366
 
276
- ### Specifying decorators
367
+ ### Specifying Decorators
277
368
 
278
- When you're using `decorates_association`, Draper uses the `decorate` method on the associated record (or each associated record, in the case of a collection association) to perform the decoration. If you want use a specific decorator, you can use the `:with` option:
369
+ When you're using `decorates_association`, Draper uses the `decorate` method on the associated record(s) to perform the decoration. If you want use a specific decorator, you can use the `:with` option:
279
370
 
280
371
  ```ruby
281
372
  class ArticleDecorator < Draper::Decorator
@@ -285,9 +376,9 @@ end
285
376
 
286
377
  For a collection association, you can specify a `CollectionDecorator` subclass, which is applied to the whole collection, or a singular `Decorator` subclass, which is applied to each item individually.
287
378
 
288
- ### Scoping associations
379
+ ### Scoping Associations
289
380
 
290
- If you want your decorated association to be ordered, limited, or otherwise scoped, you can pass a `:scope` option to `decorates_association`, which will be applied to the collection before decoration:
381
+ If you want your decorated association to be ordered, limited, or otherwise scoped, you can pass a `:scope` option to `decorates_association`, which will be applied to the collection *before* decoration:
291
382
 
292
383
  ```ruby
293
384
  class ArticleDecorator < Draper::Decorator
@@ -295,9 +386,11 @@ class ArticleDecorator < Draper::Decorator
295
386
  end
296
387
  ```
297
388
 
298
- ### Breaking with convention
389
+ ### Proxying Class Methods
390
+
391
+ If you want to proxy class methods to the wrapped model class, including when using `decorates_finders`, Draper needs to know the model class. By default, it assumes that your decorators are named `SomeModelDecorator`, and then attempts to proxy unknown class methods to `SomeModel`.
299
392
 
300
- If, as well as instance methods, you want to proxy class methods to the model through the decorator (including when using `decorates_finders`), Draper needs to know the model class. By default, it assumes that your decorators are named `SomeModelDecorator`, and then attempts to proxy unknown class methods to `SomeModel`. If your model name can't be inferred from your decorator name in this way, you need to use the `decorates` method:
393
+ If your model name can't be inferred from your decorator name in this way, you need to use the `decorates` method:
301
394
 
302
395
  ```ruby
303
396
  class MySpecialArticleDecorator < Draper::Decorator
@@ -305,12 +398,11 @@ class MySpecialArticleDecorator < Draper::Decorator
305
398
  end
306
399
  ```
307
400
 
308
- You don't need to worry about this if you don't want to proxy class methods.
401
+ This is only necessary when proxying class methods.
309
402
 
310
403
  ### Making models decoratable
311
404
 
312
- Models get their `decorate` method from the `Draper::Decoratable` module, which is included in `ActiveRecord::Base` and `Mongoid::Document` by default. If you're using another ORM, or want to decorate plain old Ruby objects, you can include this module manually.
313
-
405
+ Models get their `decorate` method from the `Draper::Decoratable` module, which is included in `ActiveRecord::Base` and `Mongoid::Document` by default. If you're [using another ORM](https://github.com/drapergem/draper/wiki/Using-other-ORMs) (including versions of Mongoid prior to 3.0), or want to decorate plain old Ruby objects, you can include this module manually.
314
406
 
315
407
  ## Contributors
316
408