draper_new 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.
Files changed (144) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +15 -0
  5. data/.yardopts +1 -0
  6. data/CHANGELOG.md +230 -0
  7. data/CONTRIBUTING.md +20 -0
  8. data/Gemfile +16 -0
  9. data/Guardfile +26 -0
  10. data/LICENSE +7 -0
  11. data/README.md +587 -0
  12. data/Rakefile +69 -0
  13. data/draper_new.gemspec +31 -0
  14. data/gemfiles/4.0.gemfile +3 -0
  15. data/gemfiles/4.1.gemfile +3 -0
  16. data/gemfiles/4.2.6.gemfile +3 -0
  17. data/gemfiles/4.2.gemfile +3 -0
  18. data/lib/draper.rb +63 -0
  19. data/lib/draper/automatic_delegation.rb +56 -0
  20. data/lib/draper/collection_decorator.rb +100 -0
  21. data/lib/draper/decoratable.rb +96 -0
  22. data/lib/draper/decoratable/equality.rb +26 -0
  23. data/lib/draper/decorated_association.rb +35 -0
  24. data/lib/draper/decorates_assigned.rb +44 -0
  25. data/lib/draper/decorator.rb +293 -0
  26. data/lib/draper/delegation.rb +13 -0
  27. data/lib/draper/factory.rb +91 -0
  28. data/lib/draper/finders.rb +37 -0
  29. data/lib/draper/helper_proxy.rb +44 -0
  30. data/lib/draper/helper_support.rb +5 -0
  31. data/lib/draper/lazy_helpers.rb +15 -0
  32. data/lib/draper/railtie.rb +70 -0
  33. data/lib/draper/tasks/test.rake +22 -0
  34. data/lib/draper/test/devise_helper.rb +30 -0
  35. data/lib/draper/test/minitest_integration.rb +6 -0
  36. data/lib/draper/test/rspec_integration.rb +20 -0
  37. data/lib/draper/test_case.rb +42 -0
  38. data/lib/draper/undecorate.rb +9 -0
  39. data/lib/draper/version.rb +3 -0
  40. data/lib/draper/view_context.rb +104 -0
  41. data/lib/draper/view_context/build_strategy.rb +48 -0
  42. data/lib/draper/view_helpers.rb +37 -0
  43. data/lib/generators/controller_override.rb +17 -0
  44. data/lib/generators/mini_test/decorator_generator.rb +20 -0
  45. data/lib/generators/mini_test/templates/decorator_spec.rb +4 -0
  46. data/lib/generators/mini_test/templates/decorator_test.rb +4 -0
  47. data/lib/generators/rails/decorator_generator.rb +36 -0
  48. data/lib/generators/rails/templates/decorator.rb +19 -0
  49. data/lib/generators/rspec/decorator_generator.rb +9 -0
  50. data/lib/generators/rspec/templates/decorator_spec.rb +4 -0
  51. data/lib/generators/test_unit/decorator_generator.rb +9 -0
  52. data/lib/generators/test_unit/templates/decorator_test.rb +4 -0
  53. data/spec/draper/collection_decorator_spec.rb +307 -0
  54. data/spec/draper/decoratable/equality_spec.rb +10 -0
  55. data/spec/draper/decoratable_spec.rb +202 -0
  56. data/spec/draper/decorated_association_spec.rb +84 -0
  57. data/spec/draper/decorates_assigned_spec.rb +71 -0
  58. data/spec/draper/decorator_spec.rb +816 -0
  59. data/spec/draper/factory_spec.rb +251 -0
  60. data/spec/draper/finders_spec.rb +166 -0
  61. data/spec/draper/helper_proxy_spec.rb +61 -0
  62. data/spec/draper/lazy_helpers_spec.rb +21 -0
  63. data/spec/draper/undecorate_spec.rb +19 -0
  64. data/spec/draper/view_context/build_strategy_spec.rb +116 -0
  65. data/spec/draper/view_context_spec.rb +154 -0
  66. data/spec/draper/view_helpers_spec.rb +8 -0
  67. data/spec/dummy/.rspec +2 -0
  68. data/spec/dummy/Rakefile +7 -0
  69. data/spec/dummy/app/controllers/application_controller.rb +4 -0
  70. data/spec/dummy/app/controllers/localized_urls.rb +5 -0
  71. data/spec/dummy/app/controllers/posts_controller.rb +20 -0
  72. data/spec/dummy/app/decorators/mongoid_post_decorator.rb +4 -0
  73. data/spec/dummy/app/decorators/post_decorator.rb +60 -0
  74. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  75. data/spec/dummy/app/mailers/application_mailer.rb +3 -0
  76. data/spec/dummy/app/mailers/post_mailer.rb +19 -0
  77. data/spec/dummy/app/models/admin.rb +5 -0
  78. data/spec/dummy/app/models/mongoid_post.rb +5 -0
  79. data/spec/dummy/app/models/post.rb +3 -0
  80. data/spec/dummy/app/models/user.rb +5 -0
  81. data/spec/dummy/app/views/layouts/application.html.erb +11 -0
  82. data/spec/dummy/app/views/post_mailer/decorated_email.html.erb +1 -0
  83. data/spec/dummy/app/views/posts/_post.html.erb +40 -0
  84. data/spec/dummy/app/views/posts/show.html.erb +1 -0
  85. data/spec/dummy/bin/rails +4 -0
  86. data/spec/dummy/config.ru +4 -0
  87. data/spec/dummy/config/application.rb +71 -0
  88. data/spec/dummy/config/boot.rb +5 -0
  89. data/spec/dummy/config/database.yml +25 -0
  90. data/spec/dummy/config/environment.rb +5 -0
  91. data/spec/dummy/config/environments/development.rb +33 -0
  92. data/spec/dummy/config/environments/production.rb +57 -0
  93. data/spec/dummy/config/environments/test.rb +31 -0
  94. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  95. data/spec/dummy/config/initializers/inflections.rb +15 -0
  96. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  97. data/spec/dummy/config/initializers/secret_token.rb +8 -0
  98. data/spec/dummy/config/initializers/session_store.rb +8 -0
  99. data/spec/dummy/config/locales/en.yml +5 -0
  100. data/spec/dummy/config/mongoid.yml +79 -0
  101. data/spec/dummy/config/routes.rb +9 -0
  102. data/spec/dummy/db/migrate/20121019115657_create_posts.rb +8 -0
  103. data/spec/dummy/db/schema.rb +21 -0
  104. data/spec/dummy/db/seeds.rb +2 -0
  105. data/spec/dummy/fast_spec/post_decorator_spec.rb +37 -0
  106. data/spec/dummy/lib/tasks/test.rake +16 -0
  107. data/spec/dummy/public/404.html +26 -0
  108. data/spec/dummy/public/422.html +26 -0
  109. data/spec/dummy/public/500.html +25 -0
  110. data/spec/dummy/public/favicon.ico +0 -0
  111. data/spec/dummy/script/rails +6 -0
  112. data/spec/dummy/spec/decorators/active_model_serializers_spec.rb +16 -0
  113. data/spec/dummy/spec/decorators/devise_spec.rb +64 -0
  114. data/spec/dummy/spec/decorators/helpers_spec.rb +21 -0
  115. data/spec/dummy/spec/decorators/post_decorator_spec.rb +66 -0
  116. data/spec/dummy/spec/decorators/spec_type_spec.rb +7 -0
  117. data/spec/dummy/spec/decorators/view_context_spec.rb +22 -0
  118. data/spec/dummy/spec/mailers/post_mailer_spec.rb +33 -0
  119. data/spec/dummy/spec/models/mongoid_post_spec.rb +8 -0
  120. data/spec/dummy/spec/models/post_spec.rb +6 -0
  121. data/spec/dummy/spec/shared_examples/decoratable.rb +24 -0
  122. data/spec/dummy/spec/spec_helper.rb +8 -0
  123. data/spec/dummy/test/decorators/minitest/devise_test.rb +64 -0
  124. data/spec/dummy/test/decorators/minitest/helpers_test.rb +21 -0
  125. data/spec/dummy/test/decorators/minitest/spec_type_test.rb +52 -0
  126. data/spec/dummy/test/decorators/minitest/view_context_test.rb +24 -0
  127. data/spec/dummy/test/decorators/test_unit/devise_test.rb +64 -0
  128. data/spec/dummy/test/decorators/test_unit/helpers_test.rb +21 -0
  129. data/spec/dummy/test/decorators/test_unit/view_context_test.rb +24 -0
  130. data/spec/dummy/test/minitest_helper.rb +2 -0
  131. data/spec/dummy/test/test_helper.rb +3 -0
  132. data/spec/generators/controller/controller_generator_spec.rb +22 -0
  133. data/spec/generators/decorator/decorator_generator_spec.rb +92 -0
  134. data/spec/integration/integration_spec.rb +66 -0
  135. data/spec/performance/active_record.rb +4 -0
  136. data/spec/performance/benchmark.rb +55 -0
  137. data/spec/performance/decorators.rb +45 -0
  138. data/spec/performance/models.rb +20 -0
  139. data/spec/spec_helper.rb +41 -0
  140. data/spec/support/dummy_app.rb +85 -0
  141. data/spec/support/matchers/have_text.rb +50 -0
  142. data/spec/support/shared_examples/decoratable_equality.rb +40 -0
  143. data/spec/support/shared_examples/view_helpers.rb +39 -0
  144. metadata +420 -0
