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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +71 -0
- data/.rspec +1 -2
- data/CHANGELOG.md +29 -0
- data/Gemfile +27 -4
- data/README.md +24 -2
- data/bin/bundle +114 -0
- data/bin/rake +29 -0
- data/draper.gemspec +4 -4
- data/lib/draper/automatic_delegation.rb +16 -6
- data/lib/draper/decoratable/collection_proxy.rb +15 -0
- data/lib/draper/decoratable.rb +2 -2
- data/lib/draper/helper_proxy.rb +2 -1
- data/lib/draper/lazy_helpers.rb +1 -1
- data/lib/draper/query_methods.rb +2 -2
- data/lib/draper/railtie.rb +8 -4
- data/lib/draper/version.rb +1 -1
- data/lib/draper/view_context/build_strategy.rb +1 -9
- data/lib/draper/view_helpers.rb +1 -1
- data/lib/draper.rb +2 -6
- data/spec/draper/collection_decorator_spec.rb +5 -4
- data/spec/draper/decoratable_spec.rb +1 -1
- data/spec/draper/decorator_spec.rb +4 -4
- data/spec/draper/factory_spec.rb +8 -8
- data/spec/draper/query_methods_spec.rb +10 -0
- data/spec/draper/view_context/build_strategy_spec.rb +1 -18
- data/spec/dummy/.rspec +0 -1
- data/spec/dummy/app/decorators/comment_decorator.rb +13 -0
- data/spec/dummy/app/decorators/mongoid_post_decorator.rb +1 -3
- data/spec/dummy/app/models/admin.rb +2 -4
- data/spec/dummy/app/models/comment.rb +3 -0
- data/spec/dummy/app/models/mongoid_post.rb +2 -4
- data/spec/dummy/app/models/post.rb +4 -0
- data/spec/dummy/app/models/user.rb +2 -4
- data/spec/dummy/config/application.rb +22 -51
- data/spec/dummy/config/environments/development.rb +66 -21
- data/spec/dummy/config/environments/production.rb +77 -32
- data/spec/dummy/config/environments/test.rb +56 -20
- data/spec/dummy/config/initializers/draper.rb +4 -2
- data/spec/dummy/config/storage.yml +7 -0
- data/spec/dummy/db/migrate/20240907041839_create_comments.rb +9 -0
- data/spec/dummy/db/schema.rb +16 -9
- data/spec/dummy/spec/decorators/active_model_serializers_spec.rb +1 -1
- data/spec/dummy/spec/decorators/post_decorator_spec.rb +1 -1
- data/spec/dummy/spec/jobs/publish_post_job_spec.rb +2 -0
- data/spec/dummy/spec/models/post_spec.rb +41 -5
- data/spec/dummy/spec/rails_helper.rb +69 -0
- data/spec/dummy/spec/spec_helper.rb +90 -5
- data/spec/generators/decorator/decorator_generator_spec.rb +1 -1
- data/spec/performance/benchmark.rb +1 -1
- data/spec/support/dummy_app.rb +1 -1
- metadata +40 -13
- data/.travis.yml +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78c5e444690de191d46a5be87ed46a3f9be6ec0ffd59fed6dcd1d63e5d527b85
|
4
|
+
data.tar.gz: f92be8ee42d8ce2e48c1743077f758eef779296593fcbcdef9a82fd5937a03ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
--
|
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
|
-
|
19
|
-
|
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
|
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
|
-
[](https://github.com/drapergem/draper/actions?query=workflow%3Aci+branch%3Amaster)
|
4
4
|
[](https://codeclimate.com/github/drapergem/draper)
|
5
5
|
[](https://codeclimate.com/github/drapergem/draper/test_coverage)
|
6
6
|
[](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
|
-
*
|
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
|
-
|
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 = "
|
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
|
-
#
|
22
|
-
|
23
|
-
|
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
|
-
|
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
|
data/lib/draper/decoratable.rb
CHANGED
@@ -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
|
data/lib/draper/helper_proxy.rb
CHANGED
@@ -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
|
data/lib/draper/lazy_helpers.rb
CHANGED
@@ -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
|
data/lib/draper/query_methods.rb
CHANGED
@@ -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
|
data/lib/draper/railtie.rb
CHANGED
@@ -33,10 +33,14 @@ module Draper
|
|
33
33
|
end
|
34
34
|
|
35
35
|
initializer 'draper.setup_orm' do
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
|
data/lib/draper/version.rb
CHANGED
@@ -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 ||=
|
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
|
data/lib/draper/view_helpers.rb
CHANGED
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
|
-
|
63
|
+
decorated = CollectionDecorator.new([]).tap(&:to_a)
|
64
|
+
undecorated = CollectionDecorator.new([])
|
64
65
|
|
65
|
-
expect(
|
66
|
-
|
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
|
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
|
|