dekorator 1.0.0.pre.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +51 -0
  3. data/CHANGELOG.md +20 -4
  4. data/CODE_OF_CONDUCT.md +1 -1
  5. data/README.md +104 -38
  6. data/benchmarks/README.md +7 -0
  7. data/benchmarks/benchmark.rb +135 -0
  8. data/dekorator.gemspec +24 -11
  9. data/lib/dekorator.rb +67 -39
  10. data/lib/dekorator/rails/controller.rb +17 -0
  11. data/lib/dekorator/railtie.rb +9 -5
  12. data/lib/dekorator/version.rb +1 -1
  13. data/lib/generators/decorator_generator.rb +7 -0
  14. data/lib/generators/{decorator → dekorator/decorator}/USAGE +1 -1
  15. data/lib/generators/dekorator/decorator/decorator_generator.rb +17 -0
  16. data/lib/generators/{decorator → dekorator/decorator}/templates/decorator.rb +0 -0
  17. data/lib/generators/dekorator/{install_generator.rb → install/install_generator.rb} +8 -6
  18. data/lib/generators/rspec/decorator_generator.rb +2 -0
  19. data/lib/generators/test_unit/decorator_generator.rb +2 -0
  20. metadata +22 -36
  21. data/.editorconfig +0 -14
  22. data/.gitignore +0 -11
  23. data/.rspec +0 -3
  24. data/.rubocop.yml +0 -114
  25. data/.simplecov +0 -5
  26. data/.travis.yml +0 -37
  27. data/Appraisals +0 -17
  28. data/Gemfile +0 -22
  29. data/Gemfile.lock +0 -157
  30. data/bin/console +0 -16
  31. data/bin/setup +0 -8
  32. data/gemfiles/.bundle/config +0 -2
  33. data/gemfiles/rails_5.0.x.gemfile +0 -21
  34. data/gemfiles/rails_5.0.x.gemfile.lock +0 -207
  35. data/gemfiles/rails_5.1.x.gemfile +0 -21
  36. data/gemfiles/rails_5.1.x.gemfile.lock +0 -207
  37. data/gemfiles/rails_5.2.x.gemfile +0 -21
  38. data/gemfiles/rails_5.2.x.gemfile.lock +0 -207
  39. data/gemfiles/rails_6.0.x.gemfile +0 -21
  40. data/gemfiles/rails_6.0.x.gemfile.lock +0 -220
  41. data/lib/dekorator/decorators_helper.rb +0 -5
  42. data/lib/dekorator/rspec.rb +0 -0
  43. data/lib/generators/decorator/decorator_generator.rb +0 -11
  44. data/lib/generators/decorator/templates/decorator_test.rb +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92168b3d181e861e0c2649e7f6a56165da132af21e251ddaa92d08e6f98381b8
4
- data.tar.gz: ac455c756a54061271316b83e37025353a9371480b19f212aabdc37a72056f66
3
+ metadata.gz: e632f3f499971f15713b16354a960d3c0c2e42436694a040d5a77c8627baec7a
4
+ data.tar.gz: 1318630635b3406f2336d0d144d1651c0b66bb013e4f5e342c726314ba145b30
5
5
  SHA512:
