methodobject 0.1.0 → 0.2.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/README.md +14 -5
- data/lib/method_object.rb +15 -5
- data/lib/method_object/version.rb +1 -1
- data/methodobject.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10216ed93b5d15e346c868027b9521f22ca0a248
|
4
|
+
data.tar.gz: 7712785d34e678ac89b433c83704b3f899a81611
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5c4c44ca7934c5df3f44f1dd56db376d0f8566d247f3e8811eccfbcd465a50f4bc9fe5d33d683f1400d5d166c34df67edf21accffd1a18253910aa2c2d0c19b
|
7
|
+
data.tar.gz: f510bb02516ec64eed92e041640a4193485258993543d36c9633820dd9e56f5a906160e6aa0abcb9b8c60ad4d4c3dd12701866752be023363584c8ae26efb790
|
data/README.md
CHANGED
@@ -11,9 +11,9 @@ a common pattern used to ease the extraction of complex methods from other class
|
|
11
11
|
|
12
12
|
The __method object pattern__ is advisable when a method is too long and difficult to separate due to tangled masses of local variables that are hard to isolate from each other: the solution is to extract the entire method into a separate class and turn its local variables into fields of the class; this allows isolating the problem at the class level and it paves the way for splitting a large and unwieldy method into smaller ones that would not fit with the purpose of the original class anyway.
|
13
13
|
|
14
|
-
This gem also provides a uniform interface to write __service objects__, that is a common way to extract common operations from models and controllers in Rails application. Borrowing the design from [an article](http://brewhouse.io/blog/2014/04/30/gourmet-service-objects.html) on what the author defines as _"Gourmet Service Object"_, it provides some plumbing to implement such a pattern, with objects that expose
|
14
|
+
This gem also provides a uniform interface to write __service objects__, that is a common way to extract common operations from models and controllers in Rails application. Borrowing the design from [an article](http://brewhouse.io/blog/2014/04/30/gourmet-service-objects.html) on what the author defines as _"Gourmet Service Object"_, it provides some plumbing to implement such a pattern, with objects that expose an operation as their entry-point.
|
15
15
|
|
16
|
-
The interface exposed by a MethodObject is similar to the one of a _proc_/_lambda_, exposing a `call` method both at class and instance level and a convenience `to_proc` method to convert it to a Proc. Other neat features include optional type checking for the arguments and inheritance between
|
16
|
+
The interface exposed by a MethodObject is similar to the one of a _proc_/_lambda_, exposing a `call` method both at class and instance level and a convenience `to_proc` method to convert it to a Proc. Other neat features include optional type checking for the arguments and inheritance between method objects.
|
17
17
|
|
18
18
|
## Installation
|
19
19
|
|
@@ -38,7 +38,7 @@ Or install it yourself as:
|
|
38
38
|
```ruby
|
39
39
|
class ComplexCalculation < MethodObject
|
40
40
|
# Type checking is optional. If omitted, anything is accepted.
|
41
|
-
# Type checking can also done with a proc or anything that responds to #===
|
41
|
+
# Type checking can also be done with a proc or anything that responds to #===
|
42
42
|
# e.g. parameter :start_number, ->(p) { p.respond_to?(:to_i) }
|
43
43
|
parameter :start_number, Integer
|
44
44
|
|
@@ -60,14 +60,14 @@ class ComplexCalculation < MethodObject
|
|
60
60
|
|
61
61
|
def perform_complex_calculation
|
62
62
|
# The arguments are available as accessors
|
63
|
-
start_number +
|
63
|
+
start_number + end_number + @magic_number
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
67
|
# The class-method version of `call` accepts the arguments as named parameters
|
68
68
|
ComplexCalculation.call(start_number: 1, end_number: 3) #=> 46
|
69
69
|
ComplexCalculation.call(start_number: 1) #=> 45
|
70
|
-
ComplexCalculation.call(end_number: 3) #=> raise
|
70
|
+
ComplexCalculation.call(end_number: 3) #=> raise MethodObject::UnknownParameter
|
71
71
|
|
72
72
|
# `call` can also be omitted, as per usual Ruby semantics
|
73
73
|
ComplexCalculation.(start_number: 1)
|
@@ -112,6 +112,15 @@ say_my_name(&NameSayer)
|
|
112
112
|
# - You're goddamn right!
|
113
113
|
```
|
114
114
|
|
115
|
+
### Errors
|
116
|
+
|
117
|
+
* `MethodObject::ParameterRequired` is raised when a required parameter is not set on `call`
|
118
|
+
* `MethodObject::InvalidParameterValue` is raised when a given value's type does not match the type specified for the parameter
|
119
|
+
* `MethodObject::UnknownParameter` is raised when using an undefined parameter
|
120
|
+
|
121
|
+
All these classes inherit from `MethodObject::ParameterError`, which inherits from `ArgumentError`.
|
122
|
+
|
123
|
+
|
115
124
|
## Development
|
116
125
|
|
117
126
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/method_object.rb
CHANGED
@@ -31,7 +31,7 @@ require 'method_object/parameter'
|
|
31
31
|
#
|
32
32
|
# ComplexCalculation.call(start_number: 1, end_number: 3) #=> 46
|
33
33
|
# ComplexCalculation.call(start_number: 1) #=> 45
|
34
|
-
# ComplexCalculation.call(end_number: 3) #=> raise
|
34
|
+
# ComplexCalculation.call(end_number: 3) #=> raise MethodObject::UnknownParameter
|
35
35
|
#
|
36
36
|
# calculation = ComplexCalculation.new(end_number: 3)
|
37
37
|
# calculation.start_number = 1
|
@@ -60,6 +60,11 @@ require 'method_object/parameter'
|
|
60
60
|
# # - You're Heisenberg
|
61
61
|
# # - You're goddamn right!
|
62
62
|
class MethodObject
|
63
|
+
ParameterError = Class.new(::ArgumentError)
|
64
|
+
ParameterRequired = Class.new(ParameterError)
|
65
|
+
InvalidParameterValue = Class.new(ParameterError)
|
66
|
+
UnknownParameter = Class.new(ParameterError)
|
67
|
+
|
63
68
|
class << self
|
64
69
|
# Calls the MethodObject with the given arguments.
|
65
70
|
#
|
@@ -95,7 +100,7 @@ class MethodObject
|
|
95
100
|
parameters << arg
|
96
101
|
|
97
102
|
define_method("#{name}=") do |value|
|
98
|
-
raise
|
103
|
+
raise InvalidParameterValue, "Expected a #{type} for #{name}, #{value.class} received" unless arg.acceptable?(value)
|
99
104
|
@monitor.synchronize { instance_variable_set("@#{name}", value) }
|
100
105
|
end
|
101
106
|
|
@@ -140,7 +145,12 @@ class MethodObject
|
|
140
145
|
|
141
146
|
@monitor = Monitor.new
|
142
147
|
|
143
|
-
args.each
|
148
|
+
args.each do |k, v|
|
149
|
+
method = "#{k}="
|
150
|
+
raise UnknownParameter, "Parameter #{k} unknown" unless respond_to?(method)
|
151
|
+
public_send(method, v)
|
152
|
+
end
|
153
|
+
|
144
154
|
self.class.send(:parameters)
|
145
155
|
.reject { |p| args.keys.map(&:to_sym).include?(p.name) }
|
146
156
|
.select(&:default?)
|
@@ -180,14 +190,14 @@ class MethodObject
|
|
180
190
|
|
181
191
|
private
|
182
192
|
|
183
|
-
# @raise [
|
193
|
+
# @raise [ParameterRequired]
|
184
194
|
def assert_required_arguments!
|
185
195
|
missing_params =
|
186
196
|
self.class.send(:parameters)
|
187
197
|
.select { |p| !p.default? && !public_send("#{p.name}?") }
|
188
198
|
.map(&:name)
|
189
199
|
|
190
|
-
raise
|
200
|
+
raise ParameterRequired, "Missing required arguments: #{missing_params.join(', ')}" \
|
191
201
|
unless missing_params.empty?
|
192
202
|
end
|
193
203
|
end
|
data/methodobject.gemspec
CHANGED
@@ -29,5 +29,5 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_development_dependency "rake", "~> 10.0"
|
30
30
|
spec.add_development_dependency "rspec", "~> 3.0"
|
31
31
|
spec.add_development_dependency "pry"
|
32
|
-
spec.add_development_dependency "
|
32
|
+
spec.add_development_dependency "coveralls"
|
33
33
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: methodobject
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michele Piccirillo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: coveralls
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -125,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
125
|
version: '0'
|
126
126
|
requirements: []
|
127
127
|
rubyforge_project:
|
128
|
-
rubygems_version: 2.
|
128
|
+
rubygems_version: 2.6.11
|
129
129
|
signing_key:
|
130
130
|
specification_version: 4
|
131
131
|
summary: Method Object pattern in Ruby for your service objects
|