draper 4.0.1 → 4.0.4

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +71 -0
  3. data/.rspec +1 -2
  4. data/CHANGELOG.md +29 -0
  5. data/Gemfile +27 -4
  6. data/README.md +24 -2
  7. data/bin/bundle +114 -0
  8. data/bin/rake +29 -0
  9. data/draper.gemspec +4 -4
  10. data/lib/draper/automatic_delegation.rb +16 -6
  11. data/lib/draper/decoratable/collection_proxy.rb +15 -0
  12. data/lib/draper/decoratable.rb +2 -2
  13. data/lib/draper/helper_proxy.rb +2 -1
  14. data/lib/draper/lazy_helpers.rb +1 -1
  15. data/lib/draper/query_methods.rb +2 -2
  16. data/lib/draper/railtie.rb +8 -4
  17. data/lib/draper/version.rb +1 -1
  18. data/lib/draper/view_context/build_strategy.rb +1 -9
  19. data/lib/draper/view_helpers.rb +1 -1
  20. data/lib/draper.rb +2 -6
  21. data/spec/draper/collection_decorator_spec.rb +5 -4
  22. data/spec/draper/decoratable_spec.rb +1 -1
  23. data/spec/draper/decorator_spec.rb +4 -4
  24. data/spec/draper/factory_spec.rb +8 -8
  25. data/spec/draper/query_methods_spec.rb +10 -0
  26. data/spec/draper/view_context/build_strategy_spec.rb +1 -18
  27. data/spec/dummy/.rspec +0 -1
  28. data/spec/dummy/app/decorators/comment_decorator.rb +13 -0
  29. data/spec/dummy/app/decorators/mongoid_post_decorator.rb +1 -3
  30. data/spec/dummy/app/models/admin.rb +2 -4
  31. data/spec/dummy/app/models/comment.rb +3 -0
  32. data/spec/dummy/app/models/mongoid_post.rb +2 -4
  33. data/spec/dummy/app/models/post.rb +4 -0
  34. data/spec/dummy/app/models/user.rb +2 -4
  35. data/spec/dummy/config/application.rb +22 -51
  36. data/spec/dummy/config/environments/development.rb +66 -21
  37. data/spec/dummy/config/environments/production.rb +77 -32
  38. data/spec/dummy/config/environments/test.rb +56 -20
  39. data/spec/dummy/config/initializers/draper.rb +4 -2
  40. data/spec/dummy/config/storage.yml +7 -0
  41. data/spec/dummy/db/migrate/20240907041839_create_comments.rb +9 -0
  42. data/spec/dummy/db/schema.rb +16 -9
  43. data/spec/dummy/spec/decorators/active_model_serializers_spec.rb +1 -1
  44. data/spec/dummy/spec/decorators/post_decorator_spec.rb +1 -1
  45. data/spec/dummy/spec/jobs/publish_post_job_spec.rb +2 -0
  46. data/spec/dummy/spec/models/post_spec.rb +41 -5
  47. data/spec/dummy/spec/rails_helper.rb +69 -0
  48. data/spec/dummy/spec/spec_helper.rb +90 -5
  49. data/spec/generators/decorator/decorator_generator_spec.rb +1 -1
  50. data/spec/performance/benchmark.rb +1 -1
  51. data/spec/support/dummy_app.rb +1 -1
  52. metadata +40 -13
  53. data/.travis.yml +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a90d57e1df50336b735a6f16cc119a558ee8472b70bd9748c59f25b70afc319a
4
- data.tar.gz: a4510f40a8afac7976e7afea4659d8e1c3eb981c005bc4046660b4d110874df7
3
+ metadata.gz: 78c5e444690de191d46a5be87ed46a3f9be6ec0ffd59fed6dcd1d63e5d527b85
4
+ data.tar.gz: f92be8ee42d8ce2e48c1743077f758eef779296593fcbcdef9a82fd5937a03ae
5
5
  SHA512:
6
- metadata.gz: bee71715525fdc2de5336c399b1dfe4a774d9fd68071bb01468c8f31712504cf6af8beecf1f4facf4ea25ef5bcad7a14b2e2f12bec12f7b6f1e55c04318c4f7a
7
- data.tar.gz: 8f013f4b36efa767ada401a979e5bf10e28f068997d24fd8035e4025254300709eb7c2e80c5f0498cc49c176b7561fbff48e2cc03f39b418f368c3266bf30359
6
+ metadata.gz: 2b2d10594f175019d7cbee9b7af7f811c8978349abae3cdce746abd94f24501d81b519c9da9ae350658265dd5aa0b33cdd9b3f18e26df922363227df8f57c4a4
7
+ data.tar.gz: 81565fd7b8034294a41c49b557f48619e6cee814056d2d4bff4c0e6f17c024877b250b421d4a185310f6b6fa3dee14b51d954b6ee3cef39100d3cfb4c9582af7
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: CI
3
+
4
+ on:
5
+ push:
6
+ branches:
7
+ - master
8
+ pull_request:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ rspec:
15
+ name: >-
16
+ rspec (${{ matrix.ruby }})
17
+
18
+ runs-on: ubuntu-latest
19
+
20
+ strategy:
21
+ fail-fast: false
22
+ matrix:
23
+ ruby:
24
+ - 3.3
25
+ - 3.2
26
+ - 3.1
27
+ rails:
28
+ - 7.2
29
+ include:
30
+ # Edge
31
+ - { ruby: 'head', rails: 'edge', allow-fail: true }
32
+ # Outdated
33
+ - { ruby: '3.0', rails: '7.1' }
34
+ - { ruby: '2.7', rails: '6' } # RSpec AR Expectations support Rails 7.1 since Ruby 3.0
35
+ - { ruby: '2.6', rails: '6' }
36
+ - { ruby: '2.5', rails: '6' }
37
+ - { ruby: '2.4', rails: '5' }
38
+
39
+ env:
40
+ RAILS_VERSION: "${{ matrix.rails }}"
41
+
42
+ services:
43
+ mongodb:
44
+ image: mongo
45
+ ports:
46
+ - 27017:27017
47
+
48
+ steps:
49
+ - uses: actions/checkout@v4
50
+
51
+ - name: Setup Ruby
52
+ uses: ruby/setup-ruby@v1
53
+ with:
54
+ ruby-version: ${{ matrix.ruby }}
55
+ rubygems: latest
56
+ bundler-cache: true
57
+
58
+ - name: RSpec & publish code coverage
59
+ uses: paambaati/codeclimate-action@v8
60
+ env:
61
+ CC_TEST_REPORTER_ID: b7ba588af2a540fa96c267b3655a2afe31ea29976dc25905a668dd28d5e88915
62
+ with:
63
+ coverageCommand: bin/rake
64
+ continue-on-error: ${{ matrix.allow-fail }}
65
+ id: test
66
+
67
+ - name: >-
68
+ Test ${{ steps.test.outcome }}
69
+ run: |
70
+ echo Ruby ${{ matrix.ruby }}
71
+ echo Rails ${{ matrix.rails }}
data/.rspec CHANGED
@@ -1,2 +1 @@
1
- --color
2
- --order rand
1
+ --format progress
data/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Draper Changelog
2
2
 