6
- metadata.gz: 75e15ec204e2ce9645209582b70009c21690857df2eca9098b3d45ffc725bd92cc673d65d7ae0f2f69515a26befcaedf85dd7a80fae520b6d4b22d17982f15f7
7
- data.tar.gz: 6432e281aa9ff6dee4fb31b247f4ffa216b35fe3cc522f794e0d75040518c9cb3e318fcc3e053a9e9daa3ec346a6778b75dc906e580b66b21ae659d95e50dbe3
6
+ metadata.gz: c51f4aa3459a64007d77e6f33361e2fdacceb56893f05cfef773c2bd0401ea92cb021bd6fc8153ff8b679fcff52de642fe7338d8cefe448b59595edc36e1ed19
7
+ data.tar.gz: 453e6c9a109f4b0c791a211365284adac236496dd7e7f7280103066f074e867c103f9d1c298b5096f3228e9bc4627f73713da659c38e62e5e20af5b0eaa74909
@@ -0,0 +1,51 @@
1
+ name: Tests
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ name: Ruby ${{ matrix.versions.ruby }}, Rails ${{ matrix.versions.rails }}
8
+ runs-on: ubuntu-latest
9
+ strategy:
10
+ matrix:
11
+ versions:
12
+ - { ruby: "2.4.x", rails: "5.0.x" }
13
+ - { ruby: "2.5.x", rails: "5.0.x" }
14
+ - { ruby: "2.6.x", rails: "5.0.x" }
15
+ - { ruby: "2.4.x", rails: "5.1.x" }
16
+ - { ruby: "2.5.x", rails: "5.1.x" }
17
+ - { ruby: "2.6.x", rails: "5.1.x" }
18
+ - { ruby: "2.4.x", rails: "5.2.x" }
19
+ - { ruby: "2.5.x", rails: "5.2.x" }
20
+ - { ruby: "2.6.x", rails: "5.2.x" }
21
+ - { ruby: "2.5.x", rails: "6.0.x" }
22
+ - { ruby: "2.6.x", rails: "6.0.x" }
23
+
24
+ steps:
25
+ - uses: actions/checkout@v1
26
+
27
+ - uses: actions/cache@v1
28
+ id: cache
29
+ with:
30
+ path: gemfiles/vendor/bundle
31
+ key: ruby-${{ matrix.versions.ruby }}-rails-${{ matrix.versions.rails }}
32
+
33
+ - name: Set up Ruby
34
+ uses: actions/setup-ruby@v1
35
+ with:
36
+ ruby-version: ${{ matrix.versions.ruby }}
37
+
38
+ - name: Set up bundler
39
+ run: |
40
+ echo 'gem: --no-document' >> ~/.gemrc
41
+ gem install bundler
42
+ bundle config --global gemfile gemfiles/rails_${{ matrix.versions.rails }}.gemfile
43
+ bundle config --global path vendor/bundle
44
+
45
+ - name: Install gems
46
+ run: |
47
+ bundle install --jobs $(nproc) --retry 3
48
+
49
+ - name: Test with Rake
50
+ run: |
51
+ bundle exec rake test:all_with_coverage
@@ -1,4 +1,5 @@
1
1
  # Changelog
2
+
2
3
  All notable changes to this project will be documented in this file.
3
4
 
4
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
@@ -7,10 +8,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
8
  ## [Unreleased]
8
9
  Nothing yet
9
10
 
