draper 2.1.0 → 3.0.0
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/.codeclimate.yml +16 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +24 -0
- data/.gitignore +3 -1
- data/.rubocop.yml +11 -0
- data/.travis.yml +3 -7
- data/CHANGELOG.md +26 -0
- data/Gemfile +4 -5
- data/Guardfile +5 -5
- data/README.md +61 -11
- data/Rakefile +1 -1
- data/draper.gemspec +12 -10
- data/lib/draper.rb +8 -3
- data/lib/draper/automatic_delegation.rb +5 -3
- data/lib/draper/collection_decorator.rb +1 -11
- data/lib/draper/compatibility/api_only.rb +23 -0
- data/lib/draper/configuration.rb +15 -0
- data/lib/draper/decoratable.rb +3 -4
- data/lib/draper/decorator.rb +4 -24
- data/lib/draper/finders.rb +0 -0
- data/lib/draper/helper_proxy.rb +1 -8
- data/lib/draper/railtie.rb +12 -21
- data/lib/draper/tasks/test.rake +2 -15
- data/lib/draper/test/devise_helper.rb +1 -8
- data/lib/draper/test/minitest_integration.rb +0 -0
- data/lib/draper/test/rspec_integration.rb +1 -5
- data/lib/draper/test_case.rb +4 -8
- data/lib/draper/undecorate.rb +8 -0
- data/lib/draper/version.rb +1 -1
- data/lib/draper/view_context.rb +3 -19
- data/lib/draper/view_context/build_strategy.rb +11 -2
- data/lib/generators/controller_override.rb +2 -2
- data/lib/generators/draper/install_generator.rb +14 -0
- data/lib/generators/draper/templates/application_decorator.rb +8 -0
- data/lib/generators/mini_test/decorator_generator.rb +1 -1
- data/lib/generators/rails/decorator_generator.rb +1 -8
- data/lib/generators/rspec/templates/decorator_spec.rb +2 -2
- data/spec/draper/collection_decorator_spec.rb +11 -26
- data/spec/draper/configuration_spec.rb +25 -0
- data/spec/draper/decoratable_spec.rb +29 -16
- data/spec/draper/decorated_association_spec.rb +9 -9
- data/spec/draper/decorates_assigned_spec.rb +6 -6
- data/spec/draper/decorator_spec.rb +112 -89
- data/spec/draper/draper_spec.rb +24 -0
- data/spec/draper/factory_spec.rb +26 -26
- data/spec/draper/finders_spec.rb +21 -21
- data/spec/draper/helper_proxy_spec.rb +3 -3
- data/spec/draper/lazy_helpers_spec.rb +2 -2
- data/spec/draper/undecorate_chain_spec.rb +20 -0
- data/spec/draper/view_context/build_strategy_spec.rb +26 -10
- data/spec/draper/view_context_spec.rb +49 -21
- data/spec/dummy/app/controllers/base_controller.rb +4 -0
- data/spec/dummy/app/controllers/posts_controller.rb +2 -2
- data/spec/dummy/app/decorators/post_decorator.rb +0 -0
- data/spec/dummy/app/views/posts/_post.html.erb +8 -6
- data/spec/dummy/config/boot.rb +1 -1
- data/spec/dummy/config/initializers/draper.rb +3 -0
- data/spec/dummy/config/mongoid.yml +104 -41
- data/spec/dummy/db/schema.rb +4 -4
- data/spec/dummy/fast_spec/post_decorator_spec.rb +1 -1
- data/spec/dummy/lib/tasks/test.rake +1 -1
- data/spec/dummy/spec/decorators/active_model_serializers_spec.rb +4 -8
- data/spec/dummy/spec/decorators/devise_spec.rb +0 -9
- data/spec/dummy/spec/decorators/post_decorator_spec.rb +2 -4
- data/spec/dummy/spec/mailers/post_mailer_spec.rb +0 -8
- data/spec/dummy/spec/shared_examples/decoratable.rb +0 -2
- data/spec/dummy/test/decorators/minitest/devise_test.rb +0 -9
- data/spec/dummy/test/decorators/minitest/view_context_test.rb +3 -3
- data/spec/dummy/test/decorators/test_unit/devise_test.rb +0 -9
- data/spec/dummy/test/decorators/test_unit/view_context_test.rb +1 -1
- data/spec/generators/controller/controller_generator_spec.rb +3 -3
- data/spec/generators/decorator/decorator_generator_spec.rb +14 -12
- data/spec/generators/install/install_generator_spec.rb +19 -0
- data/spec/integration/integration_spec.rb +11 -8
- data/spec/performance/benchmark.rb +1 -1
- data/spec/spec_helper.rb +4 -4
- data/spec/support/matchers/have_text.rb +2 -2
- data/spec/support/shared_examples/view_helpers.rb +8 -8
- metadata +71 -29
- data/gemfiles/4.0.gemfile +0 -3
- data/gemfiles/4.1.gemfile +0 -3
- data/gemfiles/4.2.gemfile +0 -3
- data/spec/dummy/app/controllers/application_controller.rb +0 -4
@@ -0,0 +1,23 @@
|
|
1
|
+
module Draper
|
2
|
+
module Compatibility
|
3
|
+
# Draper expects your `ApplicationController` to include `ActionView::Rendering`. The
|
4
|
+
# `ApplicationController` generated by Rails 5 API-only applications (created with
|
5
|
+
# `rails new --api`) don't by default. However, including `ActionView::Rendering` in
|
6
|
+
# `ApplicatonController` breaks `render :json` due to `render_to_body` being overridden.
|
7
|
+
#
|
8
|
+
# This compatibility patch fixes the issue by restoring the original `render_to_body`
|
9
|
+
# method after including `ActionView::Rendering`. Ultimately, including `ActionView::Rendering`
|
10
|
+
# in an ActionController::API may not be supported functionality by Rails (see Rails issue
|
11
|
+
# for more detail: https://github.com/rails/rails/issues/27211). This hack is meant to be a
|
12
|
+
# temporary solution until we can find a way to not rely on the controller layer.
|
13
|
+
module ApiOnly
|
14
|
+
extend ActiveSupport::Concern
|
15
|
+
|
16
|
+
included do
|
17
|
+
alias :previous_render_to_body :render_to_body
|
18
|
+
include ActionView::Rendering
|
19
|
+
alias :render_to_body :previous_render_to_body
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Draper
|
2
|
+
module Configuration
|
3
|
+
def configure
|
4
|
+
yield self
|
5
|
+
end
|
6
|
+
|
7
|
+
def default_controller
|
8
|
+
@@default_controller ||= ApplicationController
|
9
|
+
end
|
10
|
+
|
11
|
+
def default_controller=(controller)
|
12
|
+
@@default_controller = controller
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/draper/decoratable.rb
CHANGED
@@ -56,8 +56,7 @@ module Draper
|
|
56
56
|
# @param [Hash] options
|
57
57
|
# see {Decorator.decorate_collection}.
|
58
58
|
def decorate(options = {})
|
59
|
-
|
60
|
-
decorator_class.decorate_collection(collection, options.reverse_merge(with: nil))
|
59
|
+
decorator_class.decorate_collection(all, options.reverse_merge(with: nil))
|
61
60
|
end
|
62
61
|
|
63
62
|
def decorator_class?
|
@@ -75,10 +74,10 @@ module Draper
|
|
75
74
|
decorator_name = "#{prefix}Decorator"
|
76
75
|
decorator_name.constantize
|
77
76
|
rescue NameError => error
|
77
|
+
raise unless error.missing_name?(decorator_name)
|
78
78
|
if superclass.respond_to?(:decorator_class)
|
79
79
|
superclass.decorator_class
|
80
80
|
else
|
81
|
-
raise unless error.missing_name?(decorator_name)
|
82
81
|
raise Draper::UninferrableDecoratorError.new(self)
|
83
82
|
end
|
84
83
|
end
|
@@ -87,7 +86,7 @@ module Draper
|
|
87
86
|
#
|
88
87
|
# @return [Boolean]
|
89
88
|
def ===(other)
|
90
|
-
super || (other.
|
89
|
+
super || (other.is_a?(Draper::Decorator) && super(other.object))
|
91
90
|
end
|
92
91
|
|
93
92
|
end
|
data/lib/draper/decorator.rb
CHANGED
@@ -10,8 +10,6 @@ module Draper
|
|
10
10
|
# @return the object being decorated.
|
11
11
|
attr_reader :object
|
12
12
|
alias_method :model, :object
|
13
|
-
alias_method :source, :object # TODO: deprecate this
|
14
|
-
alias_method :to_source, :object # TODO: deprecate this
|
15
13
|
|
16
14
|
# @return [Hash] extra data to be used in user-defined methods.
|
17
15
|
attr_accessor :context
|
@@ -72,15 +70,10 @@ module Draper
|
|
72
70
|
# Checks whether this decorator class has a corresponding {object_class}.
|
73
71
|
def self.object_class?
|
74
72
|
object_class
|
75
|
-
rescue Draper::
|
73
|
+
rescue Draper::UninferrableObjectError
|
76
74
|
false
|
77
75
|
end
|
78
76
|
|
79
|
-
class << self # TODO deprecate this
|
80
|
-
alias_method :source_class, :object_class
|
81
|
-
alias_method :source_class?, :object_class?
|
82
|
-
end
|
83
|
-
|
84
77
|
# Automatically decorates ActiveRecord finder methods, so that you can use
|
85
78
|
# `ProductDecorator.find(id)` instead of
|
86
79
|
# `ProductDecorator.decorate(Product.find(id))`.
|
@@ -182,7 +175,7 @@ module Draper
|
|
182
175
|
|
183
176
|
# Returns a unique hash for a decorated object based on
|
184
177
|
# the decorator class and the object being decorated.
|
185
|
-
#
|
178
|
+
#
|
186
179
|
# @return [Fixnum]
|
187
180
|
def hash
|
188
181
|
self.class.hash ^ object.hash
|
@@ -203,18 +196,6 @@ module Draper
|
|
203
196
|
super || object.instance_of?(klass)
|
204
197
|
end
|
205
198
|
|
206
|
-
if RUBY_VERSION < "2.0"
|
207
|
-
# nasty hack to stop 1.9.x using the delegated `to_s` in `inspect`
|
208
|
-
alias_method :_to_s, :to_s
|
209
|
-
|
210
|
-
def inspect
|
211
|
-
ivars = instance_variables.map do |name|
|
212
|
-
"#{name}=#{instance_variable_get(name).inspect}"
|
213
|
-
end
|
214
|
-
_to_s.insert(-2, " #{ivars.join(", ")}")
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
199
|
delegate :to_s
|
219
200
|
|
220
201
|
# In case object is nil
|
@@ -242,8 +223,7 @@ module Draper
|
|
242
223
|
def self.collection_decorator_class
|
243
224
|
name = collection_decorator_name
|
244
225
|
name.constantize
|
245
|
-
rescue NameError
|
246
|
-
raise if name && !error.missing_name?(name)
|
226
|
+
rescue NameError
|
247
227
|
Draper::CollectionDecorator
|
248
228
|
end
|
249
229
|
|
@@ -268,7 +248,7 @@ module Draper
|
|
268
248
|
name.constantize
|
269
249
|
rescue NameError => error
|
270
250
|
raise if name && !error.missing_name?(name)
|
271
|
-
raise Draper::
|
251
|
+
raise Draper::UninferrableObjectError.new(self)
|
272
252
|
end
|
273
253
|
|
274
254
|
def self.collection_decorator_name
|
data/lib/draper/finders.rb
CHANGED
File without changes
|
data/lib/draper/helper_proxy.rb
CHANGED
@@ -4,9 +4,7 @@ module Draper
|
|
4
4
|
class HelperProxy
|
5
5
|
|
6
6
|
# @overload initialize(view_context)
|
7
|
-
def initialize(view_context
|
8
|
-
view_context ||= current_view_context # backwards compatibility
|
9
|
-
|
7
|
+
def initialize(view_context)
|
10
8
|
@view_context = view_context
|
11
9
|
end
|
12
10
|
|
@@ -35,10 +33,5 @@ module Draper
|
|
35
33
|
view_context.send(name, *args, &block)
|
36
34
|
end
|
37
35
|
end
|
38
|
-
|
39
|
-
def current_view_context
|
40
|
-
ActiveSupport::Deprecation.warn("wrong number of arguments (0 for 1) passed to Draper::HelperProxy.new", caller[1..-1])
|
41
|
-
Draper::ViewContext.current.view_context
|
42
|
-
end
|
43
36
|
end
|
44
37
|
end
|
data/lib/draper/railtie.rb
CHANGED
@@ -3,8 +3,6 @@ require 'rails/railtie'
|
|
3
3
|
module ActiveModel
|
4
4
|
class Railtie < Rails::Railtie
|
5
5
|
generators do |app|
|
6
|
-
app ||= Rails.application # Rails 3.0.x does not yield `app`
|
7
|
-
|
8
6
|
Rails::Generators.configure! app.config.generators
|
9
7
|
require_relative '../generators/controller_override'
|
10
8
|
end
|
@@ -13,7 +11,6 @@ end
|
|
13
11
|
|
14
12
|
module Draper
|
15
13
|
class Railtie < Rails::Railtie
|
16
|
-
|
17
14
|
config.after_initialize do |app|
|
18
15
|
app.config.paths.add 'app/decorators', eager_load: true
|
19
16
|
|
@@ -23,19 +20,19 @@ module Draper
|
|
23
20
|
end
|
24
21
|
end
|
25
22
|
|
26
|
-
initializer
|
23
|
+
initializer 'draper.setup_action_controller' do
|
27
24
|
ActiveSupport.on_load :action_controller do
|
28
25
|
Draper.setup_action_controller self
|
29
26
|
end
|
30
27
|
end
|
31
28
|
|
32
|
-
initializer
|
29
|
+
initializer 'draper.setup_action_mailer' do
|
33
30
|
ActiveSupport.on_load :action_mailer do
|
34
31
|
Draper.setup_action_mailer self
|
35
32
|
end
|
36
33
|
end
|
37
34
|
|
38
|
-
initializer
|
35
|
+
initializer 'draper.setup_orm' do
|
39
36
|
[:active_record, :mongoid].each do |orm|
|
40
37
|
ActiveSupport.on_load orm do
|
41
38
|
Draper.setup_orm self
|
@@ -43,28 +40,22 @@ module Draper
|
|
43
40
|
end
|
44
41
|
end
|
45
42
|
|
46
|
-
initializer
|
47
|
-
ActiveSupport.on_load :active_model_serializers do
|
48
|
-
if defined?(ActiveModel::ArraySerializerSupport)
|
49
|
-
Draper::CollectionDecorator.send :include, ActiveModel::ArraySerializerSupport
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
initializer "draper.minitest-rails_integration" do |app|
|
43
|
+
initializer 'draper.minitest-rails_integration' do
|
55
44
|
ActiveSupport.on_load :minitest do
|
56
|
-
require
|
45
|
+
require 'draper/test/minitest_integration'
|
57
46
|
end
|
58
47
|
end
|
59
48
|
|
60
|
-
|
49
|
+
def initialize_view_context
|
61
50
|
require 'action_controller/test_case'
|
62
|
-
|
51
|
+
Draper.default_controller.new.view_context
|
63
52
|
Draper::ViewContext.build
|
64
53
|
end
|
65
54
|
|
66
|
-
|
67
|
-
|
68
|
-
|
55
|
+
console { initialize_view_context }
|
56
|
+
|
57
|
+
runner { initialize_view_context }
|
58
|
+
|
59
|
+
rake_tasks { Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each { |f| load f } }
|
69
60
|
end
|
70
61
|
end
|
data/lib/draper/tasks/test.rake
CHANGED
@@ -1,22 +1,9 @@
|
|
1
1
|
require 'rake/testtask'
|
2
|
-
|
3
|
-
test_task = if Rails.version.to_f < 3.2
|
4
|
-
require 'rails/test_unit/railtie'
|
5
|
-
Rake::TestTask
|
6
|
-
else
|
7
|
-
require 'rails/test_unit/sub_test_task'
|
8
|
-
Rails::SubTestTask
|
9
|
-
end
|
2
|
+
require 'rails/test_unit/railtie'
|
10
3
|
|
11
4
|
namespace :test do
|
12
|
-
|
5
|
+
Rake::TestTask.new(decorators: "test:prepare") do |t|
|
13
6
|
t.libs << "test"
|
14
7
|
t.pattern = "test/decorators/**/*_test.rb"
|
15
8
|
end
|
16
9
|
end
|
17
|
-
|
18
|
-
if Rails.version.to_f < 4.2 && Rake::Task.task_defined?('test:run')
|
19
|
-
Rake::Task['test:run'].enhance do
|
20
|
-
Rake::Task['test:decorators'].invoke
|
21
|
-
end
|
22
|
-
end
|
@@ -1,14 +1,7 @@
|
|
1
1
|
module Draper
|
2
2
|
module DeviseHelper
|
3
3
|
def sign_in(resource_or_scope, resource = nil)
|
4
|
-
scope =
|
5
|
-
Devise::Mapping.find_scope!(resource_or_scope)
|
6
|
-
rescue RuntimeError => e
|
7
|
-
# Draper 1.0 didn't require the mapping to exist
|
8
|
-
ActiveSupport::Deprecation.warn("#{e.message}.\nUse `sign_in :user, mock_user` instead.", caller)
|
9
|
-
:user
|
10
|
-
end
|
11
|
-
|
4
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
12
5
|
_stub_current_scope scope, resource || resource_or_scope
|
13
6
|
end
|
14
7
|
|
File without changes
|
@@ -7,11 +7,7 @@ module Draper
|
|
7
7
|
end
|
8
8
|
|
9
9
|
RSpec.configure do |config|
|
10
|
-
|
11
|
-
config.include DecoratorExampleGroup, file_path: %r{spec/decorators}, type: :decorator
|
12
|
-
else
|
13
|
-
config.include DecoratorExampleGroup, example_group: {file_path: %r{spec/decorators}}, type: :decorator
|
14
|
-
end
|
10
|
+
config.include DecoratorExampleGroup, file_path: %r{spec/decorators}, type: :decorator
|
15
11
|
|
16
12
|
[:decorator, :controller, :mailer].each do |type|
|
17
13
|
config.before(:each, type: type) { Draper::ViewContext.clear! }
|
data/lib/draper/test_case.rb
CHANGED
@@ -29,14 +29,10 @@ module Draper
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
if defined?
|
33
|
-
|
34
|
-
include Draper::TestCase::ViewContextTeardown
|
35
|
-
end
|
32
|
+
if defined? ActionController::TestCase
|
33
|
+
ActionController::TestCase.include Draper::TestCase::ViewContextTeardown
|
36
34
|
end
|
37
35
|
|
38
|
-
if defined?
|
39
|
-
|
40
|
-
include Draper::TestCase::ViewContextTeardown
|
41
|
-
end
|
36
|
+
if defined? ActionMailer::TestCase
|
37
|
+
ActionMailer::TestCase.include Draper::TestCase::ViewContextTeardown
|
42
38
|
end
|
data/lib/draper/undecorate.rb
CHANGED
data/lib/draper/version.rb
CHANGED
data/lib/draper/view_context.rb
CHANGED
@@ -20,8 +20,10 @@ module Draper
|
|
20
20
|
RequestStore.store[:current_controller]
|
21
21
|
end
|
22
22
|
|
23
|
-
# Sets the current controller.
|
23
|
+
# Sets the current controller. Clears view context when we are setting
|
24
|
+
# different controller.
|
24
25
|
def self.controller=(controller)
|
26
|
+
clear! if RequestStore.store[:current_controller] != controller
|
25
27
|
RequestStore.store[:current_controller] = controller
|
26
28
|
end
|
27
29
|
|
@@ -82,23 +84,5 @@ module Draper
|
|
82
84
|
def self.build_strategy
|
83
85
|
@build_strategy ||= Draper::ViewContext::BuildStrategy.new(:full)
|
84
86
|
end
|
85
|
-
|
86
|
-
# @deprecated Use {controller} instead.
|
87
|
-
def self.current_controller
|
88
|
-
ActiveSupport::Deprecation.warn("Draper::ViewContext.current_controller is deprecated (use controller instead)", caller)
|
89
|
-
self.controller || ApplicationController.new
|
90
|
-
end
|
91
|
-
|
92
|
-
# @deprecated Use {controller=} instead.
|
93
|
-
def self.current_controller=(controller)
|
94
|
-
ActiveSupport::Deprecation.warn("Draper::ViewContext.current_controller= is deprecated (use controller instead)", caller)
|
95
|
-
self.controller = controller
|
96
|
-
end
|
97
|
-
|
98
|
-
# @deprecated Use {build} instead.
|
99
|
-
def self.build_view_context
|
100
|
-
ActiveSupport::Deprecation.warn("Draper::ViewContext.build_view_context is deprecated (use build instead)", caller)
|
101
|
-
build
|
102
|
-
end
|
103
87
|
end
|
104
88
|
end
|
@@ -37,10 +37,19 @@ module Draper
|
|
37
37
|
attr_reader :block
|
38
38
|
|
39
39
|
def controller
|
40
|
-
|
41
|
-
|
40
|
+
Draper::ViewContext.controller ||= Draper.default_controller.new
|
41
|
+
Draper::ViewContext.controller.tap do |controller|
|
42
|
+
controller.request ||= new_test_request controller if defined?(ActionController::TestRequest)
|
42
43
|
end
|
43
44
|
end
|
45
|
+
|
46
|
+
def new_test_request(controller)
|
47
|
+
is_above_rails_5_1 ? ActionController::TestRequest.create(controller) : ActionController::TestRequest.create
|
48
|
+
end
|
49
|
+
|
50
|
+
def is_above_rails_5_1
|
51
|
+
ActionController::TestRequest.method(:create).parameters.first == [:req, :controller_class]
|
52
|
+
end
|
44
53
|
end
|
45
54
|
|
46
55
|
end
|
@@ -5,13 +5,13 @@ require "rails/generators/rails/scaffold_controller/scaffold_controller_generato
|
|
5
5
|
module Rails
|
6
6
|
module Generators
|
7
7
|
class ControllerGenerator
|
8
|
-
hook_for :decorator, default: true do |generator|
|
8
|
+
hook_for :decorator, type: :boolean, default: true do |generator|
|
9
9
|
invoke generator, [name.singularize]
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
class ScaffoldControllerGenerator
|
14
|
-
hook_for :decorator, default: true
|
14
|
+
hook_for :decorator, type: :boolean, default: true
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Draper
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
|
6
|
+
desc 'Creates an ApplicationDecorator, if none exists.'
|
7
|
+
|
8
|
+
def create_application_decorator
|
9
|
+
file = 'application_decorator.rb'
|
10
|
+
copy_file file, "app/decorators/#{file}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|