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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8f916404cf4e974217978e9ae9059d1096fab845
4
- data.tar.gz: 770f10363861e160a56f3762fe65478b3be6d114
3
+ metadata.gz: 10216ed93b5d15e346c868027b9521f22ca0a248
4
+ data.tar.gz: 7712785d34e678ac89b433c83704b3f899a81611
5
5
  SHA512:
6
- metadata.gz: 4c32191104f627bfef8a295790497146ec76788fac297ae4ed02a1f87e8dfab25cfe79d15758466690ca2bca710d841edb2cc954410f6e9b699d016528c076bd
7
- data.tar.gz: 95ada31f90716259011285e221d67e7441bf8b8e316a1e83466158632c4cc374d4c5ab4422856a3d4da7ef7bcc0bee6f73ecd3e6c113bb4fe27834e1cea9242b
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 a operation as their entry-point.
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 MO's.
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 + second_number + @magic_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 ArgumentError
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.
@@ -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 ArgumentError
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 ArgumentError, "Expected a #{type} for #{name}, #{value.class} received" unless arg.acceptable?(value)
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 { |k, v| public_send("#{k}=", v) }
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 [ArgumentError]
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 ArgumentError, "Missing required arguments: #{missing_params.join(', ')}" \
200
+ raise ParameterRequired, "Missing required arguments: #{missing_params.join(', ')}" \
191
201
  unless missing_params.empty?
192
202
  end
193
203
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class MethodObject
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -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 "simplecov"
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.1.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-04-27 00:00:00.000000000 Z
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: simplecov
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.5.1
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