11
+ ## [1.0.0] - 2019-12-02
12
+ ### Added
13
+ - Avoid deep decoration ([#25](https://github.com/komposable/dekorator/pull/25))
14
+ - Make `decorate` accessible in ApplicationController ([#29](https://github.com/komposable/dekorator/pull/29))
15
+
16
+ ### Changed
17
+ - Moved to Komposable organization ([#13](https://github.com/komposable/dekorator/pull/13))
18
+ - Replace Travis CI by Github Actions and remove ruby 2.3 support ([#23](https://github.com/komposable/dekorator/pull/23))
19
+ - Update railtie to prevent triggering initialization autoloaded constant deprecation warning ([#30](https://github.com/komposable/dekorator/pull/30))
20
+ - Improve generators ([#31](https://github.com/komposable/dekorator/pull/31))
21
+
22
+ ### Fixes
23
+ - Fix DecoratedEnumerableProxy for Rails 6 ([5a656333](https://github.com/komposable/dekorator/commit/5a656333e9ca6321d0474f0e54de4332219b88d0))
24
+
10
25
  ## 1.0.0.pre.1 - 2019-01-30
11
26
  ### Added
12
- - Create Dekorator::Base the base of decorators (a2a36d66)
13
- - Create `dekorator:install` generator (a2a36d66)
14
- - Create `decorator` generator (a2a36d66)
27
+ - Create Dekorator::Base the base of decorators ([a2a36d66](https://github.com/komposable/dekorator/commit/a2a36d66c6de6cb0a00f783794cd29f899bc04b6))
28
+ - Create `dekorator:install` generator ([a2a36d66](https://github.com/komposable/dekorator/commit/a2a36d66c6de6cb0a00f783794cd29f899bc04b6))
29
+ - Create `decorator` generator ([a2a36d66](https://github.com/komposable/dekorator/commit/a2a36d66c6de6cb0a00f783794cd29f899bc04b6))
15
30
 
16
- [Unreleased]: https://github.com/pantographe/dekorator/compare/v1.0.0.pre.1...HEAD
31
+ [Unreleased]: https://github.com/komposable/dekorator/compare/v1.0.0...master
32
+ [1.0.0]: https://github.com/komposable/dekorator/compare/v1.0.0...1.0.0.pre.1
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
55
55
  ## Enforcement
56
56
 
57
57
  Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at nicolas@pantographe.studio. All
58
+ reported by contacting the project team at oss@pantographe.studio. All
59
59
  complaints will be reviewed and investigated and will result in a response that
60
60
  is deemed necessary and appropriate to the circumstances. The project team is
61
61
  obligated to maintain confidentiality with regard to the reporter of an incident.
data/README.md CHANGED
@@ -1,24 +1,24 @@
1
1
  # Dekorator
2
2
 
3
- [![Build Status](https://travis-ci.org/pantographe/dekorator.svg?branch=master)](https://travis-ci.org/pantographe/dekorator)
3
+ [![Tests](https://github.com/komposable/dekorator/workflows/Tests/badge.svg)](https://github.com/komposable/dekorator/actions)
4
4
  [![Gem Version](https://badge.fury.io/rb/dekorator.svg)](https://rubygems.org/gems/dekorator)
5
- [![Coverage Status](https://coveralls.io/repos/github/pantographe/dekorator/badge.svg)](https://coveralls.io/github/pantographe/dekorator)
6
- [![Inch CI](https://inch-ci.org/github/pantographe/dekorator.svg?branch=master)](https://inch-ci.org/github/pantographe/dekorator)
7
- [![Yardoc](https://img.shields.io/badge/doc-yardoc-blue.svg)](https://www.rubydoc.info/github/pantographe/dekorator/master)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/f7ab08512ead00da34c0/maintainability)](https://codeclimate.com/github/komposable/dekorator/maintainability)
6
+ [![Coverage Status](https://coveralls.io/repos/github/komposable/dekorator/badge.svg)](https://coveralls.io/github/komposable/dekorator)
7
+ [![Inch CI](https://inch-ci.org/github/komposable/dekorator.svg?branch=master)](https://inch-ci.org/github/komposable/dekorator)
8
+ [![Yardoc](https://img.shields.io/badge/doc-yardoc-blue.svg)](https://www.rubydoc.info/github/komposable/dekorator/master)
8
9
 
9
- **Dekorator** is an opinionated way of organizing model-view code in Ruby on Rails, based on _decorators_.
10
+ **Dekorator** is a lightweight library to implement _presenters_ and/or _decorators_ in your Rails app. It has less features than [`draper`](https://github.com/drapergem/draper) and aims at having a lower memory footprint.
10
11
 
11
- **Not production ready**
12
+ This gem has been inspired by our Rails development practices at [Pantographe](https://pantographe.studio), and the [Ruby memory, ActiveRecord and Draper](https://medium.com/appaloosa-store-engineering/ruby-memory-activerecord-and-draper-64f06abeeb34) talk by [Benoit Tigeot](https://github.com/benoittgt).
12
13
 
13
14
  ## Compatibility
14
15
 
15
- * Ruby 2.3+
16
+ * Ruby 2.4+
16
17
  * Rails 5.0+
17
18
 
18
-
19
19
  ## Installation
20
20
 
21
- Add this line to your application's Gemfile:
21
+ Add this line to your application `Gemfile`:
22
22
 
23
23
  ```ruby
24
24
  gem "dekorator"
@@ -28,7 +28,6 @@ And then execute:
28
28
 
29
29
  $ bundle
30
30
 
31
-
32
31
  ## Getting started
33
32
 
34
33
  Run the following command to set up your project:
@@ -37,7 +36,6 @@ Run the following command to set up your project:
37
36
 
38
37
  This command will create an `ApplicationDecorator` file.
39
38
 
40
-
41
39
  ## Usage
42
40
 
43
41
  Generate a new decorator with the `decorator` generator:
@@ -48,23 +46,55 @@ This command will generate the following file:
48
46
 
49
47
  ```ruby
50
48
  class UserDecorator < ApplicationDecorator
51
- # include ActionView::Helpers::TextHelper
52
- #
53
- # decorates_association :posts
54
- #
55
- # def full_name
56
- # [first_name, last_name].join(" ")
57
- # end
58
- #
59
- # def biography_summary
60
- # truncate(biography, length: 170)
61
- # end
49
+ include ActionView::Helpers::TextHelper
50
+
51
+ decorates_association :posts
52
+
53
+ def full_name
54
+ [first_name, last_name].join(" ")
55
+ end
56
+
57
+ def biography_summary
58
+ truncate(biography, length: 170)
59
+ end
62
60
  end
63
61
  ```
64
62
 
63
+ ### Decorate from a controller
64
+
65
+ ```ruby
66
+ class UsersController < ApplicationController
67
+ def index
68
+ @users = decorate User.all
69
+ end
70
+
71
+ def show
72
+ @user = decorate User.find(params[:id])
73
+ end
74
+ end
75
+ ```
76
+
77
+ ### Decorate from a view
78
+
79
+ ```erb
80
+ # app/views/users/index.html.erb
81
+
82
+ <ul>
83
+ <% decorate(@users).each do |user| %>
84
+ <li><%= user.full_name %></li>
85
+ <% end %>
86
+ </ul>
87
+ ```
88
+
89
+ ### Decorate outside a controller/view
90
+
91
+ ```ruby
92
+ UserDecorate.decorate(User.first) # => UserDecorator
93
+ ```
94
+
65
95
  ### Associations
66
96
 
67
- If you want to automatically decorates association for a decorated object,
97
+ If you want to automatically decorate an association for a decorated object,
68
98
  you have to use `#decorates_association` as following:
69
99
 
70
100
  ```ruby
@@ -82,29 +112,34 @@ end
82
112
  In this example, `UserDecorator#posts` will be decorated.
83
113
 
84
114
  ```ruby
85
- decorated_user = decorator(User.first)
115
+ decorated_user = decorate(User.first)
86
116
  decorated_user # => UserDecorator
87
117
  decorated_user.posts.first # => PostDecorator
88
118
  ```
89
119
 
90
- ### Specify decorator
120
+ ### Custom decorator
121
+
122
+ By default, Dekorator searches for the decorator class by adding `Decorator` at the end.
123
+ For `User`, Dekorator looks for the `UserDecorator` class, and for `User::Profile`
124
+ it looks for `User::ProfileDecorator`.
91
125
 
92
- If you want to create specific decorator or sub-decorator, you could simply
93
- specify the decorator class that should be use.
126
+ If you want to create a specific decorator or sub-decorator, you can simply
127
+ specify the decorator class that should be used.
94
128
 
95
129
  ```ruby
96
130
  class AdminDecorator < ApplicationDecorator
131
+ ...
97
132
  end
98
133
 
99
- decorated_user = decorator(User.first, with: AdminDecorator)
134
+ decorated_user = decorate(User.first, with: AdminDecorator)
100
135
  decorated_user # => AdminDecorator
101
136
  ```
102
137
 
103
- You also could specify the decorator for associations:
138
+ You can also specify the decorator for associations:
104
139
 
105
140
  ```ruby
106
141
  class UserDecorator < ApplicationDecorator
107
- decorates_association :posts, ArticleDecorator
142
+ decorates_association :posts, with: ArticleDecorator
108
143
 
109
144
  ...
110
145
  end
@@ -112,7 +147,7 @@ end
112
147
  class ArticleDecorator < ApplicationDecorator
113
148
  end
114
149
 
115
- decorated_user = decorator(User.first)
150
+ decorated_user = decorate(User.first)
116
151
  decorated_user # => UserDecorator
117
152
  decorated_user.posts.first # => ArticleDecorator
118
153
  ```
@@ -140,10 +175,10 @@ end
140
175
 
141
176
  ### Devise
142
177
 
143
- If you use [`device`][devise] gem you may have an issue if you decorate your
178
+ If you use the [`Devise`][devise] gem you may have an issue if you decorate your
144
179
  `User` model.
145
180
 
146
- You must define `#devise_scope` as following. Devise need to manage with
181
+ You must define `#devise_scope` as following. Devise needs to manage with the
147
182
  `User` model (https://github.com/plataformatec/devise/blob/369ba267efaa10d01c8dba59b09c3b94dd9e5551/lib/devise/mapping.rb#L35).
148
183
 
149
184
  ```ruby
@@ -156,24 +191,55 @@ class UserDecorator < ApplicationDecorator
156
191
  end
157
192
  ```
158
193
 
194
+ ## Testing
195
+
196
+ `rails generate decorator user` also generates a testing file based on your
197
+ configuration.
198
+
199
+ You can test a decorator the same way you do for helpers.
200
+
201
+ ### RSpec
202
+
203
+ ```ruby
204
+ describe UserDecorator, type: :decorator do
205
+ let(:object) { User.new(first_name: "John", last_name: "Doe") }
206
+ let(:decorated_user) { described_class.new(object) }
207
+
208
+ describe "#full_name" do
209
+ it { expect(decorated_user.full_name).to eq("John Doe") }
210
+ end
211
+ end
212
+ ```
159
213
 
160
214
  ## Development
161
215
 
162
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
216
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
217
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
218
+ prompt that will allow you to experiment.
163
219
 
164
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
220
+ To install this gem onto your local machine, run `bundle exec rake install`.
221
+ To release a new version, update the version number in `version.rb`, then
222
+ run `bundle exec rake release`, which will create a git tag for the version,
223
+ push git commits and tags, and push the `.gem` file to [rubygems.org].
165
224
 
166
225
  ## Contributing
167
226
 
168
- Bug reports and pull requests are welcome on GitHub at https://github.com/pantographe/dekorator. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
227
+ Bug reports and pull requests are welcome on GitHub at
228
+ https://github.com/komposable/dekorator. This project is intended to be a safe,
229
+ welcoming space for collaboration, and contributors are expected to adhere to
230
+ the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
169
231
 
170
232
  ## License
171
233
 
172
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
234
+ The gem is available as open source under the terms of the [MIT License].
173
235
 
174
236
  ## Code of Conduct
175
237
 
176
- Everyone interacting in the Dekorator project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/pantographe/dekorator/blob/master/CODE_OF_CONDUCT.md).
238
+ Everyone interacting in the Dekorator project codebases, issue trackers,
239
+ chat rooms and mailing lists is expected to follow the [code of conduct].
177
240
 
178
241
  [activeadmin]: https://activeadmin.info/11-decorators.html
179
242
  [devise]: https://github.com/plataformatec/devise/
243
+ [rubygems.org]: https://rubygems.org
244
+ [MIT License]: https://opensource.org/licenses/MIT
245
+ [code of conduct]: https://github.com/komposable/dekorator/blob/master/CODE_OF_CONDUCT.md
@@ -0,0 +1,7 @@
1
+ # Benchmarks
2
+
3
+ ## Run benchmarks
4
+
5
+ ```sh
6
+ $ ruby benchmark.rb
7
+ ```
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/inline"
4
+
5
+ gemfile(true) do
6
+ source "https://rubygems.org"
7
+
8
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
9
+
10
+ gem "rails", "6.0.1"
11
+ gem "sqlite3"
12
+ gem "benchmark-ips"
13
+ gem "benchmark-memory"
14
+
15
+ gem "dekorator", path: "../", require: false
16
+ gem "draper", require: false
17
+ end
18
+
19
+ require "active_record"
20
+ require "logger"
21
+
22
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
23
+ ActiveRecord::Base.logger = nil # Logger.new(STDOUT)
24
+
25
+ ActiveRecord::Schema.define do
26
+ create_table :posts, force: true do |t|
27
+ t.string :title
28
+ t.text :body
29
+ end
30
+
31
+ create_table :comments, force: true do |t|
32
+ t.integer :post_id
33
+ t.string :author
34
+ t.text :body
35
+ end
36
+ end
37
+
38
+ # Models
39
+ class Post < ActiveRecord::Base
40
+ has_many :comments
41
+
42
+ def summary
43
+ @summary ||= body&.truncate(170)
44
+ end
45
+ end
46
+
47
+ class Comment < ActiveRecord::Base
48
+ belongs_to :post
49
+ end
50
+
51
+ # Data
52
+ comments = 100.times.map { Comment.new(author: "John D.", body: "Great article") }
53
+ 10.times.each { Post.create!(title: "Our first article!", body: "", comments: comments) }
54
+
55
+ # Decorators
56
+ require "dekorator"
57
+
58
+ class PostDecorator < Dekorator::Base
59
+ decorates_association :comments
60
+
61
+ def summary
62
+ @summary ||= body&.truncate(170)
63
+ end
64
+ end
65
+
66
+ class CommentDecorator < Dekorator::Base
67
+ end
68
+
69
+ require "draper"
70
+
71
+ class CommentDraperDecorator < Draper::Decorator
72
+ end
73
+
74
+ class PostDraperDecorator < Draper::Decorator
75
+ decorates_association :comments, with: CommentDraperDecorator
76
+
77
+ def summary
78
+ @summary ||= object.body&.truncate(170)
79
+ end
80
+ end
81
+
82
+ require "delegate"
83
+
84
+ class PostDelegator < SimpleDelegator
85
+ def summary
86
+ @summary ||= body&.truncate(170)
87
+ end
88
+
89
+ def comments
90
+ @comments = __getobj__.comments.map { |comment| CommentDelegator.new(CommentDelegator) }
91
+ end
92
+ end
93
+
94
+ class CommentDelegator < SimpleDelegator
95
+ end
96
+
97
+ # Benchmark
98
+ SCENARIOS = {
99
+ "#summary" => :summary,
100
+ "#comments" => :comments,
101
+ }
102
+
103
+ SCENARIOS.each_pair do |name, method|
104
+ puts
105
+ puts " #{name} ".center(80, "=")
106
+ puts
107
+
108
+ model = Post.all
109
+
110
+ puts " ips ".center(80, "-")
111
+ puts
112
+
113
+ Benchmark.ips do |x|
114
+ x.report("In model") { model.first.public_send(method) }
115
+ x.report("Dekorator") { PostDecorator.decorate(model).first.public_send(method) }
116
+ x.report("Dekorator.new") { PostDecorator.decorate(model).first.public_send(method) }
117
+ x.report("Draper") { PostDraperDecorator.decorate_collection(model).first.public_send(method) }
118
+ x.report("SimpleDelegator") { PostDelegator.new(model.first).public_send(method) }
119
+
120
+ x.compare!
121
+ end
122
+
123
+ puts " memory ".center(80, "-")
124
+ puts
125
+
126
+ Benchmark.memory do |x|
127
+ x.report("In model") { model.first.public_send(method) }
128
+ x.report("Dekorator") { PostDecorator.decorate(model).first.public_send(method) }
129
+ x.report("Dekorator.new") { PostDecorator.decorate(model).first.public_send(method) }
130
+ x.report("Draper") { PostDraperDecorator.decorate_collection(model).first.public_send(method) }
131
+ x.report("SimpleDelegator") { PostDelegator.new(model.first).public_send(method) }
132
+
133
+ x.compare!
134
+ end
135
+ end