marameters 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
- checksums.yaml.gz.sig +0 -0
- data/README.adoc +130 -6
- data/lib/marameters/builder.rb +28 -0
- data/lib/marameters/defaulter.rb +29 -0
- data/lib/marameters/signature.rb +23 -0
- data/marameters.gemspec +2 -2
- data.tar.gz.sig +0 -0
- metadata +7 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a3daee40e52b7df55680618be8c5a37a6a62c3ca7f62b88128fbc724f4222c50
|
|
4
|
+
data.tar.gz: 3b4d527a40fc8ed6500faea3e6676b45be484a2fb9288b5e79ee38684ac0bec0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 459d04fcc654dcf3ef58d23dfaaff01f5df52e0ffbb8d670cb0d1a9f59f10f91d0e9ff424e5871c9e892a1ba7f2b4cbdb236a287e3b3ffbdf32a1e56de9b5f97
|
|
7
|
+
data.tar.gz: 92df818d39aeacd231721b69299e0e23705b0f889db54360fefd0f269355fcbf40499b62c59bfc30a22b99dac39874b8a168c381e825ae4b2891a18b6fd9f53f
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/README.adoc
CHANGED
|
@@ -14,7 +14,8 @@ difference between a method's parameters and arguments is:
|
|
|
14
14
|
Example: `demo 1, two: 2`.
|
|
15
15
|
|
|
16
16
|
This gem will help you debug methods or -- more importantly -- aid your workflow when
|
|
17
|
-
metaprogramming
|
|
17
|
+
metaprogramming, as used in the link:https://www.alchemists.io/projects/auto_injector[Auto Injector]
|
|
18
|
+
gem, when architecting more sophisticated applications.
|
|
18
19
|
|
|
19
20
|
toc::[]
|
|
20
21
|
|
|
@@ -45,8 +46,16 @@ gem "marameters"
|
|
|
45
46
|
|
|
46
47
|
== Usage
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
There are two main objects you'll want to interact with:
|
|
50
|
+
|
|
51
|
+
* *Analyzer*: Allows you to analyze a method's parameters.
|
|
52
|
+
* *Signature*: Allows you to dynamically build a method signature.
|
|
53
|
+
|
|
54
|
+
Both of these objects are meant to serve as building blocks to more complex architectures.
|
|
55
|
+
|
|
56
|
+
=== Analyzer
|
|
57
|
+
|
|
58
|
+
To understand how to _analyze_ a method's parameters, consider the following demonstration class:
|
|
50
59
|
|
|
51
60
|
[source,ruby]
|
|
52
61
|
----
|
|
@@ -55,21 +64,23 @@ class Demo
|
|
|
55
64
|
@logger = logger
|
|
56
65
|
end
|
|
57
66
|
|
|
58
|
-
def
|
|
67
|
+
def all one, two = nil, *three, four:, five: nil, **six, &seven
|
|
59
68
|
logger.debug [one, two, three, four, five, six, seven]
|
|
60
69
|
end
|
|
61
70
|
|
|
71
|
+
def none = logger.debug "Nothing to see here."
|
|
72
|
+
|
|
62
73
|
private
|
|
63
74
|
|
|
64
75
|
attr_reader :logger
|
|
65
76
|
end
|
|
66
77
|
----
|
|
67
78
|
|
|
68
|
-
|
|
79
|
+
You can then analyze the `#all` method's parameters as follows:
|
|
69
80
|
|
|
70
81
|
[source,ruby]
|
|
71
82
|
----
|
|
72
|
-
analyzer = Marameters::Analyzer.new Demo.instance_method(:
|
|
83
|
+
analyzer = Marameters::Analyzer.new Demo.instance_method(:all).parameters
|
|
73
84
|
|
|
74
85
|
analyzer.block # :seven
|
|
75
86
|
analyzer.block? # true
|
|
@@ -91,6 +102,119 @@ analyzer.to_a # [[:req, :one], [:opt, :two], [:rest, :three], [:
|
|
|
91
102
|
analyzer.to_h # {:req=>:one, :opt=>:two, :rest=>:three, :keyreq=>:four, :key=>:five, :keyrest=>:six, :block=>:seven}
|
|
92
103
|
----
|
|
93
104
|
|
|
105
|
+
In contrast the above, we can also analyze the `#none` method which has no parameters for a
|
|
106
|
+
completely different result:
|
|
107
|
+
|
|
108
|
+
[source,ruby]
|
|
109
|
+
----
|
|
110
|
+
analyzer = Marameters::Analyzer.new Demo.instance_method(:none).parameters
|
|
111
|
+
|
|
112
|
+
analyzer.block # nil
|
|
113
|
+
analyzer.block? # false
|
|
114
|
+
analyzer.empty? # true
|
|
115
|
+
analyzer.keywords # []
|
|
116
|
+
analyzer.keywords? # false
|
|
117
|
+
analyzer.kind?(:req) # true
|
|
118
|
+
analyzer.kinds # []
|
|
119
|
+
analyzer.name?(:three) # false
|
|
120
|
+
analyzer.names # []
|
|
121
|
+
analyzer.only_bare_splats? # false
|
|
122
|
+
analyzer.only_double_splats? # false
|
|
123
|
+
analyzer.only_single_splats? # false
|
|
124
|
+
analyzer.positionals # []
|
|
125
|
+
analyzer.positionals? # false
|
|
126
|
+
analyzer.splats # []
|
|
127
|
+
analyzer.splats? # false
|
|
128
|
+
analyzer.to_a # []
|
|
129
|
+
analyzer.to_h # {}
|
|
130
|
+
----
|
|
131
|
+
|
|
132
|
+
=== Signature
|
|
133
|
+
|
|
134
|
+
The signature class is the opposite of the analyzer in that you want to feed it parameters for
|
|
135
|
+
turning into a method signature. This is useful when dynamically building method signatures or using
|
|
136
|
+
the same signature for multiple methods when metaprogramming.
|
|
137
|
+
|
|
138
|
+
The following demonstrates how you might construct a method signature with all possible parameters:
|
|
139
|
+
|
|
140
|
+
[source,ruby]
|
|
141
|
+
----
|
|
142
|
+
signature = Marameters::Signature.new(
|
|
143
|
+
{
|
|
144
|
+
req: :one,
|
|
145
|
+
opt: [:two, 2],
|
|
146
|
+
rest: :three,
|
|
147
|
+
keyreq: :four,
|
|
148
|
+
key: [:five, 5],
|
|
149
|
+
keyrest: :six,
|
|
150
|
+
block: :seven
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
puts signature
|
|
155
|
+
# one, two = 2, *three, four:, five: 5, **six, &seven
|
|
156
|
+
----
|
|
157
|
+
|
|
158
|
+
You'll notice that the parameters is a hash _and_ some values can be tuples. The reason is that it's
|
|
159
|
+
easier to write a hash than a double nested array as normally produced by the analyzer or directly
|
|
160
|
+
from `Method#parameters`. The optional positional and keyword parameters use tuples because you
|
|
161
|
+
might want to supply a default value and this provides a way for you to do that with minimal syntax.
|
|
162
|
+
This can be demonstrated further by using optional keywords (same applies for optional positionals):
|
|
163
|
+
|
|
164
|
+
[source,ruby]
|
|
165
|
+
----
|
|
166
|
+
# With no default
|
|
167
|
+
puts Marameters::Signature.new({key: :demo})
|
|
168
|
+
# demo: nil
|
|
169
|
+
|
|
170
|
+
# With explicit nil as default
|
|
171
|
+
puts Marameters::Signature.new({key: [:demo, nil]})
|
|
172
|
+
# demo: nil
|
|
173
|
+
|
|
174
|
+
# With string as default
|
|
175
|
+
puts Marameters::Signature.new({key: [:demo, "test"]})
|
|
176
|
+
# demo: "test"
|
|
177
|
+
|
|
178
|
+
# With symbol as default
|
|
179
|
+
puts Marameters::Signature.new({key: [:demo, :test]})
|
|
180
|
+
# demo: :test
|
|
181
|
+
|
|
182
|
+
# With object(dependency) as default
|
|
183
|
+
puts Marameters::Signature.new({key: [:demo, "*Object.new"]})
|
|
184
|
+
# demo: Object.new
|
|
185
|
+
----
|
|
186
|
+
|
|
187
|
+
In the case of object dependencies you need to wrap these in a string _and_ prefix them with a star
|
|
188
|
+
(`*`) so the signature builder won't confuse these as a normal string. There are two reasons why
|
|
189
|
+
this is important:
|
|
190
|
+
|
|
191
|
+
* The star (`*`) signifies that you want the object to be passed through without any further
|
|
192
|
+
processing while also not being confused normal strings.
|
|
193
|
+
* Objects wrapped as strings allows your dependency to be lazy loaded. Otherwise, if `Object.new`
|
|
194
|
+
was pass directly, you'd be passing the evaluated instance (i.e. `#<Object:0x0000000107df4028>`)
|
|
195
|
+
which is not what you want until much later when your method is defined.
|
|
196
|
+
|
|
197
|
+
When you put all of this together, you can dynamically build a method as follows:
|
|
198
|
+
|
|
199
|
+
[source,ruby]
|
|
200
|
+
----
|
|
201
|
+
signature = Marameters::Signature.new({opt: [:text, "This is a test."]})
|
|
202
|
+
|
|
203
|
+
Example = Module.new do
|
|
204
|
+
module_eval <<~DEFINITION, __FILE__, __LINE__ + 1
|
|
205
|
+
def self.say #{signature}
|
|
206
|
+
text
|
|
207
|
+
end
|
|
208
|
+
DEFINITION
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
puts Example.say
|
|
212
|
+
# This is a test.
|
|
213
|
+
|
|
214
|
+
puts Example.say "Hello"
|
|
215
|
+
# Hello
|
|
216
|
+
----
|
|
217
|
+
|
|
94
218
|
== Development
|
|
95
219
|
|
|
96
220
|
You can also use the IRB console for direct access to all objects:
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Marameters
|
|
4
|
+
# Builds a single parameter of a method's parameter signature.
|
|
5
|
+
class Builder
|
|
6
|
+
def initialize defaulter: Defaulter
|
|
7
|
+
@defaulter = defaulter
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# :reek:DuplicateMethodCall
|
|
11
|
+
def call kind, name, default: nil
|
|
12
|
+
case kind
|
|
13
|
+
when :req then name
|
|
14
|
+
when :opt then "#{name} = #{defaulter.call default}"
|
|
15
|
+
when :rest then "*#{name}"
|
|
16
|
+
when :keyreq then "#{name}:"
|
|
17
|
+
when :key then "#{name}: #{defaulter.call default}"
|
|
18
|
+
when :keyrest then "**#{name}"
|
|
19
|
+
when :block then "&#{name}"
|
|
20
|
+
else fail ArgumentError, "Wrong kind (#{kind}), name (#{name}), or default (#{default})."
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
attr_reader :defaulter
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Marameters
|
|
4
|
+
# Calculates the default for a given value when used within a method's parameter.
|
|
5
|
+
class Defaulter
|
|
6
|
+
PASSTHROUGH = "*"
|
|
7
|
+
|
|
8
|
+
def self.call(...) = new(...).call
|
|
9
|
+
|
|
10
|
+
def initialize value, passthrough: PASSTHROUGH
|
|
11
|
+
@value = value
|
|
12
|
+
@passthrough = passthrough
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def call
|
|
16
|
+
case value
|
|
17
|
+
when nil then "nil"
|
|
18
|
+
when /\A#{Regexp.escape passthrough}/ then value.delete_prefix passthrough
|
|
19
|
+
when String then value.dump
|
|
20
|
+
when Symbol then value.inspect
|
|
21
|
+
else value
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
attr_reader :value, :passthrough
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Marameters
|
|
4
|
+
# Produces a method signature for given parameters.
|
|
5
|
+
class Signature
|
|
6
|
+
def initialize parameters, builder: Builder.new
|
|
7
|
+
@parameters = parameters
|
|
8
|
+
@builder = builder
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s = build.join ", "
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
attr_reader :parameters, :builder
|
|
16
|
+
|
|
17
|
+
def build
|
|
18
|
+
parameters.reduce [] do |signature, (kind, (name, default))|
|
|
19
|
+
signature << builder.call(kind, name, default:)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/marameters.gemspec
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |spec|
|
|
4
4
|
spec.name = "marameters"
|
|
5
|
-
spec.version = "0.
|
|
5
|
+
spec.version = "0.2.0"
|
|
6
6
|
spec.authors = ["Brooke Kuhlmann"]
|
|
7
7
|
spec.email = ["brooke@alchemists.io"]
|
|
8
8
|
spec.homepage = "https://www.alchemists.io/projects/marameters"
|
|
9
|
-
spec.summary = "Provides method parameter
|
|
9
|
+
spec.summary = "Provides dynamic method parameter construction and deconstruction."
|
|
10
10
|
spec.license = "Hippocratic-2.1"
|
|
11
11
|
|
|
12
12
|
spec.metadata = {
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: marameters
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brooke Kuhlmann
|
|
@@ -28,7 +28,7 @@ cert_chain:
|
|
|
28
28
|
lkHilIrX69jq8wMPpBhlaw2mRmeSL50Wv5u6xVBvOHhXFSP1crXM95vfLhLyRYod
|
|
29
29
|
W2A=
|
|
30
30
|
-----END CERTIFICATE-----
|
|
31
|
-
date: 2022-03-
|
|
31
|
+
date: 2022-03-12 00:00:00.000000000 Z
|
|
32
32
|
dependencies:
|
|
33
33
|
- !ruby/object:Gem::Dependency
|
|
34
34
|
name: refinements
|
|
@@ -71,6 +71,9 @@ files:
|
|
|
71
71
|
- README.adoc
|
|
72
72
|
- lib/marameters.rb
|
|
73
73
|
- lib/marameters/analyzer.rb
|
|
74
|
+
- lib/marameters/builder.rb
|
|
75
|
+
- lib/marameters/defaulter.rb
|
|
76
|
+
- lib/marameters/signature.rb
|
|
74
77
|
- marameters.gemspec
|
|
75
78
|
homepage: https://www.alchemists.io/projects/marameters
|
|
76
79
|
licenses:
|
|
@@ -97,8 +100,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
97
100
|
- !ruby/object:Gem::Version
|
|
98
101
|
version: '0'
|
|
99
102
|
requirements: []
|
|
100
|
-
rubygems_version: 3.3.
|
|
103
|
+
rubygems_version: 3.3.9
|
|
101
104
|
signing_key:
|
|
102
105
|
specification_version: 4
|
|
103
|
-
summary: Provides method parameter
|
|
106
|
+
summary: Provides dynamic method parameter construction and deconstruction.
|
|
104
107
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|