method_man 1.0.0 → 2.1.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/.rubocop.yml +30 -0
- data/.ruby-version +2 -1
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -0
- data/README.md +29 -6
- data/Rakefile +2 -1
- data/lib/method_object/version.rb +2 -1
- data/lib/method_object.rb +152 -24
- data/method_man.gemspec +8 -5
- data/spec/method_man_spec.rb +168 -21
- data/spec/spec_helper.rb +1 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0ddc3147244cc0dc922a4ebc1aa9512efedfecf
|
4
|
+
data.tar.gz: 5139372bb0da36319b9cd7a3338da3dd507e1724
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71436d2cf1e9b82acf277477ae6009d1e6d05288f93a848cb8055dfa8b6169c27fdc615ed5ca3ab710b4241f45f658aa0ec5989e2f42380f7b1df92893453a21
|
7
|
+
data.tar.gz: 7cf527f78e56ed58fa9e64f7e0149f006fc398fbb81309f4315fe790288075ed07cd600c623f987daafdffc12dbb8fb127bc5c320a9b0bd83075d218b2eb45d7
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- spec/*
|
4
|
+
TargetRubyVersion: 2.4
|
5
|
+
|
6
|
+
# We don't care about method length, since we check method cyclomatic
|
7
|
+
# complexity.
|
8
|
+
Metrics/MethodLength:
|
9
|
+
Enabled: false
|
10
|
+
Metrics/ClassLength:
|
11
|
+
Enabled: false
|
12
|
+
Metrics/ModuleLength:
|
13
|
+
Enabled: false
|
14
|
+
|
15
|
+
# Trailing commas make for clearer diffs because the last line won't appear
|
16
|
+
# to have been changed, as it would if it lacked a comma and had one added.
|
17
|
+
Style/TrailingCommaInArguments:
|
18
|
+
EnforcedStyleForMultiline: comma
|
19
|
+
Style/TrailingCommaInLiteral:
|
20
|
+
EnforcedStyleForMultiline: comma
|
21
|
+
|
22
|
+
# Cop supports --auto-correct.
|
23
|
+
# Configuration parameters: PreferredDelimiters.
|
24
|
+
Style/PercentLiteralDelimiters:
|
25
|
+
PreferredDelimiters:
|
26
|
+
# Using `[]` for string arrays instead of `()`, since normal arrays are
|
27
|
+
# indicated with `[]` not `()`.
|
28
|
+
'%w': '[]'
|
29
|
+
'%W': '[]'
|
30
|
+
'%i': '[]'
|
data/.ruby-version
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
2.
|
1
|
+
2.4.0
|
2
|
+
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Change log
|
2
|
+
|
3
|
+
## 2.0.0
|
4
|
+
Convert MethodObject to use inheritance and a class method for dynamic setup of class internals
|
5
|
+
- Enables code editors to find declaration of MethodObject
|
6
|
+
- Allows constants to be nested whereas previous implementation was based on a Struct which could not contain constants.
|
7
|
+
|
8
|
+
## 2.1.0
|
9
|
+
Allow automatic delegation inspired by Golang's embedding.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
Defines a MethodObject class which facilitates basic setup for Kent Beck's "[method object](http://c2.com/cgi/wiki?MethodObject)".
|
4
4
|
|
5
|
-
The MethodObject class is largely based on a Ruby Struct, but with a few additional features:
|
6
|
-
|
7
5
|
* Facilitates basic method object pattern setup. You only need to supply an instance `call` method.
|
8
6
|
* Accepts a list of arguments which are mapped to required keyword arguments.
|
9
7
|
* Disallows calling `new` on the resulting MethodObject class instance.
|
@@ -22,13 +20,13 @@ gem 'method_man', require: 'method_object'
|
|
22
20
|
```ruby
|
23
21
|
require 'method_object'
|
24
22
|
|
25
|
-
MakeArbitraryArray
|
23
|
+
class MakeArbitraryArray < MethodObject
|
24
|
+
attrs(:first_name, :last_name, :message)
|
25
|
+
|
26
26
|
def call
|
27
27
|
[fullname, message, 42]
|
28
28
|
end
|
29
29
|
|
30
|
-
private
|
31
|
-
|
32
30
|
def fullname
|
33
31
|
"#{first_name} #{last_name}"
|
34
32
|
end
|
@@ -39,5 +37,30 @@ gem 'method_man', require: 'method_object'
|
|
39
37
|
last_name: 'Smith',
|
40
38
|
message: 'Hi',
|
41
39
|
)
|
42
|
-
=> [
|
40
|
+
=> ['John Smith', 'Hi', 42]
|
41
|
+
```
|
42
|
+
|
43
|
+
Also allows automatic delegation inspired by Go's
|
44
|
+
[delegation](https://nathany.com/good/).
|
45
|
+
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'method_object'
|
49
|
+
|
50
|
+
class MakeArbitraryArray < MethodObject
|
51
|
+
attrs(:company)
|
52
|
+
|
53
|
+
def call
|
54
|
+
[
|
55
|
+
company.name,
|
56
|
+
name, # Automatic delegation since company has a `name` method
|
57
|
+
company_name, # Automatic delegation with prefix
|
58
|
+
]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
company = Company.new(name: 'Tyrell Corporation')
|
63
|
+
|
64
|
+
MakeArbitraryArray.call(company: company)
|
65
|
+
=> ['Tyrell Corporation', 'Tyrell Corporation', 'Tyrell Corporation']
|
43
66
|
```
|
data/Rakefile
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'bundler/gem_tasks'
|
data/lib/method_object.rb
CHANGED
@@ -1,42 +1,170 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'method_object/version'
|
2
3
|
|
4
|
+
# See gemspec for description
|
3
5
|
class MethodObject
|
4
|
-
|
5
|
-
|
6
|
-
|
6
|
+
class AmbigousMethodError < NameError; end
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def attrs(*attributes)
|
10
|
+
@attributes = attributes
|
11
|
+
Setup.call(attributes: attributes, subclass: self)
|
12
|
+
end
|
7
13
|
|
8
|
-
|
9
|
-
|
10
|
-
|
14
|
+
def call(**args)
|
15
|
+
new(args).call
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader(:attributes)
|
19
|
+
|
20
|
+
private(:new)
|
11
21
|
end
|
12
22
|
|
23
|
+
def initialize(_); end
|
24
|
+
|
13
25
|
def call
|
14
|
-
|
15
|
-
|
26
|
+
raise NotImplementedError, 'Define the call method'
|
27
|
+
end
|
16
28
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
29
|
+
def method_missing(name, *args, &block)
|
30
|
+
candidates = candidates_for_method_missing(name)
|
31
|
+
case candidates.length
|
32
|
+
when 0
|
33
|
+
super
|
34
|
+
when 1
|
35
|
+
define_and_call_new_method(candidates.first)
|
36
|
+
else
|
37
|
+
handle_ambiguous_missing_method(candidates, name)
|
24
38
|
end
|
25
39
|
end
|
26
40
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
41
|
+
def respond_to_missing?(name)
|
42
|
+
candidates_for_method_missing(name).length == 1
|
43
|
+
end
|
44
|
+
|
45
|
+
def candidates_for_method_missing(method_name)
|
46
|
+
potential_candidates =
|
47
|
+
self.class.attributes.map do |attribute|
|
48
|
+
PotentialDelegator.new(attribute, send(attribute), method_name)
|
49
|
+
end +
|
50
|
+
self.class.attributes.map do |attribute|
|
51
|
+
PotentialDelegatorWithPrefix.new(
|
52
|
+
attribute,
|
53
|
+
send(attribute),
|
54
|
+
method_name,
|
55
|
+
)
|
31
56
|
end
|
32
|
-
|
57
|
+
potential_candidates.select(&:candidate?)
|
33
58
|
end
|
34
59
|
|
35
|
-
def
|
36
|
-
|
60
|
+
def define_and_call_new_method(candidate)
|
61
|
+
self.class.class_eval(
|
62
|
+
<<-RUBY
|
63
|
+
def #{candidate.delegated_method}
|
64
|
+
#{candidate.attribute}.#{candidate.method_to_call_on_delegate}
|
65
|
+
end
|
66
|
+
RUBY
|
67
|
+
)
|
68
|
+
send(candidate.delegated_method)
|
37
69
|
end
|
38
70
|
|
39
|
-
def
|
40
|
-
|
71
|
+
def handle_ambiguous_missing_method(candidates, method_name)
|
72
|
+
raise(
|
73
|
+
AmbigousMethodError,
|
74
|
+
"#{method_name} is ambiguous: " +
|
75
|
+
candidates
|
76
|
+
.map do |candidate|
|
77
|
+
"#{candidate.attribute}.#{candidate.method_to_call_on_delegate}"
|
78
|
+
end
|
79
|
+
.join(', '),
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Represents a possible match of the form:
|
84
|
+
# some_method => my_attribute.some_method
|
85
|
+
PotentialDelegator = Struct.new(:attribute, :object, :delegated_method) do
|
86
|
+
def candidate?
|
87
|
+
object.respond_to?(delegated_method)
|
88
|
+
end
|
89
|
+
|
90
|
+
def call
|
91
|
+
object.public_send(delegated_method)
|
92
|
+
end
|
93
|
+
|
94
|
+
alias_method :method_to_call_on_delegate, :delegated_method
|
95
|
+
end
|
96
|
+
|
97
|
+
# Represents a possible match of the form:
|
98
|
+
# my_attribute_some_method => my_attribute.some_method
|
99
|
+
PotentialDelegatorWithPrefix =
|
100
|
+
Struct.new(:attribute, :object, :delegated_method) do
|
101
|
+
def candidate?
|
102
|
+
name_matches? && object.respond_to?(method_to_call_on_delegate)
|
103
|
+
end
|
104
|
+
|
105
|
+
def call
|
106
|
+
object.public_send(method_to_call_on_delegate)
|
107
|
+
end
|
108
|
+
|
109
|
+
def method_to_call_on_delegate
|
110
|
+
delegated_method.to_s.sub(prefix, '')
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def name_matches?
|
116
|
+
delegated_method.to_s.start_with?(prefix)
|
117
|
+
end
|
118
|
+
|
119
|
+
def prefix
|
120
|
+
"#{attribute}_"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Dynamically defines custom attr_readers and initializer
|
125
|
+
class Setup < SimpleDelegator
|
126
|
+
def self.call(attributes:, subclass:)
|
127
|
+
new(attributes, subclass).call
|
128
|
+
end
|
129
|
+
|
130
|
+
attr_accessor(:attributes)
|
131
|
+
|
132
|
+
def initialize(attributes, subclass)
|
133
|
+
self.attributes = attributes
|
134
|
+
super(subclass)
|
135
|
+
end
|
136
|
+
|
137
|
+
def call
|
138
|
+
define_attr_readers
|
139
|
+
define_initializer
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
def define_attr_readers
|
145
|
+
__getobj__.send(:attr_reader, *attributes)
|
146
|
+
end
|
147
|
+
|
148
|
+
def attr_accessor(attribute)
|
149
|
+
super
|
150
|
+
end
|
151
|
+
|
152
|
+
def define_initializer
|
153
|
+
class_eval(
|
154
|
+
<<-RUBY
|
155
|
+
def initialize(#{required_keyword_args_string})
|
156
|
+
#{assignments}
|
157
|
+
end
|
158
|
+
RUBY
|
159
|
+
)
|
160
|
+
end
|
161
|
+
|
162
|
+
def required_keyword_args_string
|
163
|
+
attributes.map { |arg| "#{arg}:" }.join(',')
|
164
|
+
end
|
165
|
+
|
166
|
+
def assignments
|
167
|
+
attributes.map { |attribute| "@#{attribute} = #{attribute}\n" }.join
|
168
|
+
end
|
41
169
|
end
|
42
170
|
end
|
data/method_man.gemspec
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'method_object/version'
|
@@ -7,16 +8,18 @@ Gem::Specification.new do |spec|
|
|
7
8
|
spec.name = 'method_man'
|
8
9
|
spec.version = MethodObject::VERSION
|
9
10
|
spec.authors = ['Clay Shentrup']
|
10
|
-
spec.email = %w
|
11
|
-
spec.summary =
|
12
|
-
|
11
|
+
spec.email = %w[cshentrup@gmail.com]
|
12
|
+
spec.summary = 'Provides a MethodObject class which implements Kent' +
|
13
|
+
%q(Beck's "method object" pattern.)
|
14
|
+
spec.description = 'Provides a MethodObject class which implements Kent' +
|
15
|
+
%q(Beck's "method object" pattern.)
|
13
16
|
spec.homepage = 'https://github.com/brokenladder/method_man'
|
14
17
|
spec.license = 'MIT'
|
15
18
|
|
16
|
-
spec.files = `git ls-files`.split(
|
19
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
20
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
21
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = %w
|
22
|
+
spec.require_paths = %w[lib]
|
20
23
|
|
21
24
|
spec.required_ruby_version = '>= 2.1'
|
22
25
|
|
data/spec/method_man_spec.rb
CHANGED
@@ -1,38 +1,185 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'method_object'
|
2
3
|
|
3
4
|
describe MethodObject do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
it 'makes new a private class method' do
|
6
|
+
expect { subject.new }.to raise_error(NoMethodError)
|
7
|
+
end
|
8
|
+
|
9
|
+
context 'without attrs' do
|
10
|
+
subject do
|
11
|
+
Class.new(described_class) do
|
12
|
+
def call
|
13
|
+
true
|
14
|
+
end
|
8
15
|
end
|
9
16
|
end
|
10
|
-
end
|
11
17
|
|
12
|
-
|
13
|
-
let(:value_two) { 2 }
|
14
|
-
let(:actual_result) do
|
15
|
-
subject.call(value_one: value_one, value_two: value_two)
|
18
|
+
specify { expect(subject.call).to be(true) }
|
16
19
|
end
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
context 'with attrs' do
|
22
|
+
subject do
|
23
|
+
Class.new(described_class) do
|
24
|
+
attrs(:company, :user)
|
21
25
|
|
22
|
-
|
23
|
-
expect { subject.call }.to raise_error ArgumentError
|
24
|
-
end
|
26
|
+
@sent_messages = []
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
+
def self.sent_messages
|
29
|
+
@sent_messages
|
30
|
+
end
|
31
|
+
|
32
|
+
def call
|
33
|
+
{
|
34
|
+
address: address,
|
35
|
+
respond_to_address: respond_to_missing?(:address),
|
36
|
+
company_address: company_address,
|
37
|
+
respond_to_company_address: respond_to_missing?(:company_address),
|
38
|
+
company: company,
|
39
|
+
respond_to_name: respond_to_missing?(:name),
|
40
|
+
company_name: company_name,
|
41
|
+
respond_to_company_name: respond_to_missing?(:company_name),
|
42
|
+
user: user,
|
43
|
+
user_name: user_name,
|
44
|
+
respond_to_user_name: respond_to_missing?(:user_name),
|
45
|
+
respond_to_missing: respond_to_missing?(:undefined_method),
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
let(:company) do
|
52
|
+
double('company', address: company_address, name: company_name)
|
53
|
+
end
|
54
|
+
let(:company_address) { '101 Minitru Lane' }
|
55
|
+
let(:company_name) { 'Periscope Data' }
|
56
|
+
let(:user) { double('user', name: user_name) }
|
57
|
+
let(:user_name) { 'Woody' }
|
58
|
+
|
59
|
+
let(:result) { subject.call(company: company, user: user) }
|
60
|
+
|
61
|
+
specify do
|
62
|
+
expect(result).to eq(
|
63
|
+
address: company_address,
|
64
|
+
respond_to_address: true,
|
65
|
+
company_address: company_address,
|
66
|
+
respond_to_company_address: true,
|
67
|
+
company: company,
|
68
|
+
respond_to_name: false,
|
69
|
+
company_name: company_name,
|
70
|
+
respond_to_company_name: true,
|
71
|
+
user: user,
|
72
|
+
user_name: user_name,
|
73
|
+
respond_to_user_name: true,
|
74
|
+
respond_to_missing: false,
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'uses required keyword arguments' do
|
79
|
+
expect { subject.call }.to raise_error(ArgumentError)
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'with ambiguous method call' do
|
83
|
+
subject do
|
84
|
+
Class.new(described_class) do
|
85
|
+
attrs(:company, :user)
|
86
|
+
|
87
|
+
def call
|
88
|
+
name
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
specify do
|
94
|
+
expect { result }.to raise_error(
|
95
|
+
MethodObject::AmbigousMethodError,
|
96
|
+
a_string_including('company.name, user.name'),
|
97
|
+
)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'ambigous method call due to delegation' do
|
102
|
+
subject do
|
103
|
+
Class.new(described_class) do
|
104
|
+
attrs(:company, :user)
|
105
|
+
|
106
|
+
def call
|
107
|
+
company_address
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
let(:user) { double('user', company_address: nil) }
|
113
|
+
|
114
|
+
specify do
|
115
|
+
expect { result }.to raise_error(
|
116
|
+
MethodObject::AmbigousMethodError,
|
117
|
+
a_string_including('user.company_address, company.address'),
|
118
|
+
)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe 'respecting method privacy' do
|
123
|
+
let(:subject) do
|
124
|
+
Class.new(described_class) do
|
125
|
+
attrs(:diary)
|
126
|
+
|
127
|
+
def call
|
128
|
+
diary_contents
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
let(:diary) do
|
133
|
+
Module.new do
|
134
|
+
def self.contents; end
|
135
|
+
|
136
|
+
private_class_method(:contents)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
specify do
|
141
|
+
expect { subject.call(diary: diary) }.to raise_error(StandardError)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe '"memoizes" method calls' do
|
146
|
+
subject do
|
147
|
+
Class.new(described_class) do
|
148
|
+
attrs(:company)
|
149
|
+
@sent_messages = []
|
150
|
+
|
151
|
+
def self.sent_messages
|
152
|
+
@sent_messages
|
153
|
+
end
|
154
|
+
|
155
|
+
def call
|
156
|
+
[name, name]
|
157
|
+
end
|
158
|
+
|
159
|
+
# Ensure it defines resolved methods
|
160
|
+
def method_missing(method, *_args)
|
161
|
+
if self.class.sent_messages.include?(method)
|
162
|
+
raise 'method not memoized'
|
163
|
+
end
|
164
|
+
self.class.sent_messages << method
|
165
|
+
super
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
specify do
|
171
|
+
expect(subject.call(company: company)).to eq([company_name, company_name])
|
172
|
+
end
|
173
|
+
end
|
28
174
|
end
|
29
175
|
|
30
176
|
context 'without a provided instance call method' do
|
31
|
-
subject
|
177
|
+
subject do
|
178
|
+
Class.new(described_class) { attrs(:user_1_age) }
|
179
|
+
end
|
32
180
|
|
33
|
-
|
34
|
-
expect { subject.call(
|
35
|
-
.to raise_error NotImplementedError
|
181
|
+
specify do
|
182
|
+
expect { subject.call(user_1_age: user_1_age) }.to raise_error(NameError)
|
36
183
|
end
|
37
184
|
end
|
38
185
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: method_man
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Clay Shentrup
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,7 +52,7 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.2'
|
55
|
-
description: Provides a MethodObject class which implements
|
55
|
+
description: Provides a MethodObject class which implements KentBeck's "method object"
|
56
56
|
pattern.
|
57
57
|
email:
|
58
58
|
- cshentrup@gmail.com
|
@@ -62,7 +62,9 @@ extra_rdoc_files: []
|
|
62
62
|
files:
|
63
63
|
- ".gitignore"
|
64
64
|
- ".rspec"
|
65
|
+
- ".rubocop.yml"
|
65
66
|
- ".ruby-version"
|
67
|
+
- CHANGELOG.md
|
66
68
|
- Gemfile
|
67
69
|
- LICENSE
|
68
70
|
- LICENSE.txt
|
@@ -93,10 +95,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
95
|
version: '0'
|
94
96
|
requirements: []
|
95
97
|
rubyforge_project:
|
96
|
-
rubygems_version: 2.
|
98
|
+
rubygems_version: 2.6.8
|
97
99
|
signing_key:
|
98
100
|
specification_version: 4
|
99
|
-
summary: Provides a MethodObject class which implements
|
101
|
+
summary: Provides a MethodObject class which implements KentBeck's "method object"
|
100
102
|
pattern.
|
101
103
|
test_files:
|
102
104
|
- spec/method_man_spec.rb
|