3
+ ## 4.0.4 - 2025-01-28
4
+
5
+ ### Fixes
6
+ * Fix a `LoadError` caused by a cherry-pick issue in version 4.0.3
7
+
8
+ ## 4.0.3 - 2025-01-27
9
+
10
+ Added support for latest Ruby (upto 3.4) and Rails (upto 8) versions.
11
+
12
+ ### Fixes
13
+ * Fix `CollectionDecorator#respond_to?` for non-ORM collections [#920](https://github.com/drapergem/draper/pull/920)
14
+ * Fix issues with using Draper outside of controller scope [#927](https://github.com/drapergem/draper/pull/927)
15
+ * Fix decoration of AR associations [#932](https://github.com/drapergem/draper/pull/932)
16
+
17
+ ### Other Changes
18
+ * Improve performance of delegation via `delegate_all` [#911](https://github.com/drapergem/draper/pull/911)
19
+ * Improve README [#878](https://github.com/drapergem/draper/pull/878), [#922](https://github.com/drapergem/draper/pull/922), [#934](https://github.com/drapergem/draper/pull/934)
20
+
21
+ ## 4.0.2 - 2021-05-27
22
+
23
+ ### Fixes
24
+ * Fix kwargs usage for Ruby 3 compatibility [#885](https://github.com/drapergem/draper/pull/885)
25
+ * Fix ruby warnings for "ambiguous first argument" [#881](https://github.com/drapergem/draper/pull/881)
26
+ * Fix rake warnings in CI [#897](https://github.com/drapergem/draper/pull/897)
27
+ * Fix decoration spec [#895](https://github.com/drapergem/draper/pull/895)
28
+
29
+ ### Other Changes
30
+ * Migration from Travis CI to GitHub Actions [#893](https://github.com/drapergem/draper/pull/893), [#896](https://github.com/drapergem/draper/pull/896), [#903](https://github.com/drapergem/draper/pull/903)
31
+
3
32
  ## 4.0.1 - 2020-03-25
4
33
 
5
34
  ### Fixes
data/Gemfile CHANGED
@@ -2,6 +2,8 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
+ gem 'puma'
6
+
5
7
  platforms :ruby do
6
8
  if RUBY_VERSION >= "2.5.0"
7
9
  gem 'sqlite3'
@@ -15,9 +17,30 @@ platforms :jruby do
15
17
  gem "activerecord-jdbcsqlite3-adapter"
16
18
  end
17
19
 
18
- if RUBY_VERSION >= "2.5.0"
19
- gem "rails", "~> 6.0"
20
+ case rails_version = ENV['RAILS_VERSION']
21
+ when nil
22
+ gem 'rails'
23
+ when 'edge'
24
+ gem 'rails', github: 'rails/rails'
20
25
  else
21
- gem "rails", "~> 5.0"
26
+ gem 'rails', "~> #{rails_version}.0"
27
+ end
28
+
29
+ gem 'mongoid' unless
30
+ rails_version == 'edge'
31
+ gem 'active_model_serializers'
32
+
33
+ case RUBY_VERSION
34
+ when '2.6'...'3.0'
35
+ gem "turbo-rails", "<= 2.0.7"
36
+ gem "redis", "~> 4.0"
37
+ when '3.0'...'4'
38
+ gem 'turbo-rails'
39
+ gem 'redis', '~> 4.0'
40
+ end
41
+
42
+ if RUBY_VERSION < "2.5.0"
43
+ gem 'rspec-activerecord-expectations', '~> 1.2.0'
44
+ gem 'simplecov', '0.17.1'
45
+ gem "loofah", "< 2.21.0" # Workaround for `uninitialized constant Nokogiri::HTML4`
22
46
  end
23
- gem "mongoid", github: "mongodb/mongoid"
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Draper: View Models for Rails
2
2
 
3
- [![TravisCI Build Status](https://travis-ci.org/drapergem/draper.svg?branch=master)](http://travis-ci.org/drapergem/draper)
3
+ [![Actions Status](https://github.com/drapergem/draper/workflows/CI/badge.svg?branch=master)](https://github.com/drapergem/draper/actions?query=workflow%3Aci+branch%3Amaster)
4
4
  [![Code Climate](https://codeclimate.com/github/drapergem/draper.svg)](https://codeclimate.com/github/drapergem/draper)
5
5
  [![Test Coverage](https://api.codeclimate.com/v1/badges/0d40c43951d516bf6985/test_coverage)](https://codeclimate.com/github/drapergem/draper/test_coverage)
6
6
  [![Inline docs](http://inch-ci.org/github/drapergem/draper.svg?branch=master)](http://inch-ci.org/github/drapergem/draper)
@@ -131,6 +131,17 @@ class ArticleDecorator < Draper::Decorator
131
131
  end
132
132
  ```
133
133
 
134
+
135
+ To decorate a model in a namespace e.g. `Admin::Catalogue` place the decorator under the
136
+ directory `app/decorators/admin` in the same way you would with views and models.
137
+
138
+ ```ruby
139
+ # app/decorators/admin/catalogue_decorator.rb
140
+ class Admin::CatalogueDecorator < Draper::Decorator
141
+ # ...
142
+ end
143
+ ```
144
+
134
145
  ### Generators
135
146
 
136
147
  To create an `ApplicationDecorator` that all generated decorators inherit from, run...
@@ -155,6 +166,15 @@ rails generate decorator Article
155
166
 
156
167
  ...to create the `ArticleDecorator`.
157
168
 
169
+ If you don't want Rails to generate decorator files when generating a new controller,
170
+ you can add the following configuration to your `config/application.rb` file:
171
+
172
+ ```ruby
173
+ config.generators do |g|
174
+ g.decorator false
175
+ end
176
+ ```
177
+
158
178
  ### Accessing Helpers
159
179
 
160
180
  Normal Rails helpers are still useful for lots of tasks. Both Rails' provided
@@ -664,7 +684,8 @@ great community of open source
664
684
 
665
685
  ### Current maintainers
666
686
 
667
- * Cliff Braton (cliff.braton@gmail.com)
687
+ * Alexander Senko (Alexander.Senko@gmail.com)
688
+ * Yuji Yaginuma (yuuji.yaginuma@gmail.com)
668
689
 
669
690
  ### Historical maintainers
670
691
 
@@ -673,3 +694,4 @@ great community of open source
673
694
  * Vasiliy Ermolovich
674
695
  * Andrew Haines
675
696
  * Sean Linsley
697
+ * Cliff Braton (cliff.braton@gmail.com)
data/bin/bundle ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'bundle' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "rubygems"
12
+
13
+ m = Module.new do
14
+ module_function
15
+
16
+ def invoked_as_script?
17
+ File.expand_path($0) == File.expand_path(__FILE__)
18
+ end
19
+
20
+ def env_var_version
21
+ ENV["BUNDLER_VERSION"]
22
+ end
23
+
24
+ def cli_arg_version
25
+ return unless invoked_as_script? # don't want to hijack other binstubs
26
+ return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27
+ bundler_version = nil
28
+ update_index = nil
29
+ ARGV.each_with_index do |a, i|
30
+ if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31
+ bundler_version = a
32
+ end
33
+ next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34
+ bundler_version = $1
35
+ update_index = i
36
+ end
37
+ bundler_version
38
+ end
39
+
40
+ def gemfile
41
+ gemfile = ENV["BUNDLE_GEMFILE"]
42
+ return gemfile if gemfile && !gemfile.empty?
43
+
44
+ File.expand_path("../../Gemfile", __FILE__)
45
+ end
46
+
47
+ def lockfile
48
+ lockfile =
49
+ case File.basename(gemfile)
50
+ when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
51
+ else "#{gemfile}.lock"
52
+ end
53
+ File.expand_path(lockfile)
54
+ end
55
+
56
+ def lockfile_version
57
+ return unless File.file?(lockfile)
58
+ lockfile_contents = File.read(lockfile)
59
+ return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60
+ Regexp.last_match(1)
61
+ end
62
+
63
+ def bundler_version
64
+ @bundler_version ||=
65
+ env_var_version || cli_arg_version ||
66
+ lockfile_version
67
+ end
68
+
69
+ def bundler_requirement
70
+ return "#{Gem::Requirement.default}.a" unless bundler_version
71
+
72
+ bundler_gem_version = Gem::Version.new(bundler_version)
73
+
74
+ requirement = bundler_gem_version.approximate_recommendation
75
+
76
+ return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
77
+
78
+ requirement += ".a" if bundler_gem_version.prerelease?
79
+
80
+ requirement
81
+ end
82
+
83
+ def load_bundler!
84
+ ENV["BUNDLE_GEMFILE"] ||= gemfile
85
+
86
+ activate_bundler
87
+ end
88
+
89
+ def activate_bundler
90
+ gem_error = activation_error_handling do
91
+ gem "bundler", bundler_requirement
92
+ end
93
+ return if gem_error.nil?
94
+ require_error = activation_error_handling do
95
+ require "bundler/version"
96
+ end
97
+ return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
98
+ warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
99
+ exit 42
100
+ end
101
+
102
+ def activation_error_handling
103
+ yield
104
+ nil
105
+ rescue StandardError, LoadError => e
106
+ e
107
+ end
108
+ end
109
+
110
+ m.load_bundler!
111
+
112
+ if m.invoked_as_script?
113
+ load Gem.bin_path("bundler", "bundle")
114
+ end
data/bin/rake ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rake", "rake")
data/draper.gemspec CHANGED
@@ -1,18 +1,17 @@
1
- require File.join(__dir__, "lib", "draper", "version")
1
+ require_relative 'lib/draper/version'
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "draper"
5
5
  s.version = Draper::VERSION
6
6
  s.authors = ["Jeff Casimir", "Steve Klabnik"]
7
7
  s.email = ["jeff@casimircreative.com", "steve@steveklabnik.com"]
8
- s.homepage = "http://github.com/drapergem/draper"
8
+ s.homepage = "https://github.com/drapergem/draper"
9
9
  s.summary = "View Models for Rails"
10
10
  s.description = "Draper adds an object-oriented layer of presentation logic to your Rails apps."
11
11
  s.license = "MIT"
12
12
 
13
13
  s.files = `git ls-files`.split("\n")
14
14
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
15
  s.require_paths = ["lib"]
17
16
 
18
17
  s.required_ruby_version = '>= 2.2.2'
@@ -22,13 +21,14 @@ Gem::Specification.new do |s|
22
21
  s.add_dependency 'request_store', '>= 1.0'
23
22
  s.add_dependency 'activemodel', '>= 5.0'
24
23
  s.add_dependency 'activemodel-serializers-xml', '>= 1.0'
24
+ s.add_dependency 'ruby2_keywords'
25
25
 
26
26
  s.add_development_dependency 'ammeter'
27
27
  s.add_development_dependency 'rake'
28
28
  s.add_development_dependency 'rspec-rails'
29
+ s.add_development_dependency 'rspec-activerecord-expectations'
29
30
  s.add_development_dependency 'minitest-rails'
30
31
  s.add_development_dependency 'capybara'
31
- s.add_development_dependency 'active_model_serializers', '>= 0.10'
32
32
  s.add_development_dependency 'rubocop'
33
33
  s.add_development_dependency 'simplecov'
34
34
  end
@@ -6,7 +6,7 @@ module Draper
6
6
  # method calls to `object` as well. Calling `super` will first try to call the method on
7
7
  # the parent decorator class. If no method exists on the parent class, it will then try
8
8
  # to call the method on the `object`.
9
- def method_missing(method, *args, &block)
9
+ ruby2_keywords def method_missing(method, *args, &block)
10
10
  return super unless delegatable?(method)
11
11
 
12
12
  object.send(method, *args, &block)
@@ -18,16 +18,26 @@ module Draper
18
18
  super || delegatable?(method)
19
19
  end
20
20
 
21
- # @private
22
- def delegatable?(method)
23
- return if private_methods(false).include?(method)
21
+ # The inherit argument for `private_method_defined?` is supported since Ruby 2.6.
22
+ if RUBY_VERSION >= "2.6"
23
+ # @private
24
+ def delegatable?(method)
25
+ return if self.class.private_method_defined?(method, false)
24
26
 
25
- object.respond_to?(method)
27
+ object.respond_to?(method)
28
+ end
29
+ else
30
+ # @private
31
+ def delegatable?(method)
32
+ return if private_methods(false).include?(method)
33
+
34
+ object.respond_to?(method)
35
+ end
26
36
  end
27
37
 
28
38
  module ClassMethods
29
39
  # Proxies missing class methods to the source class.
30
- def method_missing(method, *args, &block)
40
+ ruby2_keywords def method_missing(method, *args, &block)
31
41
  return super unless delegatable?(method)
32
42
 
33
43
  object_class.send(method, *args, &block)
@@ -0,0 +1,15 @@
1
+ module Draper
2
+ module Decoratable
3
+ module CollectionProxy
4
+ # Decorates a collection of objects. Used at the end of a scope chain.
5
+ #
6
+ # @example
7
+ # company.products.popular.decorate
8
+ # @param [Hash] options
9
+ # see {Decorator.decorate_collection}.
10
+ def decorate(options = {})
11
+ decorator_class.decorate_collection(load_target, options.reverse_merge(with: nil))
12
+ end
13
+ end
14
+ end
15
+ end
@@ -11,6 +11,8 @@ module Draper
11
11
  extend ActiveSupport::Concern
12
12
  include Draper::Decoratable::Equality
13
13
 
14
+ autoload :CollectionProxy, 'draper/decoratable/collection_proxy'
15
+
14
16
  # Decorates the object using the inferred {#decorator_class}.
15
17
  # @param [Hash] options
16
18
  # see {Decorator#initialize}
@@ -87,8 +89,6 @@ module Draper
87
89
  def ===(other)
88
90
  super || (other.is_a?(Draper::Decorator) && super(other.object))
89
91
  end
90
-
91
92
  end
92
-
93
93
  end
94
94
  end
@@ -8,7 +8,7 @@ module Draper
8
8
  end
9
9
 
10
10
  # Sends helper methods to the view context.
11
- def method_missing(method, *args, &block)
11
+ ruby2_keywords def method_missing(method, *args, &block)
12
12
  self.class.define_proxy method
13
13
  send(method, *args, &block)
14
14
  end
@@ -31,6 +31,7 @@ module Draper
31
31
  define_method name do |*args, &block|
32
32
  view_context.send(name, *args, &block)
33
33
  end
34
+ ruby2_keywords name
34
35
  end
35
36
  end
36
37
  end
@@ -4,7 +4,7 @@ module Draper
4
4
  # bazillion methods.
5
5
  module LazyHelpers
6
6
  # Sends missing methods to the {HelperProxy}.
7
- def method_missing(method, *args, &block)
7
+ ruby2_keywords def method_missing(method, *args, &block)
8
8
  helpers.send(method, *args, &block)
9
9
  rescue NoMethodError
10
10
  super
@@ -3,14 +3,14 @@ require_relative 'query_methods/load_strategy'
3
3
  module Draper
4
4
  module QueryMethods
5
5
  # Proxies missing query methods to the source class if the strategy allows.
6
- def method_missing(method, *args, &block)
6
+ ruby2_keywords def method_missing(method, *args, &block)
7
7
  return super unless strategy.allowed? method
8
8
 
9
9
  object.send(method, *args, &block).decorate(with: decorator_class, context: context)
10
10
  end
11
11
 
12
12
  def respond_to_missing?(method, include_private = false)
13
- strategy.allowed?(method) || super
13
+ object.respond_to?(method) && strategy.allowed?(method) || super
14
14
  end
15
15
 
16
16
  private
@@ -33,10 +33,14 @@ module Draper
33
33
  end
34
34
 
35
35
  initializer 'draper.setup_orm' do
36
- [:active_record, :mongoid].each do |orm|
37
- ActiveSupport.on_load orm do
38
- Draper.setup_orm self
39
- end
36
+ ActiveSupport.on_load :active_record do
37
+ include Draper::Decoratable
38
+
39
+ ActiveRecord::Associations::CollectionProxy.include Draper::Decoratable::CollectionProxy
40
+ end
41
+
42
+ ActiveSupport.on_load :mongoid do
43
+ include Draper::Decoratable
40
44
  end
41
45
  end
42
46
 
@@ -1,3 +1,3 @@
1
1
  module Draper
2
- VERSION = '4.0.1'
2
+ VERSION = '4.0.4'
3
3
  end
@@ -38,17 +38,9 @@ module Draper
38
38
  def controller
39
39
  Draper::ViewContext.controller ||= Draper.default_controller.new
40
40
  Draper::ViewContext.controller.tap do |controller|
41
- controller.request ||= new_test_request controller if defined?(ActionController::TestRequest)
41
+ controller.request ||= ActionDispatch::TestRequest.create
42
42
  end
43
43
  end
44
-
45
- def new_test_request(controller)
46
- is_above_rails_5_1 ? ActionController::TestRequest.create(controller) : ActionController::TestRequest.create
47
- end
48
-
49
- def is_above_rails_5_1
50
- ActionController::TestRequest.method(:create).parameters.first == [:req, :controller_class]
51
- end
52
44
  end
53
45
  end
54
46
  end
@@ -28,7 +28,7 @@ module Draper
28
28
 
29
29
  # Alias for `helpers.localize`, since localize is something that's used
30
30
  # quite often. Further aliased to `l` for convenience.
31
- def localize(*args)
31
+ ruby2_keywords def localize(*args)
32
32
  helpers.localize(*args)
33
33
  end
34
34
 
data/lib/draper.rb CHANGED
@@ -8,6 +8,8 @@ require 'active_support/core_ext/hash/keys'
8
8
  require 'active_support/core_ext/hash/reverse_merge'
9
9
  require 'active_support/core_ext/name_error'
10
10
 
11
+ require 'ruby2_keywords'
12
+
11
13
  require 'draper/version'
12
14
  require 'draper/configuration'
13
15
  require 'draper/view_helpers'
@@ -49,12 +51,6 @@ module Draper
49
51
  end
50
52
  end
51
53
 
52
- def self.setup_orm(base)
53
- base.class_eval do
54
- include Draper::Decoratable
55
- end
56
- end
57
-
58
54
  class UninferrableDecoratorError < NameError
59
55
  def initialize(klass)
60
56
  super("Could not infer a decorator for #{klass}.")
@@ -60,10 +60,11 @@ module Draper
60
60
 
61
61
  context "when the collection has not yet been decorated" do
62
62
  it "does not trigger decoration" do
63
- decorator = CollectionDecorator.new([])
63
+ decorated = CollectionDecorator.new([]).tap(&:to_a)
64
+ undecorated = CollectionDecorator.new([])
64
65
 
65
- expect(decorator).not_to receive(:decorated_collection)
66
- decorator.context = {other: "context"}
66
+ expect(decorated.instance_variable_defined?(:@decorated_collection)).to be_truthy
67
+ expect(undecorated.instance_variable_defined?(:@decorated_collection)).to be_falsy
67
68
  end
68
69
 
69
70
  it "sets context after decoration is triggered" do
@@ -217,7 +218,7 @@ module Draper
217
218
  it "uses the custom class name" do
218
219
  decorator = ProductsDecorator.new([])
219
220
 
220
- expect(decorator.to_s).to match /ProductsDecorator/
221
+ expect(decorator.to_s).to match(/ProductsDecorator/)
221
222
  end
222
223
  end
223
224
  end
@@ -147,7 +147,7 @@ module Draper
147
147
  scoped = [Product.new]
148
148
  allow(Product).to receive(:all).and_return(scoped)
149
149
 
150
- expect(Product.decorator_class).to receive(:decorate_collection).with(scoped, with: nil).and_return(:decorated_collection)
150
+ expect(Product.decorator_class).to receive(:decorate_collection).with(scoped, {with: nil}).and_return(:decorated_collection)
151
151
  expect(Product.decorate).to be :decorated_collection
152
152
  end
153
153