@@ -0,0 +1,69 @@
1
+ require 'rake'
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ def run_in_dummy_app(command)
6
+ success = system("cd spec/dummy && #{command}")
7
+ raise "#{command} failed" unless success
8
+ end
9
+
10
+ task "default" => "ci"
11
+
12
+ desc "Run all tests for CI"
13
+ task "ci" => "spec"
14
+
15
+ desc "Run all specs"
16
+ task "spec" => "spec:all"
17
+
18
+ namespace "spec" do
19
+ task "all" => ["draper", "generators", "integration"]
20
+
21
+ def spec_task(name)
22
+ desc "Run #{name} specs"
23
+ RSpec::Core::RakeTask.new(name) do |t|
24
+ t.pattern = "spec/#{name}/**/*_spec.rb"
25
+ end
26
+ end
27
+
28
+ spec_task "draper"
29
+ spec_task "generators"
30
+
31
+ desc "Run integration specs"
32
+ task "integration" => ["db:setup", "integration:all"]
33
+
34
+ namespace "integration" do
35
+ task "all" => ["development", "production", "test"]
36
+
37
+ ["development", "production"].each do |environment|
38
+ task environment do
39
+ Rake::Task["spec:integration:run"].execute environment
40
+ end
41
+ end
42
+
43
+ task "run" do |t, environment|
44
+ puts "Running integration specs in #{environment}"
45
+
46
+ ENV["RAILS_ENV"] = environment
47
+ success = system("rspec spec/integration")
48
+
49
+ raise "Integration specs failed in #{environment}" unless success
50
+ end
51
+
52
+ task "test" do
53
+ puts "Running rake in dummy app"
54
+ ENV["RAILS_ENV"] = "test"
55
+ run_in_dummy_app "rake"
56
+ end
57
+ end
58
+ end
59
+
60
+ namespace "db" do
61
+ desc "Set up databases for integration testing"
62
+ task "setup" do
63
+ puts "Setting up databases"
64
+ run_in_dummy_app "rm -f db/*.sqlite3"
65
+ run_in_dummy_app "RAILS_ENV=development rake db:schema:load db:seed"
66
+ run_in_dummy_app "RAILS_ENV=production rake db:schema:load db:seed"
67
+ run_in_dummy_app "RAILS_ENV=test rake db:schema:load"
68
+ end
69
+ end
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "draper/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "draper_new"
7
+ s.version = Draper::VERSION
8
+ s.authors = ["Chashmeet Singh"]
9
+ s.email = ["chashmeetsingh@gmail.com"]
10
+ s.homepage = "http://github.com/chashmeetsingh/draper"
11
+ s.summary = "View Models for Rails"
12
+ s.description = "Draper adds an object-oriented layer of presentation logic to your Rails apps."
13
+ s.license = "MIT"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency 'activesupport'
21
+ s.add_dependency 'actionpack'
22
+ s.add_dependency 'request_store'
23
+ s.add_dependency 'activemodel'
24
+
25
+ s.add_development_dependency 'ammeter'
26
+ s.add_development_dependency 'rake'
27
+ s.add_development_dependency 'rspec-rails'
28
+ s.add_development_dependency 'minitest-rails'
29
+ s.add_development_dependency 'capybara'
30
+ s.add_development_dependency 'active_model_serializers'
31
+ end
@@ -0,0 +1,3 @@
1
+ gem "rails", "~> 4.0.0"
2
+ gem "mongoid", "~> 4.0"
3
+ gem "devise", "~> 3.0.0"
@@ -0,0 +1,3 @@
1
+ gem "rails", "~> 4.1.0"
2
+ gem "mongoid", "~> 4.0"
3
+ gem "devise", "~> 3.2"
@@ -0,0 +1,3 @@
1
+ gem "rails", "~> 4.2.6"
2
+ gem "mongoid", "~> 5.1.3"
3
+ gem "devise", "~> 4.1.1"
@@ -0,0 +1,3 @@
1
+ gem "rails", "~> 4.2.0"
2
+ gem "mongoid", "~> 4.0"
3
+ gem "devise", "~> 3.4"
@@ -0,0 +1,63 @@
1
+ require 'action_view'
2
+ require 'active_model/naming'
3
+ require 'active_model/serialization'
4
+ require 'active_model/serializers/json'
5
+ require 'active_model/serializers/xml'
6
+ require 'active_support/inflector'
7
+ require 'active_support/core_ext/hash/keys'
8
+ require 'active_support/core_ext/hash/reverse_merge'
9
+ require 'active_support/core_ext/name_error'
10
+
11
+ require 'draper/version'
12
+ require 'draper/view_helpers'
13
+ require 'draper/delegation'
14
+ require 'draper/automatic_delegation'
15
+ require 'draper/finders'
16
+ require 'draper/decorator'
17
+ require 'draper/helper_proxy'
18
+ require 'draper/lazy_helpers'
19
+ require 'draper/decoratable'
20
+ require 'draper/factory'
21
+ require 'draper/decorated_association'
22
+ require 'draper/helper_support'
23
+ require 'draper/view_context'
24
+ require 'draper/collection_decorator'
25
+ require 'draper/undecorate'
26
+ require 'draper/decorates_assigned'
27
+ require 'draper/railtie' if defined?(Rails)
28
+
29
+ module Draper
30
+ def self.setup_action_controller(base)
31
+ base.class_eval do
32
+ include Draper::ViewContext
33
+ extend Draper::HelperSupport
34
+ extend Draper::DecoratesAssigned
35
+
36
+ before_filter :activate_draper
37
+ end
38
+ end
39
+
40
+ def self.setup_action_mailer(base)
41
+ base.class_eval do
42
+ include Draper::ViewContext
43
+ end
44
+ end
45
+
46
+ def self.setup_orm(base)
47
+ base.class_eval do
48
+ include Draper::Decoratable
49
+ end
50
+ end
51
+
52
+ class UninferrableDecoratorError < NameError
53
+ def initialize(klass)
54
+ super("Could not infer a decorator for #{klass}.")
55
+ end
56
+ end
57
+
58
+ class UninferrableSourceError < NameError
59
+ def initialize(klass)
60
+ super("Could not infer a source for #{klass}.")
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,56 @@
1
+ module Draper
2
+ module AutomaticDelegation
3
+ extend ActiveSupport::Concern
4
+
5
+ # Delegates missing instance methods to the source object.
6
+ def method_missing(method, *args, &block)
7
+ return super unless delegatable?(method)
8
+
9
+ self.class.delegate method
10
+ send(method, *args, &block)
11
+ end
12
+
13
+ # Checks if the decorator responds to an instance method, or is able to
14
+ # proxy it to the source object.
15
+ def respond_to_missing?(method, include_private = false)
16
+ super || delegatable?(method)
17
+ end
18
+
19
+ # @private
20
+ def delegatable?(method)
21
+ object.respond_to?(method)
22
+ end
23
+
24
+ module ClassMethods
25
+ # Proxies missing class methods to the source class.
26
+ def method_missing(method, *args, &block)
27
+ return super unless delegatable?(method)
28
+
29
+ object_class.send(method, *args, &block)
30
+ end
31
+
32
+ # Checks if the decorator responds to a class method, or is able to proxy
33
+ # it to the source class.
34
+ def respond_to_missing?(method, include_private = false)
35
+ super || delegatable?(method)
36
+ end
37
+
38
+ # @private
39
+ def delegatable?(method)
40
+ object_class? && object_class.respond_to?(method)
41
+ end
42
+
43
+ # @private
44
+ # Avoids reloading the model class when ActiveSupport clears autoloaded
45
+ # dependencies in development mode.
46
+ def before_remove_const
47
+ end
48
+ end
49
+
50
+ included do
51
+ private :delegatable?
52
+ private_class_method :delegatable?
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,100 @@
1
+ module Draper
2
+ class CollectionDecorator
3
+ include Enumerable
4
+ include Draper::ViewHelpers
5
+ extend Draper::Delegation
6
+
7
+ # @return the collection being decorated.
8
+ attr_reader :object
9
+
10
+ # @return [Class] the decorator class used to decorate each item, as set by
11
+ # {#initialize}.
12
+ attr_reader :decorator_class
13
+
14
+ # @return [Hash] extra data to be used in user-defined methods, and passed
15
+ # to each item's decorator.
16
+ attr_accessor :context
17
+
18
+ array_methods = Array.instance_methods - Object.instance_methods
19
+ delegate :==, :as_json, *array_methods, to: :decorated_collection
20
+
21
+ # @param [Enumerable] object
22
+ # collection to decorate.
23
+ # @option options [Class, nil] :with (nil)
24
+ # the decorator class used to decorate each item. When `nil`, each item's
25
+ # {Decoratable#decorate decorate} method will be used.
26
+ # @option options [Hash] :context ({})
27
+ # extra data to be stored in the collection decorator and used in
28
+ # user-defined methods, and passed to each item's decorator.
29
+ def initialize(object, options = {})
30
+ options.assert_valid_keys(:with, :context)
31
+ @object = object
32
+ @decorator_class = options[:with]
33
+ @context = options.fetch(:context, {})
34
+ end
35
+
36
+ class << self
37
+ alias_method :decorate, :new
38
+ end
39
+
40
+ # @return [Array] the decorated items.
41
+ def decorated_collection
42
+ @decorated_collection ||= object.map{|item| decorate_item(item)}
43
+ end
44
+
45
+ # Delegated to the decorated collection when using the block form
46
+ # (`Enumerable#find`) or to the decorator class if not
47
+ # (`ActiveRecord::FinderMethods#find`)
48
+ def find(*args, &block)
49
+ if block_given?
50
+ decorated_collection.find(*args, &block)
51
+ else
52
+ ActiveSupport::Deprecation.warn("Using ActiveRecord's `find` on a CollectionDecorator is deprecated. Call `find` on a model, and then decorate the result", caller)
53
+ decorate_item(object.find(*args))
54
+ end
55
+ end
56
+
57
+ def to_s
58
+ "#<#{self.class.name} of #{decorator_class || "inferred decorators"} for #{object.inspect}>"
59
+ end
60
+
61
+ def context=(value)
62
+ @context = value
63
+ each {|item| item.context = value } if @decorated_collection
64
+ end
65
+
66
+ # @return [true]
67
+ def decorated?
68
+ true
69
+ end
70
+
71
+ alias_method :decorated_with?, :instance_of?
72
+
73
+ def kind_of?(klass)
74
+ decorated_collection.kind_of?(klass) || super
75
+ end
76
+ alias_method :is_a?, :kind_of?
77
+
78
+ def replace(other)
79
+ decorated_collection.replace(other)
80
+ self
81
+ end
82
+
83
+ protected
84
+
85
+ # Decorates the given item.
86
+ def decorate_item(item)
87
+ item_decorator.call(item, context: context)
88
+ end
89
+
90
+ private
91
+
92
+ def item_decorator
93
+ if decorator_class
94
+ decorator_class.method(:decorate)
95
+ else
96
+ ->(item, options) { item.decorate(options) }
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,96 @@
1
+ require 'draper/decoratable/equality'
2
+
3
+ module Draper
4
+ # Provides shortcuts to decorate objects directly, so you can do
5
+ # `@product.decorate` instead of `ProductDecorator.new(@product)`.
6
+ #
7
+ # This module is included by default into `ActiveRecord::Base` and
8
+ # `Mongoid::Document`, but you're using another ORM, or want to decorate
9
+ # plain old Ruby objects, you can include it manually.
10
+ module Decoratable
11
+ extend ActiveSupport::Concern
12
+ include Draper::Decoratable::Equality
13
+
14
+ # Decorates the object using the inferred {#decorator_class}.
15
+ # @param [Hash] options
16
+ # see {Decorator#initialize}
17
+ def decorate(options = {})
18
+ decorator_class.decorate(self, options)
19
+ end
20
+
21
+ # (see ClassMethods#decorator_class)
22
+ def decorator_class
23
+ self.class.decorator_class
24
+ end
25
+
26
+ def decorator_class?
27
+ self.class.decorator_class?
28
+ end
29
+
30
+ # The list of decorators that have been applied to the object.
31
+ #
32
+ # @return [Array<Class>] `[]`
33
+ def applied_decorators
34
+ []
35
+ end
36
+
37
+ # (see Decorator#decorated_with?)
38
+ # @return [false]
39
+ def decorated_with?(decorator_class)
40
+ false
41
+ end
42
+
43
+ # Checks if this object is decorated.
44
+ #
45
+ # @return [false]
46
+ def decorated?
47
+ false
48
+ end
49
+
50
+ module ClassMethods
51
+
52
+ # Decorates a collection of objects. Used at the end of a scope chain.
53
+ #
54
+ # @example
55
+ # Product.popular.decorate
56
+ # @param [Hash] options
57
+ # see {Decorator.decorate_collection}.
58
+ def decorate(options = {})
59
+ collection = Rails::VERSION::MAJOR >= 4 ? all : scoped
60
+ decorator_class.decorate_collection(collection, options.reverse_merge(with: nil))
61
+ end
62
+
63
+ def decorator_class?
64
+ decorator_class
65
+ rescue Draper::UninferrableDecoratorError
66
+ false
67
+ end
68
+
69
+ # Infers the decorator class to be used by {Decoratable#decorate} (e.g.
70
+ # `Product` maps to `ProductDecorator`).
71
+ #
72
+ # @return [Class] the inferred decorator class.
73
+ def decorator_class
74
+ prefix = respond_to?(:model_name) ? model_name : name
75
+ decorator_name = "#{prefix}Decorator"
76
+ decorator_name.constantize
77
+ rescue NameError => error
78
+ if superclass.respond_to?(:decorator_class)
79
+ superclass.decorator_class
80
+ else
81
+ raise unless error.missing_name?(decorator_name)
82
+ raise Draper::UninferrableDecoratorError.new(self)
83
+ end
84
+ end
85
+
86
+ # Compares with possibly-decorated objects.
87
+ #
88
+ # @return [Boolean]
89
+ def ===(other)
90
+ super || (other.respond_to?(:object) && super(other.object))
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,26 @@
1
+ module Draper
2
+ module Decoratable
3
+ module Equality
4
+ # Compares self with a possibly-decorated object.
5
+ #
6
+ # @return [Boolean]
7
+ def ==(other)
8
+ super || Equality.test_for_decorator(self, other)
9
+ end
10
+
11
+ # Compares an object to a possibly-decorated object.
12
+ #
13
+ # @return [Boolean]
14
+ def self.test(object, other)
15
+ return object == other if object.is_a?(Decoratable)
16
+ object == other || test_for_decorator(object, other)
17
+ end
18
+
19
+ # @private
20
+ def self.test_for_decorator(object, other)
21
+ other.respond_to?(:decorated?) && other.decorated? &&
22
+ other.respond_to?(:object) && test(object, other.object)
23
+ end
24
+ end
25
+ end
26
+ end