dumb_delegator 0.8.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63674a3e04272740045c64f5cd122fb431c333be76ffb7f5364067e28f31ef44
4
- data.tar.gz: 8b6ad9d8f119f2e8092e9fd5027ea076a41420ab76ea3555587577a12b234027
3
+ metadata.gz: 3dfd1848821cd96312119f18cd2cc09bfcdc72c2efca3f53ddca59bb6247008f
4
+ data.tar.gz: 6dfd0d7689ed6b8d83dd0029e3687e624594e021c5ed0c58ca4ce6489abd8812
5
5
  SHA512:
6
- metadata.gz: e5c94e20a372ff9fb834e9efe3b9bf922bc3539af15bab58aafa1fd5d8403a31b8de7728d7a6fdd7d8a90558333a2b326b866549156af3405049d811ac9b9bce
7
- data.tar.gz: 180f72c3eb297c0ea3e14f36dd87d9c13951316371f4d3d0c6eeb70e09812b4d7ee509fae5515e4559be3969612fced9da7adaa4cb5b2c4ea8459d9b77c179fd
6
+ metadata.gz: 72c45104a5258f109d258c6ff3268da7b7f1d2810f4a22ee916f8806d8cd5f3ca76ef01cfa6a7d2e18347158a25b4a727814e49be8ddec576a40d3b2bee6ca61
7
+ data.tar.gz: 49588ab5d55d168cf1916c7961285e9dc1c1a2f8fe0a6a097e6c671adee01424e374e99797410018e891fc6c9e09069515efbb84331fbd2f4c1cf9b486229ecd
data/.gitignore CHANGED
@@ -1,20 +1,23 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- .ruby-version
7
- Gemfile.lock
8
- InstalledFiles
9
- _yardoc
10
- coverage
11
- doc/
12
- lib/bundler/man
13
- bin
14
- pkg
15
- rdoc
16
- spec/reports
17
- test/tmp
18
- test/version_tmp
19
- tmp
20
- tags
1
+ # Ignore all logfiles and tempfiles
2
+ /tmp/
3
+ /tags
4
+
5
+ # Environment normalisation
6
+ /.env
7
+ /.rspec-local
8
+ /.yardoc
9
+ /lib/bundler/man/
10
+
11
+ # Gem packaging stuff
12
+ /*.gem
13
+ /pkg/
14
+
15
+ # Dependencies and such
16
+ /.bundle
17
+ /.ruby-version
18
+ /Gemfile.lock
19
+
20
+ # Spec and coverage housekeeping
21
+ /coverage/
22
+ /spec/rspec-status.txt
23
+ /spec/reports
data/.rspec CHANGED
@@ -1,3 +1,4 @@
1
+ --require spec_helper
2
+
1
3
  --color
2
4
  --format progress
3
- --order rand
@@ -4,20 +4,14 @@ env:
4
4
  global:
5
5
  - CC_TEST_REPORTER_ID=de7062a4090ce5638b515a2cf9f2ab619de3e3f4ff439dc6cdad025c7a8d6b76
6
6
  rvm:
7
- - 1.9.3
8
- - 2.0
9
- - 2.1
10
- - 2.2
11
- - 2.3
12
7
  - 2.4
13
8
  - 2.5
14
9
  - 2.6
15
10
  - 2.7
16
- - jruby-19mode
17
11
  - jruby
18
12
  cache: bundler
19
13
  before_install:
20
- - gem update --system --conservative || (gem i "rubygems-update:~>2.7" --no-document && update_rubygems) # see: https://github.com/rubygems/rubygems/issues/2534#issuecomment-448843746
14
+ - gem update --system --conservative
21
15
  - gem update bundler --conservative
22
16
  before_script:
23
17
  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
@@ -5,6 +5,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [1.0.0] 2020-01-27
9
+ ### Changed
10
+ - Require Ruby >= 2.4. We may still work with older Rubies, but no promises.
11
+ - Basic introspection support for a DumbDelegator instance: `#inspect`, `#method`, and `#methods`. [[13](https://github.com/stevenharman/dumb_delegator/pull/13)]
12
+
13
+ ### Added
14
+ - Optional support for using a DumbDelegator instance in a `case` statement. [[12](https://github.com/stevenharman/dumb_delegator/pull/12)]
15
+
8
16
  ## [0.8.1] 2020-01-25
9
17
  ### Changed
10
18
  - Explicitly Require Ruby >= 1.9.3
data/Gemfile CHANGED
@@ -1,6 +1,7 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in dumb_delegator.gemspec
4
4
  gemspec
5
5
 
6
- gem "simplecov", :group => :test, :require => nil
6
+ gem "simplecov", group: :test, require: nil
7
+ gem "pry-byebug", group: [:development, :test], platforms: [:ruby]
data/README.md CHANGED
@@ -5,11 +5,10 @@
5
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/b684cbe08af745cbe957/maintainability)](https://codeclimate.com/github/stevenharman/dumb_delegator/maintainability)
6
6
  [![Test Coverage](https://api.codeclimate.com/v1/badges/b684cbe08af745cbe957/test_coverage)](https://codeclimate.com/github/stevenharman/dumb_delegator/test_coverage)
7
7
 
8
-
9
8
  Ruby provides the `delegate` standard library.
10
9
  However, we found that it is not appropriate for cases that require nearly every call to be proxied.
11
10
 
12
- For instance, Rails uses `#class` and `#instance_of?` to introspect on model classes when generating forms and URL helpers.
11
+ For instance, Rails uses `#class` and `#instance_of?` to introspect on Model classes when generating forms and URL helpers.
13
12
  These methods are not forwarded when using `Delegator` or `SimpleDelegator`.
14
13
 
15
14
  ```ruby
@@ -42,16 +41,47 @@ d.class #=> MyAwesomeClass
42
41
  d.is_a? MyAwesomeClass #=> true
43
42
  ```
44
43
 
45
- ## Usage
44
+ ## Installation
46
45
 
47
- ### Rails Model Decorator
46
+ Add this line to your application's Gemfile:
48
47
 
49
- There are [many decorator implementations](http://robots.thoughtbot.com/post/14825364877/evaluating-alternative-decorator-implementations-in) in Ruby.
50
- One of the simplest is "`SimpleDelegator` + `super` + `__getobj__`," but it has the drawback of confusing Rails.
51
- It is necessary to redefine `#class`.
52
- We've also observed the need to redefine `#instance_of?` for URL helpers.
48
+ ```ruby
49
+ gem "dumb_delegator"
50
+ ```
51
+
52
+ And then execute:
53
+
54
+ ```bash
55
+ $ bundle
56
+ ```
57
+
58
+ Or install it yourself as:
59
+
60
+ ```bash
61
+ $ gem install dumb_delegator
62
+ ```
63
+
64
+ ### Versioning
65
+
66
+ This project adheres to [Semantic Versioning][semver].
67
+
68
+ #### Version `0.8.x`
69
+
70
+ The `0.8.0` release was downloaded 1.2MM times before the `1.0.0` work began.
71
+ Which is great.
72
+ But, we wanted to clean up some cruft, fix a few small things, and improve ergonomics.
73
+ And do all of that, while, hopefully, not breaking existing usage.
74
+
75
+ To that end, `1.0.0` dropped support for all [EoL'd Rubies][ruby-releases] and only officially supported Ruby `2.4` - `2.7` when it was released.
76
+ However, most older Rubies, _should_ still work.
77
+ Maybe… Shmaybe?
78
+ Except for Ruby 1.9, which probably _does not work_ with `DumbDelegator` `> 1.0.0`.
79
+ If you're on an EoL'd Ruby, please try the `0.8.x` versions of this gem.
80
+
81
+ ## Usage
53
82
 
54
- With `DumbDelegator`, there's not a need for this hackery because nearly every possible method is delegated:
83
+ `DumbDelegator`'s API and usage patters were inspired by Ruby stdlib's `SimpleDelegator`.
84
+ As such, the usage and ergonomics are quite similar.
55
85
 
56
86
  ```ruby
57
87
  require "dumb_delegator"
@@ -79,25 +109,73 @@ class Sugar < DumbDelegator
79
109
  end
80
110
 
81
111
  coffee = Coffee.new
82
- Sugar.new(Milk.new(coffee)).cost #=> 2.6
83
- Sugar.new(Sugar.new(coffee)).cost #=> 2.4
84
- Milk.new(coffee).origin #=> Colombia
85
- Sugar.new(Milk.new(coffee)).class #=> Coffee
112
+
113
+ cup_o_coffee = Sugar.new(Milk.new(coffee))
114
+ cup_o_coffee.origin #=> Colombia
115
+ cup_o_coffee.cost #=> 2.6
116
+
117
+ # Introspection
118
+ cup_o_coffee.class #=> Coffee
119
+ cup_o_coffee.__getobj__ #=> #<Coffee:0x00007fabed1d6910>
120
+ cup_o_coffee.inspect #=> "#<Sugar:70188197507600 obj: #<Milk:70188197507620 obj: #<Coffee:0x00007fabed1d6910>>>"
121
+ cup_o_coffee.is_a?(Coffee) #=> true
122
+ cup_o_coffee.is_a?(Milk) #=> true
123
+ cup_o_coffee.is_a?(Sugar) #=> true
86
124
  ```
87
125
 
88
- ## Installation
126
+ ### Rails Model Decorator
89
127
 
90
- Add this line to your application's Gemfile:
128
+ There are [many decorator implementations](http://robots.thoughtbot.com/post/14825364877/evaluating-alternative-decorator-implementations-in) in Ruby.
129
+ One of the simplest is "`SimpleDelegator` + `super` + `__getobj__`," but it has the drawback of confusing Rails.
130
+ It is necessary to redefine `#class`, at a minimum.
131
+ If you're relying on Rails' URL Helpers with a delegated object, you also need to redefine `#instance_of?`.
132
+ We've also observed the need to redefine other Rails-y methods to get various bits of 🧙 Rails Magic 🧙 to work as expected.
91
133
 
92
- gem "dumb_delegator"
134
+ With `DumbDelegator`, there's not a need for redefining these things because nearly every possible method is delegated.
93
135
 
94
- And then execute:
136
+ ### Optional `case` statement support
95
137
 
96
- $ bundle
138
+ Instances of `DumbDelegator` will delegate `#===` out of the box.
139
+ Meaning an instance can be used in a `case` statement so long as the `when` clauses rely on instance comparison.
140
+ For example, when using a `case` with a regular expression, range, etc...
97
141
 
98
- Or install it yourself as:
142
+ It's also common to use Class/Module in the `where` clauses.
143
+ In such usage, it's the Class/Module's `::===` method that gets called, rather than the `#===` method on the `DumbDelegator` instance.
144
+ That means we need to override each Class/Module's `::===` method, or even monkey-patch `::Module::===`.
145
+
146
+ `DumbDelegator` ships with an optional extension to override a Class/Module's `::===` method.
147
+ But you need to extend each Class/Module you use in a `where` clause.
148
+
149
+ ```ruby
150
+ def try_a_case(thing)
151
+ case thing
152
+ when MyAwesomeClass
153
+ "thing is a MyAwesomeClass."
154
+ when DumbDelegator
155
+ "thing is a DumbDelegator."
156
+ else
157
+ "Bad. This is bad."
158
+ end
159
+ end
160
+
161
+ target = MyAwesomeClass.new
162
+ dummy = DumbDelegator.new(target)
163
+
164
+ try_a_case(dummy) #=> thing is a DumbDelegator.
165
+
166
+ MyAwesomeClass.extend(DumbDelegator::TripleEqualExt)
167
+
168
+ try_a_case(dummy) #=> thing is a MyAwesomeClass.
169
+ ```
99
170
 
100
- $ gem install dumb_delegator
171
+ #### Overriding `Module::===`
172
+ If necessary, you could also override the base `Module::===`, though that's pretty invasive.
173
+
174
+ 🐲 _There be dragons!_ 🐉
175
+
176
+ ```ruby
177
+ ::Module.extend(DumbDelegator::TripleEqualExt)
178
+ ```
101
179
 
102
180
  ## Contributing
103
181
 
@@ -110,3 +188,7 @@ Or install it yourself as:
110
188
  ## Contribution Ideas/Needs
111
189
 
112
190
  1. Ruby 1.8 support (use the `blankslate` gem?)
191
+
192
+
193
+ [ruby-releases]: https://www.ruby-lang.org/en/downloads/branches/ "The current maintenance status of the various Ruby branches"
194
+ [semver]: https://semver.org/spec/v2.0.0.html "Semantic Versioning 2.0.0"
data/Rakefile CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env rake
2
- require 'bundler/gem_tasks'
2
+ require "bundler/gem_tasks"
3
3
 
4
- require 'rspec/core/rake_task'
4
+ require "rspec/core/rake_task"
5
5
  RSpec::Core::RakeTask.new(:spec) do |t|
6
- t.rspec_opts = '--tag ~objectspace' if RUBY_PLATFORM == 'java'
6
+ t.rspec_opts = "--tag ~objectspace" if RUBY_PLATFORM == "java"
7
7
  end
8
8
 
9
- task :default => :spec
9
+ task default: :spec
@@ -1,22 +1,31 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/dumb_delegator/version', __FILE__)
1
+ require File.expand_path("../lib/dumb_delegator/version", __FILE__)
3
2
 
4
3
  Gem::Specification.new do |gem|
5
4
  gem.name = "dumb_delegator"
6
5
  gem.version = DumbDelegator::VERSION
7
- gem.required_ruby_version = ">= 1.9.3"
8
- gem.authors = ['Andy Lindeman', 'Steven Harman']
9
- gem.email = ['alindeman@gmail.com', 'steven@harmanly.com']
10
- gem.description = %q{Delegator class that delegates ALL the things}
11
- gem.summary = <<-EOD
12
- Delegator and SimpleDelegator in Ruby's stdlib are somewhat useful, but they pull in most of Kernel. This is not appropriate for many uses; for instance, delegation to Rails models.
6
+ gem.required_ruby_version = ">= 2.4.0"
7
+ gem.authors = ["Andy Lindeman", "Steven Harman"]
8
+ gem.email = ["alindeman@gmail.com", "steven@harmanly.com"]
9
+ gem.licenses = ["MIT"]
10
+ gem.summary = "Delegator class that delegates ALL the things"
11
+ gem.description = <<~EOD
12
+ Delegator and SimpleDelegator in Ruby's stdlib are useful, but they pull in most of Kernel.
13
+ This is not appropriate for many uses; for instance, delegation to Rails Models.
14
+ DumbDelegator, on the other hand, delegates nearly everything to the wrapped object.
13
15
  EOD
14
- gem.homepage = 'https://github.com/stevenharman/dumb_delegator'
16
+ gem.homepage = "https://github.com/stevenharman/dumb_delegator"
15
17
 
16
- gem.files = `git ls-files`.split($\)
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
- gem.require_paths = ['lib']
18
+ gem.metadata = {
19
+ "changelog_uri" => "https://github.com/stevenharman/dumb_delegator/blob/master/CHANGELOG.md",
20
+ "documentation_uri" => "https://rubydoc.info/gems/dumb_delegator",
21
+ "source_code_uri" => "https://github.com/stevenharman/dumb_delegator",
22
+ }
19
23
 
20
- gem.add_development_dependency 'rake', '~> 10.0'
21
- gem.add_development_dependency 'rspec', '~> 3.4'
24
+ gem.files = `git ls-files`.split($\)
25
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
26
+ gem.require_paths = ["lib"]
27
+
28
+ gem.add_development_dependency "pry"
29
+ gem.add_development_dependency "rake", "~> 13.0"
30
+ gem.add_development_dependency "rspec", "~> 3.9"
22
31
  end
@@ -1,13 +1,48 @@
1
- require 'dumb_delegator/version'
1
+ require "dumb_delegator/triple_equal_ext"
2
+ require "dumb_delegator/version"
2
3
 
4
+ ##
5
+ # @example
6
+ # class Coffee
7
+ # def cost
8
+ # 2
9
+ # end
10
+ #
11
+ # def origin
12
+ # "Colombia"
13
+ # end
14
+ # end
15
+ #
16
+ # class Milk < DumbDelegator
17
+ # def cost
18
+ # super + 0.4
19
+ # end
20
+ # end
21
+ #
22
+ # class Sugar < DumbDelegator
23
+ # def cost
24
+ # super + 0.2
25
+ # end
26
+ # end
27
+ #
28
+ # coffee = Coffee.new
29
+ # Milk.new(coffee).origin #=> Colombia
30
+ # Sugar.new(Sugar.new(coffee)).cost #=> 2.4
31
+ #
32
+ # cup_o_coffee = Sugar.new(Milk.new(coffee))
33
+ # cup_o_coffee.cost #=> 2.6
34
+ # cup_o_coffee.class #=> Coffee
35
+ # cup_o_coffee.is_a?(Coffee) #=> true
36
+ # cup_o_coffee.is_a?(Milk) #=> true
37
+ # cup_o_coffee.is_a?(Sugar) #=> true
3
38
  class DumbDelegator < ::BasicObject
4
39
  (::BasicObject.instance_methods - [:equal?, :__id__, :__send__, :method_missing]).each do |method|
5
- undef_method method
40
+ undef_method(method)
6
41
  end
7
42
 
8
43
  kernel = ::Kernel.dup
9
- (kernel.instance_methods - [:dup, :clone, :respond_to?, :object_id]).each do |method|
10
- kernel.__send__ :undef_method, method
44
+ (kernel.instance_methods - [:dup, :clone, :method, :methods, :respond_to?, :object_id]).each do |method|
45
+ kernel.__send__(:undef_method, method)
11
46
  end
12
47
  include kernel
13
48
 
@@ -15,8 +50,12 @@ class DumbDelegator < ::BasicObject
15
50
  __setobj__(target)
16
51
  end
17
52
 
18
- def respond_to?(method, include_all=false)
19
- __getobj__.respond_to?(method) || super
53
+ def inspect
54
+ "#<#{(class << self; self; end).superclass}:#{object_id} obj: #{__getobj__.inspect}>"
55
+ end
56
+
57
+ def methods(all = true)
58
+ __getobj__.methods(all) | super
20
59
  end
21
60
 
22
61
  def method_missing(method, *args, &block)
@@ -27,19 +66,25 @@ class DumbDelegator < ::BasicObject
27
66
  end
28
67
  end
29
68
 
69
+ def respond_to_missing?(method, include_private = false)
70
+ __getobj__.respond_to?(method, include_private) || super
71
+ end
72
+
73
+ # @return [Object] The object calls are being delegated to
30
74
  def __getobj__
31
75
  @__dumb_target__
32
76
  end
33
77
 
78
+ # @param obj [Object] Change the object delegate to +obj+.
34
79
  def __setobj__(obj)
35
- raise ::ArgumentError, 'Delegation to self is not allowed.' if obj.__id__ == __id__
80
+ raise ::ArgumentError, "Delegation to self is not allowed." if obj.__id__ == __id__
36
81
  @__dumb_target__ = obj
37
82
  end
38
83
 
39
84
  def marshal_dump
40
85
  [
41
86
  :__v1__,
42
- __getobj__
87
+ __getobj__,
43
88
  ]
44
89
  end
45
90
 
@@ -0,0 +1,29 @@
1
+ class DumbDelegator < ::BasicObject
2
+ ##
3
+ # This optional extension enables a Class/Module to support +case+ statements.
4
+ #
5
+ # Specifically, it monkey-patches a Class/Module's +:===+ method to check if the +other+ argument is an instance of the extended Class/Module.
6
+ #
7
+ # @example Extending a Class/Module to handle class equality for a DumbDelegator instance.
8
+ #
9
+ # target = MyAwesomeClass.new
10
+ # dummy = DumbDelegator.new(target)
11
+ #
12
+ # MyAwesomeClass === dummy #=> false
13
+ # DumbDelegator === dummy #=> true
14
+ #
15
+ # MyAwesomeClass.extend(DumbDelegator::TripleEqualExt)
16
+ #
17
+ # MyAwesomeClass === dummy #=> true
18
+ # DumbDelegator === dummy #=> true
19
+ module TripleEqualExt
20
+ # Case equality for the extended Class/Module and then given +other+.
21
+ #
22
+ # @param other [Object] An instance of any Object
23
+ #
24
+ # @return [Boolean] If the +other+ is an instance of the Class/Module.
25
+ def ===(other)
26
+ super || other.is_a?(self)
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  class DumbDelegator < ::BasicObject
2
- VERSION = "0.8.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,6 +1,4 @@
1
- require 'spec_helper'
2
-
3
- describe DumbDelegator do
1
+ RSpec.describe DumbDelegator do
4
2
  subject(:dummy) { Wrapper.new(target) }
5
3
  let(:target) { Target.new }
6
4
 
@@ -55,8 +53,6 @@ describe DumbDelegator do
55
53
  end
56
54
 
57
55
  it "responds to methods defined by child classes" do
58
- expect(target).to receive(:wrapper_method).never
59
-
60
56
  expect(dummy.wrapper_method).to eq("Method only on wrapper.")
61
57
  end
62
58
 
@@ -85,51 +81,76 @@ describe DumbDelegator do
85
81
  end
86
82
 
87
83
  it "delegates object equivalence" do
88
- expect(dummy).to eql(target)
89
- expect(dummy == target).to be true
84
+ aggregate_failures do
85
+ expect(dummy).to eql(target)
86
+ expect(dummy == target).to be true
87
+ end
88
+ end
89
+
90
+ it "delegates #===" do
91
+ expect(dummy === target).to be true
90
92
  end
91
93
 
92
94
  it "delegates class checks" do
93
- expect(dummy.is_a?(Target)).to be(true)
94
- expect(dummy.kind_of?(Target)).to be(true) # rubocop:disable Style/ClassCheck
95
- expect(dummy.instance_of?(Target)).to be(true)
95
+ aggregate_failures do
96
+ expect(dummy.is_a?(Target)).to be(true)
97
+ expect(dummy.kind_of?(Target)).to be(true) # rubocop:disable Style/ClassCheck
98
+ expect(dummy.instance_of?(Target)).to be(true)
99
+ end
96
100
  end
97
101
 
98
- it "delegates ===" do
99
- pending("Implement #=== on DumbDelegator")
100
- expect(dummy === Target).to be true
102
+ it "does not delegate ::=== to the target's class" do
103
+ aggregate_failures do
104
+ expect(Target === dummy).to be false
105
+ expect(DumbDelegator === dummy).to be true
106
+ end
101
107
  end
102
108
 
103
- it 'delegates instance_eval' do
109
+ context "with a Module/Class's ::=== overridden via extension" do
110
+ let(:target) { TargetWithTripleEqualExt.new }
111
+
112
+ class TargetWithTripleEqualExt
113
+ extend DumbDelegator::TripleEqualExt
114
+ end
115
+
116
+ it "delegates ::=== to the target's class" do
117
+ aggregate_failures do
118
+ expect(TargetWithTripleEqualExt === dummy).to be true
119
+ expect(DumbDelegator === dummy).to be true
120
+ end
121
+ end
122
+ end
123
+
124
+ it "delegates instance_eval" do
104
125
  expect(target).to receive(:instance_eval)
105
126
  dummy.instance_eval { true }
106
127
  end
107
128
 
108
- it 'delegates instance_exec' do
129
+ it "delegates instance_exec" do
109
130
  expect(target).to receive(:instance_exec)
110
131
  dummy.instance_exec { true }
111
132
  end
112
133
 
113
- describe '#dup' do
114
- it 'returns a shallow of itself, the delegator (not the underlying object)', :objectspace => true do
134
+ describe "#dup" do
135
+ it "returns a shallow of itself, the delegator (not the underlying object)", objectspace: true do
115
136
  dupped = dummy.dup
116
137
 
117
138
  expect(ObjectSpace.each_object(DumbDelegator).map(&:__id__)).to include dupped.__id__
118
139
  end
119
140
  end
120
141
 
121
- describe '#clone' do
122
- it 'returns a shallow of itself, the delegator (not the underlying object)', :objectspace => true do
142
+ describe "#clone" do
143
+ it "returns a shallow of itself, the delegator (not the underlying object)", objectspace: true do
123
144
  cloned = dummy.clone
124
145
 
125
146
  expect(ObjectSpace.each_object(DumbDelegator).map(&:__id__)).to include cloned.__id__
126
147
  end
127
148
  end
128
149
 
129
- describe 'marshaling' do
150
+ describe "marshaling" do
130
151
  let(:target) { Object.new }
131
152
 
132
- it 'marshals and unmarshals itself, the delegator (not the underlying object)', :objectspace => true do
153
+ it "marshals and unmarshals itself, the delegator (not the underlying object)", objectspace: true do
133
154
  marshaled = Marshal.dump(dummy)
134
155
  unmarshaled = Marshal.load(marshaled)
135
156
 
@@ -137,7 +158,7 @@ describe DumbDelegator do
137
158
  end
138
159
  end
139
160
 
140
- describe '#respond_to?' do
161
+ describe "#respond_to?" do
141
162
  [:equal?, :__id__, :__send__, :dup, :clone, :__getobj__, :__setobj__, :marshal_dump, :marshal_load, :respond_to?].each do |method|
142
163
  it "responds to #{method}" do
143
164
  expect(dummy.respond_to?(method)).to be true
@@ -157,22 +178,53 @@ describe DumbDelegator do
157
178
  end
158
179
  end
159
180
 
160
- describe '#__setobj__' do
161
- it 'resets the target object to a different object' do
162
- expect(target).to receive(:foo).never
163
-
164
- new_target = double
165
- expect(new_target).to receive(:foo)
181
+ describe "#__setobj__" do
182
+ it "resets the target object to a different object" do
183
+ new_target = Target.new.tap do |nt|
184
+ def nt.a_new_thing
185
+ true
186
+ end
187
+ end
166
188
 
167
189
  dummy.__setobj__(new_target)
168
- dummy.foo
190
+ expect(dummy.a_new_thing).to be true
169
191
  end
170
192
 
171
- it 'cannot delegate to itself' do
193
+ it "cannot delegate to itself" do
172
194
  expect {
173
195
  dummy.__setobj__(dummy)
174
- dummy.foo
175
- }.to raise_error(ArgumentError, 'Delegation to self is not allowed.')
196
+ dummy.common_method
197
+ }.to raise_error(ArgumentError, "Delegation to self is not allowed.")
198
+ end
199
+ end
200
+
201
+ describe "introspection capabilities" do
202
+ it "provides a human-friendly representation of the delegator and wrapped object" do
203
+ expect(dummy.inspect).to match(/#<Wrapper:\w+ obj: .+Target.+>/)
204
+ end
205
+
206
+ it "reports methods defined on the target" do
207
+ expect(dummy.methods).to include(:target_method, :common_method)
208
+ end
209
+
210
+ it "reports methods defined on the wrapper" do
211
+ expect(dummy.methods).to include(:wrapper_method, :common_method)
212
+ end
213
+
214
+ it "looks up a named method on the target" do
215
+ method = dummy.method(:target_method)
216
+ aggregate_failures do
217
+ expect(method).not_to be_nil
218
+ expect(method.receiver).to eq(target)
219
+ end
220
+ end
221
+
222
+ it "looks up a named method on the wrapper" do
223
+ method = dummy.method(:wrapper_method)
224
+ aggregate_failures do
225
+ expect(method).not_to be_nil
226
+ expect(method.receiver).to equal(dummy)
227
+ end
176
228
  end
177
229
  end
178
230
  end
@@ -1,11 +1,38 @@
1
- if ENV["CODECLIMATE_REPO_TOKEN"]
1
+ if ENV["CC_TEST_REPORTER_ID"] || ENV["COVERAGE"]
2
2
  require "simplecov"
3
3
  SimpleCov.start
4
4
  end
5
5
 
6
- require File.expand_path('../lib/dumb_delegator', File.dirname(__FILE__))
6
+ require "pry"
7
+ require File.expand_path("../lib/dumb_delegator", File.dirname(__FILE__))
7
8
 
8
9
  RSpec.configure do |config|
9
- config.run_all_when_everything_filtered = true
10
- config.filter_run :focus
10
+ config.expect_with :rspec do |expectations|
11
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
12
+ end
13
+
14
+ config.mock_with :rspec do |mocks|
15
+ mocks.verify_partial_doubles = true
16
+ end
17
+
18
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
19
+ # have no way to turn it off -- the option exists only for backwards
20
+ # compatibility in RSpec 3). It causes shared context metadata to be
21
+ # inherited by the metadata hash of host groups and examples, rather than
22
+ # triggering implicit auto-inclusion in groups with matching metadata.
23
+ config.shared_context_metadata_behavior = :apply_to_host_groups
24
+
25
+ config.filter_run_when_matching :focus
26
+ config.example_status_persistence_file_path = "spec/rspec-status.txt"
27
+ config.disable_monkey_patching!
28
+ config.warnings = true
29
+
30
+ if config.files_to_run.one?
31
+ # Use the documentation formatter for detailed output,
32
+ # unless a formatter has already been configured
33
+ # (e.g. via a command-line flag).
34
+ config.default_formatter = "doc"
35
+ end
36
+ config.order = :random
37
+ Kernel.srand config.seed
11
38
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dumb_delegator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Lindeman
@@ -9,37 +9,54 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-01-26 00:00:00.000000000 Z
12
+ date: 2020-01-28 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: pry
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: rake
16
30
  requirement: !ruby/object:Gem::Requirement
17
31
  requirements:
18
32
  - - "~>"
19
33
  - !ruby/object:Gem::Version
20
- version: '10.0'
34
+ version: '13.0'
21
35
  type: :development
22
36
  prerelease: false
23
37
  version_requirements: !ruby/object:Gem::Requirement
24
38
  requirements:
25
39
  - - "~>"
26
40
  - !ruby/object:Gem::Version
27
- version: '10.0'
41
+ version: '13.0'
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: rspec
30
44
  requirement: !ruby/object:Gem::Requirement
31
45
  requirements:
32
46
  - - "~>"
33
47
  - !ruby/object:Gem::Version
34
- version: '3.4'
48
+ version: '3.9'
35
49
  type: :development
36
50
  prerelease: false
37
51
  version_requirements: !ruby/object:Gem::Requirement
38
52
  requirements:
39
53
  - - "~>"
40
54
  - !ruby/object:Gem::Version
41
- version: '3.4'
42
- description: Delegator class that delegates ALL the things
55
+ version: '3.9'
56
+ description: |
57
+ Delegator and SimpleDelegator in Ruby's stdlib are useful, but they pull in most of Kernel.
58
+ This is not appropriate for many uses; for instance, delegation to Rails Models.
59
+ DumbDelegator, on the other hand, delegates nearly everything to the wrapped object.
43
60
  email:
44
61
  - alindeman@gmail.com
45
62
  - steven@harmanly.com
@@ -57,12 +74,17 @@ files:
57
74
  - Rakefile
58
75
  - dumb_delegator.gemspec
59
76
  - lib/dumb_delegator.rb
77
+ - lib/dumb_delegator/triple_equal_ext.rb
60
78
  - lib/dumb_delegator/version.rb
61
79
  - spec/dumb_delegator_spec.rb
62
80
  - spec/spec_helper.rb
63
81
  homepage: https://github.com/stevenharman/dumb_delegator
64
- licenses: []
65
- metadata: {}
82
+ licenses:
83
+ - MIT
84
+ metadata:
85
+ changelog_uri: https://github.com/stevenharman/dumb_delegator/blob/master/CHANGELOG.md
86
+ documentation_uri: https://rubydoc.info/gems/dumb_delegator
87
+ source_code_uri: https://github.com/stevenharman/dumb_delegator
66
88
  post_install_message:
67
89
  rdoc_options: []
68
90
  require_paths:
@@ -71,19 +93,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
71
93
  requirements:
72
94
  - - ">="
73
95
  - !ruby/object:Gem::Version
74
- version: 1.9.3
96
+ version: 2.4.0
75
97
  required_rubygems_version: !ruby/object:Gem::Requirement
76
98
  requirements:
77
99
  - - ">="
78
100
  - !ruby/object:Gem::Version
79
101
  version: '0'
80
102
  requirements: []
81
- rubygems_version: 3.0.6
103
+ rubygems_version: 3.0.3
82
104
  signing_key:
83
105
  specification_version: 4
84
- summary: Delegator and SimpleDelegator in Ruby's stdlib are somewhat useful, but they
85
- pull in most of Kernel. This is not appropriate for many uses; for instance, delegation
86
- to Rails models.
106
+ summary: Delegator class that delegates ALL the things
87
107
  test_files:
88
108
  - spec/dumb_delegator_spec.rb
89
109
  - spec/spec_helper.rb