draper 4.0.1 → 4.0.4

Sign up to get free protection for your applications and to get access to all the features.
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