named-parameters 0.0.5 → 0.0.6
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.
- data/README.md +103 -102
- data/RELEASENOTES +11 -1
- data/Rakefile +10 -1
- data/VERSION +1 -1
- data/lib/named-parameters.rb +5 -1
- data/lib/named-parameters/module.rb +115 -37
- data/lib/named-parameters/object.rb +7 -3
- data/named-parameters.gemspec +12 -3
- data/spec/named-parameters_spec.rb +158 -29
- metadata +5 -5
data/README.md
CHANGED
@@ -1,143 +1,144 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
This gem enables/simulates named-parameters in Ruby.
|
1
|
+
This gem simulates named-parameters in Ruby. It's a complement to the common
|
2
|
+
Ruby idiom of using `Hash` args to emulate the use of named parameters.
|
4
3
|
|
5
|
-
|
6
|
-
|
4
|
+
It does this by extending the language with a `has_named_parameters` clause
|
5
|
+
that allows a class to declare the parameters that are acceptable to a method.
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
gem install named-parameters
|
7
|
+
The `has_named_parameters` dictates how the presence of these parameters are
|
8
|
+
enforced and raises an `ArgumentError` when a method invocation is made that
|
9
|
+
violates the rules for those parameters.
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
To enable it everywhere (recommended):
|
16
|
-
|
17
|
-
require 'named-parameters'
|
11
|
+
See: the [Named Parameter](http://en.wikipedia.org/wiki/named_parameter)
|
12
|
+
article from Wikipedia for more information.
|
18
13
|
|
19
|
-
|
14
|
+
Get It
|
15
|
+
------
|
16
|
+
You know you want it:
|
20
17
|
|
21
|
-
|
18
|
+
gem install named-parameters
|
22
19
|
|
23
|
-
|
20
|
+
Use It
|
21
|
+
------
|
22
|
+
Make it available everywhere:
|
24
23
|
|
24
|
+
require 'named-parameters'
|
25
|
+
|
26
|
+
But if you want to be selective, do:
|
27
|
+
|
25
28
|
require 'named-parameters/module'
|
26
29
|
|
27
|
-
|
28
|
-
example:
|
30
|
+
Then include the `NamedParameters` module into your class:
|
29
31
|
|
30
|
-
class
|
32
|
+
class YourClass
|
31
33
|
include NamedParameters
|
32
|
-
# ...
|
33
34
|
end
|
35
|
+
|
36
|
+
Either way, you would now be able to use the `has_named_parameters` clause
|
37
|
+
as needed:
|
34
38
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
class GoogleStorage
|
41
|
-
has_named_parameters :initialize,
|
42
|
-
:required => [ :'access-key', :'secret-key' ]
|
43
|
-
def initialize opts = { }
|
44
|
-
# ...
|
45
|
-
end
|
46
|
-
|
47
|
-
has_named_parameters :request, :optional => :timeout
|
48
|
-
def request path, opts = { }
|
49
|
-
# ...
|
39
|
+
class YourClass
|
40
|
+
has_named_parameters :your_method, :require => :param
|
41
|
+
def your_method options
|
42
|
+
puts options.inspect
|
50
43
|
end
|
51
44
|
end
|
52
|
-
|
53
|
-
Since the `GoogleStorage` class above declares that its initializer requires
|
54
|
-
`:'access-key'` and `:'secret-key'` to be specified, the following
|
55
|
-
invocation will (correctly) raise an `ArgumentError`
|
56
45
|
|
57
|
-
|
46
|
+
So when you invoke `your_method`, its parameter requirements will now be
|
47
|
+
enforced:
|
58
48
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
But specifying an unrecognized parameter will do:
|
49
|
+
obj = YourClass.new
|
50
|
+
obj.your_method :param => 'Et tu, Babe?' # will spit out: 'Et tu, Babe?'
|
51
|
+
obj.your_method # will raise an ArgumentError because the required :param was not specified
|
52
|
+
|
53
|
+
Abuse It
|
54
|
+
--------
|
55
|
+
Declare required parameters:
|
67
56
|
|
68
|
-
|
57
|
+
has_named_parameters :send_mail, :required => :to
|
58
|
+
has_named_parameters :send_mail, :required => [ :to, :subject ]
|
69
59
|
|
70
|
-
|
71
|
-
instance methods of a class:
|
72
|
-
|
73
|
-
class Point
|
74
|
-
has_named_parameters :initialize, :required => [ :x, :y ], :optional => :color
|
75
|
-
def initialize opts = { }
|
76
|
-
# ...
|
77
|
-
end
|
60
|
+
Declare optional parameters:
|
78
61
|
|
79
|
-
|
80
|
-
|
81
|
-
# ...
|
82
|
-
end
|
83
|
-
end
|
62
|
+
has_named_parameters :send_mail, :optional => :subject
|
63
|
+
has_named_parameters :send_mail, :optional => [ :subject, :bcc, :from ]
|
84
64
|
|
65
|
+
Declare one of a set of parameters as required (ie: require one and only
|
66
|
+
one from a list):
|
85
67
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
has_named_parameters :
|
68
|
+
has_named_parameters :send_mail, :oneof => [ :signature, :alias ]
|
69
|
+
|
70
|
+
Declare default values for optional parameters:
|
71
|
+
|
72
|
+
has_named_parameters :send_mail, :optional => [ :subject, :bcc, { :from => 'yourself@example.org' } ]
|
73
|
+
has_named_parameters :send_mail, :optional => [ :subject, :bcc, [ :from, 'yourself@example.org' ] ]
|
92
74
|
|
93
|
-
|
75
|
+
You can also declare default values for `:required` and `:oneof` parameters,
|
76
|
+
but really, that's just silly.
|
94
77
|
|
95
|
-
|
78
|
+
With `has_named_parameters`, you can mix-and-match parameter requirements:
|
96
79
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
called.
|
80
|
+
has_named_parameters :send_mail,
|
81
|
+
:required => [ :to, :subject, ],
|
82
|
+
:oneof => [ :signature, :alias ],
|
83
|
+
:optional => [ :subject, :bcc, [ :from, 'yourself@example.org' ] ]
|
102
84
|
|
103
|
-
|
104
|
-
following variations:
|
85
|
+
And is applicable to both class and instance methods:
|
105
86
|
|
106
|
-
|
107
|
-
|
87
|
+
require 'named-parameters'
|
88
|
+
|
89
|
+
class Mailer
|
90
|
+
has_named_parameters :send_mail,
|
91
|
+
:required => [ :to, :subject, ],
|
92
|
+
:oneof => [ :signature, :alias ],
|
93
|
+
:optional => [ :subject, :bcc, [ :from, 'yourself@example.org' ] ]
|
94
|
+
def send_mail options
|
95
|
+
# ... do send mail stuff here ...
|
96
|
+
end
|
97
|
+
|
98
|
+
has_named_parameters :archive, :optional => [ :method => 'zip' ]
|
99
|
+
def self.archive options = { }
|
100
|
+
# ... do mail archiving stuff here ...
|
101
|
+
end
|
108
102
|
end
|
109
103
|
|
110
|
-
|
111
|
-
|
112
|
-
|
104
|
+
Gotchas
|
105
|
+
-------
|
106
|
+
When `has_named_parameters` is declared in a class, it instruments the class
|
107
|
+
so that when the method in the declaration is invoked, a validation is
|
108
|
+
performed on the first `Hash` argument that was received by the method.
|
113
109
|
|
114
|
-
|
115
|
-
|
116
|
-
end
|
110
|
+
It really has no idea about the position of the argument that is supposed
|
111
|
+
to carry the named parameters.
|
117
112
|
|
118
|
-
|
113
|
+
So you can mix-and-match argument types in a method, and still declare that
|
114
|
+
it `has_named_parameters`:
|
119
115
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
# ...
|
116
|
+
has_named_parameters :request, :required => :accesskey
|
117
|
+
def request path, options
|
118
|
+
"path: #{path}, options: #{options.inspect}"
|
124
119
|
end
|
120
|
+
|
121
|
+
# invocation:
|
122
|
+
request "/xxx", :accesskey => '0925'
|
123
|
+
|
124
|
+
# result:
|
125
|
+
# => path: /xxx, options: {:accesskey => '0925'}
|
126
|
+
|
127
|
+
But be careful when you have something like the following:
|
125
128
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
# ...
|
129
|
+
has_named_parameters :request, :required => :accesskey
|
130
|
+
def request path, options = { }
|
131
|
+
"path: #{path}, options: #{options.inspect}"
|
130
132
|
end
|
131
133
|
|
132
|
-
#
|
133
|
-
|
134
|
-
def service opts
|
135
|
-
# ...
|
136
|
-
end
|
134
|
+
# invocation:
|
135
|
+
request :accesskey => '0925'
|
137
136
|
|
138
|
-
|
137
|
+
# result isn't what's expected:
|
138
|
+
# => path: {:accesskey => '0925'}, options: {}
|
139
139
|
|
140
|
-
|
140
|
+
The next release of the gem will adopt the convention of having the `Hash`
|
141
|
+
argument as the last argument passed to the method.
|
141
142
|
|
142
143
|
Dependencies
|
143
144
|
------------
|
data/RELEASENOTES
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
0.0.6 [Nov 13, 2010]
|
2
|
+
- [FEATURE] Added support for requiring one-of from a list of named
|
3
|
+
parameters.
|
4
|
+
- [FEATURE] Added support for declaring default values for parameters.
|
5
|
+
- [INTERNAL] spec is now normalized inside the has_named_parameters
|
6
|
+
declaration allowing more flexible notation when when specifying default
|
7
|
+
values for parameters.
|
8
|
+
- [INTERNAL] Updated tests.
|
9
|
+
|
1
10
|
0.0.5 [Nov 11, 2010]
|
2
11
|
--------------------
|
3
12
|
- [BUGFIX] Same as 0.0.4 - except this time it's really fixed :-)
|
@@ -8,7 +17,8 @@
|
|
8
17
|
|
9
18
|
0.0.3 [Nov 11, 2010]
|
10
19
|
--------------------
|
11
|
-
- Added support for has_named_parameter declaration for class
|
20
|
+
- [FEATURE] Added support for has_named_parameter declaration for class
|
21
|
+
methods.
|
12
22
|
|
13
23
|
0.0.2 [Nov 10, 2010]
|
14
24
|
--------------------
|
data/Rakefile
CHANGED
@@ -6,7 +6,16 @@ begin
|
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "named-parameters"
|
8
8
|
gem.summary = %Q{Poor man's named-parameters in Ruby}
|
9
|
-
gem.description = %Q{This gem
|
9
|
+
gem.description = %Q{This gem simulates named-parameters in Ruby. It's a complement to the common
|
10
|
+
Ruby idiom of using `Hash` args to emulate the use of named parameters.
|
11
|
+
|
12
|
+
It does this by extending the language with a `has_named_parameters` clause
|
13
|
+
that allows a class to declare the parameters that are acceptable to a method.
|
14
|
+
|
15
|
+
The `has_named_parameters` dictates how the presence of these parameters are
|
16
|
+
enforced and raises an `ArgumentError` when a method invocation is made that
|
17
|
+
violates the rules for those parameters.
|
18
|
+
}
|
10
19
|
gem.email = "jurisgalang@gmail.com"
|
11
20
|
gem.homepage = "http://github.com/jurisgalang/named-parameters"
|
12
21
|
gem.authors = ["Juris Galang"]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
data/lib/named-parameters.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
-
#
|
2
|
-
#
|
1
|
+
# named-parameters.rb
|
2
|
+
#
|
3
|
+
# When mixed-in, the `NamedParameters` module adds has_named_parameters class
|
4
|
+
# method, which can be used to declare methods that are supposed to accepts
|
5
|
+
# named-parameters.
|
3
6
|
#
|
4
7
|
# Sample usage:
|
5
8
|
#
|
@@ -16,14 +19,10 @@
|
|
16
19
|
# FooBar.new :y => '...' # ArgumentError - since :x was not specified
|
17
20
|
#
|
18
21
|
# @author Juris Galang
|
22
|
+
# @copyright 2010 Juris Galang. All Rights Reserved
|
19
23
|
#
|
20
|
-
class Object
|
21
|
-
def eigenclass # :nodoc:
|
22
|
-
class << self; self; end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
24
|
module NamedParameters
|
25
|
+
protected
|
27
26
|
def self.included base # :nodoc:
|
28
27
|
base.extend ClassMethods
|
29
28
|
end
|
@@ -32,31 +31,47 @@ module NamedParameters
|
|
32
31
|
# this is the method used to validate the name of the received parameters
|
33
32
|
# (based on the defined spec) when an instrumented method is invoked.
|
34
33
|
#
|
35
|
-
def self.
|
36
|
-
|
37
|
-
spec[:optional]
|
34
|
+
def self.validate_specs name, params, spec # :nodoc:
|
35
|
+
mapper = lambda{ |n| n.instance_of?(Hash) ? n.keys.first : n }
|
36
|
+
optional = spec[:optional].map &mapper
|
37
|
+
required = spec[:required].map &mapper
|
38
|
+
oneof = spec[:oneof].map &mapper
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
} ]
|
40
|
+
# determine what keys are allowed
|
41
|
+
order = lambda{ |x, y| x.to_s <=> y.to_s }
|
42
|
+
allowed = (optional + required + oneof).sort &order
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
keys
|
47
|
-
|
48
|
-
keys.sort! &
|
49
|
-
|
44
|
+
# determine what keys were passed;
|
45
|
+
# also, plugin the names of parameters assigned with default values
|
46
|
+
#keys = (params.keys.map{ |k| k.to_sym } + defaults.keys).uniq
|
47
|
+
keys = params.keys.map{ |k| k.to_sym }
|
48
|
+
keys.sort! &order
|
49
|
+
required.sort! &order
|
50
50
|
|
51
|
+
# this lambda is used to present the list of parameters as a string
|
51
52
|
list = lambda{ |params| params.join(", ") }
|
53
|
+
|
54
|
+
# require that all of :required parameters are specified
|
55
|
+
unless required.empty?
|
56
|
+
k = required & keys
|
57
|
+
raise ArgumentError, \
|
58
|
+
"#{name} requires the following parameters: #{list[required - k]}" \
|
59
|
+
unless k == required
|
60
|
+
end
|
52
61
|
|
53
|
-
|
54
|
-
|
62
|
+
# require that one (and only one) of :oneof parameters is specified
|
63
|
+
unless oneof.empty?
|
64
|
+
k = oneof & keys
|
65
|
+
raise ArgumentError, \
|
66
|
+
"#{name} requires at least one of the following parameters: #{list[oneof]}" \
|
67
|
+
if k.empty?
|
55
68
|
raise ArgumentError, \
|
56
|
-
"#{name}
|
57
|
-
|
69
|
+
"#{name} may specify only one of the following parameters: #{list[oneof]}" \
|
70
|
+
if k.length > 1
|
58
71
|
end
|
59
72
|
|
73
|
+
# enforce that only declared parameters (:required, :optional, and :oneof)
|
74
|
+
# may be specified
|
60
75
|
k = keys - allowed
|
61
76
|
raise ArgumentError, \
|
62
77
|
"Unrecognized parameter specified on call to #{name}: #{list[k]}" \
|
@@ -64,28 +79,74 @@ module NamedParameters
|
|
64
79
|
end
|
65
80
|
|
66
81
|
module ClassMethods
|
67
|
-
protected
|
68
82
|
# Declares that `method` will enforce named parameters behavior as
|
69
|
-
# described in `spec`; a method declared with
|
70
|
-
# parameters will raise an `ArgumentError` if it is invoked
|
71
|
-
# required parameters or receives an unrecognized parameter.
|
83
|
+
# described in `spec`; a method declared with `:required` and/or
|
84
|
+
# `:optional` parameters will raise an `ArgumentError` if it is invoked
|
85
|
+
# without its required parameters or receives an unrecognized parameter.
|
72
86
|
#
|
73
87
|
# Sample usage:
|
74
88
|
#
|
75
|
-
# has_named_parameters :point, :required => [ :x, :y ],
|
76
|
-
# :optional => :color
|
89
|
+
# has_named_parameters :point, :required => [ :x, :y ], :optional => :color
|
77
90
|
#
|
78
|
-
# @param [Symbol]
|
91
|
+
# @param [Symbol] method the name of the method that is supposed to
|
79
92
|
# enforce named parameters behavior.
|
80
93
|
#
|
81
|
-
# @param [Hash]
|
94
|
+
# @param [Hash] spec a `Hash` to specify the list of required and optional
|
95
|
+
# parameters for the method. Use either the `:required`, `:optional`, or
|
96
|
+
# `:oneof` key to specify the lists of parameters. The list is expected
|
97
|
+
# to be an `Array` of symbols matching the names of the expected and
|
98
|
+
# optional parameters.
|
82
99
|
#
|
83
|
-
#
|
100
|
+
# Parameters are evaluated according their classification:
|
101
|
+
#
|
102
|
+
# * `:required` means that all of these parameters must be specified.
|
103
|
+
# * `:optional` means that all or none of these parameters may be used.
|
104
|
+
# * `:oneof` means that one of these parameters must be specified.
|
84
105
|
#
|
85
106
|
def has_named_parameters method, spec = { }
|
107
|
+
# ensure spec entries are initialized and the proper types
|
108
|
+
[ :required, :optional, :oneof ].each{ |k| spec[k] ||= [] }
|
109
|
+
spec = Hash[ spec.map{ |k, v|
|
110
|
+
v = [ v ] unless v.instance_of? Array
|
111
|
+
v.map!{ |entry| entry.instance_of?(Array) ? Hash[*entry] : entry }
|
112
|
+
[ k, v ]
|
113
|
+
} ]
|
86
114
|
specs[method] = spec
|
87
115
|
end
|
88
116
|
|
117
|
+
protected
|
118
|
+
# Attach a validation block for a specific parameter that will be invoked
|
119
|
+
# before the actual `method` call.
|
120
|
+
#
|
121
|
+
# @param [Symbol] method the name of the method.
|
122
|
+
#
|
123
|
+
# @param [Symbol] param the name of the parameter whose value is to be
|
124
|
+
# validated.
|
125
|
+
#
|
126
|
+
# @param [lambda, Proc] &block the chunk of code that will perform the
|
127
|
+
# actual validation. It is expected to raise an error or return false
|
128
|
+
# if the validation fails. It receives argument for `param` on
|
129
|
+
# invocation.
|
130
|
+
#
|
131
|
+
# If `&block` is not specified then it assumes that an implicit
|
132
|
+
# validation method is defined. It calculates the name of this method
|
133
|
+
# by concatenating the values supplied for `method` and `param`,
|
134
|
+
# suffixed with the word `validation`, eg:
|
135
|
+
#
|
136
|
+
# validates_arguments_for :request, :timeout
|
137
|
+
# def request, opts = { }
|
138
|
+
# ...
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# private
|
142
|
+
# def request_timeout_validation value
|
143
|
+
# ...
|
144
|
+
# end
|
145
|
+
#
|
146
|
+
def validates_arguments method, param, &block
|
147
|
+
# TODO: IMPLEMENT
|
148
|
+
end
|
149
|
+
|
89
150
|
# add instrumentation for class methods
|
90
151
|
def singleton_method_added name # :nodoc:
|
91
152
|
instrument name do
|
@@ -122,10 +183,27 @@ module NamedParameters
|
|
122
183
|
|
123
184
|
# insert parameter validation prior to executing the instrumented method
|
124
185
|
def intercept method, owner, name, spec # :nodoc:
|
186
|
+
fullname = "#{owner}#{name}"
|
125
187
|
define_method name do |*args, &block|
|
126
|
-
|
127
|
-
|
128
|
-
|
188
|
+
# locate the argument representing the named parameters value
|
189
|
+
# for the method invocation
|
190
|
+
params = args.find{ |arg| arg.instance_of? Hash }
|
191
|
+
args << (params = { }) if params.nil?
|
192
|
+
|
193
|
+
# merge the declared default values for params into the arguments
|
194
|
+
# used when the method is invoked
|
195
|
+
defaults = { }
|
196
|
+
spec.each do |k, v|
|
197
|
+
v.each{ |entry| defaults.merge! entry if entry.instance_of? Hash }
|
198
|
+
end
|
199
|
+
params = defaults.merge params
|
200
|
+
|
201
|
+
# validate the parameters against the spec
|
202
|
+
NamedParameters::validate_specs fullname, params, spec
|
203
|
+
|
204
|
+
# inject the updated argument values for params into the arguments
|
205
|
+
# before actually making method invocation
|
206
|
+
args.map!{ |arg| arg.instance_of?(Hash) ? params : arg }
|
129
207
|
method.bind(self).call(*args, &block)
|
130
208
|
end
|
131
209
|
end
|
data/named-parameters.gemspec
CHANGED
@@ -5,12 +5,21 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{named-parameters}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Juris Galang"]
|
12
|
-
s.date = %q{2010-11-
|
13
|
-
s.description = %q{This gem
|
12
|
+
s.date = %q{2010-11-13}
|
13
|
+
s.description = %q{This gem simulates named-parameters in Ruby. It's a complement to the common
|
14
|
+
Ruby idiom of using `Hash` args to emulate the use of named parameters.
|
15
|
+
|
16
|
+
It does this by extending the language with a `has_named_parameters` clause
|
17
|
+
that allows a class to declare the parameters that are acceptable to a method.
|
18
|
+
|
19
|
+
The `has_named_parameters` dictates how the presence of these parameters are
|
20
|
+
enforced and raises an `ArgumentError` when a method invocation is made that
|
21
|
+
violates the rules for those parameters.
|
22
|
+
}
|
14
23
|
s.email = %q{jurisgalang@gmail.com}
|
15
24
|
s.extra_rdoc_files = [
|
16
25
|
"README.md"
|
@@ -2,45 +2,174 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
2
|
|
3
3
|
describe "NamedParameters" do
|
4
4
|
before :all do
|
5
|
-
class
|
5
|
+
class Foo
|
6
6
|
has_named_parameters :initialize, :required => :x, :optional => [ :y, :z ]
|
7
|
-
def initialize
|
7
|
+
def initialize opts = {}; end
|
8
8
|
|
9
9
|
has_named_parameters :method_one, :required => :x, :optional => [ :y, :z ]
|
10
|
-
def method_one
|
10
|
+
def method_one x, y, opts = {}; end
|
11
11
|
|
12
|
-
def method_two
|
12
|
+
def method_two x, y, opts = {}; end
|
13
|
+
|
14
|
+
has_named_parameters :method_three, :required => :x, :optional => [ :y, :z ]
|
15
|
+
def self.method_three x, y, opts = {}; end
|
16
|
+
|
17
|
+
def self.method_four x, y, opts = {}; end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Bar
|
21
|
+
has_named_parameters :method_with_one_required, :required => :x
|
22
|
+
def method_with_one_required opts = {}; end
|
23
|
+
|
24
|
+
has_named_parameters :method_with_many_required, :required => [ :x, :y ]
|
25
|
+
def method_with_many_required opts = {}; end
|
26
|
+
|
27
|
+
has_named_parameters :method_with_one_oneof, :oneof => :x
|
28
|
+
def method_with_one_oneof opts = {}; end
|
29
|
+
|
30
|
+
has_named_parameters :method_with_many_oneof, :oneof => [ :x, :y ]
|
31
|
+
def method_with_many_oneof opts = {}; end
|
32
|
+
|
33
|
+
has_named_parameters :method_with_one_optional, :optional => :x
|
34
|
+
def method_with_one_optional opts = {}; end
|
35
|
+
|
36
|
+
has_named_parameters :method_with_many_optional, :optional => [ :x, :y ]
|
37
|
+
def method_with_many_optional opts = {}; end
|
38
|
+
|
39
|
+
has_named_parameters :method_with_one_of_each_requirement, :required => :w, :oneof => [ :x, :y ], :optional => :z
|
40
|
+
def method_with_one_of_each_requirement opts = {}; end
|
13
41
|
end
|
14
42
|
end
|
15
43
|
|
16
44
|
it "should allow declaration of has_named_parameters" do
|
17
|
-
|
45
|
+
Foo.should respond_to :has_named_parameters
|
18
46
|
end
|
19
47
|
|
20
48
|
it "should enforce named parameters for constructor" do
|
21
|
-
lambda{
|
22
|
-
lambda{
|
23
|
-
lambda{
|
24
|
-
lambda{
|
25
|
-
lambda{
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should enforce named parameters for instrumented methods" do
|
29
|
-
lambda{ @
|
30
|
-
lambda{ @
|
31
|
-
lambda{ @
|
32
|
-
lambda{ @
|
33
|
-
lambda{ @
|
34
|
-
lambda{ @
|
35
|
-
lambda{ @
|
36
|
-
lambda{ @
|
37
|
-
lambda{ @
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should not enforce named parameters for un-instrumented methods" do
|
41
|
-
lambda{ @
|
42
|
-
lambda{ @
|
43
|
-
lambda{ @
|
44
|
-
lambda{ @
|
49
|
+
lambda{ Foo.new }.should raise_error ArgumentError
|
50
|
+
lambda{ Foo.new :w => :w }.should raise_error ArgumentError
|
51
|
+
lambda{ Foo.new :x => :x }.should_not raise_error
|
52
|
+
lambda{ Foo.new :x => :x, :y => :y }.should_not raise_error
|
53
|
+
lambda{ Foo.new :x => :x, :y => :y, :z => :z }.should_not raise_error
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should enforce named parameters for instrumented instance methods" do
|
57
|
+
lambda{ @foo = Foo.new :x => :x, :y => :y, :z => :z }.should_not raise_error
|
58
|
+
lambda{ @foo.method_one :x }.should raise_error ArgumentError
|
59
|
+
lambda{ @foo.method_one :x, :y }.should raise_error ArgumentError
|
60
|
+
lambda{ @foo.method_one :x, :y, :x => :x, :y => :y, :z => :z, :w => :w }.should raise_error ArgumentError
|
61
|
+
lambda{ @foo.method_one :x => :x, :y => :y, :z => :z }.should raise_error ArgumentError
|
62
|
+
lambda{ @foo.method_one :x, :y, :w => :w }.should raise_error ArgumentError
|
63
|
+
lambda{ @foo.method_one :x, :y, :x => :x }.should_not raise_error
|
64
|
+
lambda{ @foo.method_one :x, :y, :x => :x, :y => :y }.should_not raise_error
|
65
|
+
lambda{ @foo.method_one :x, :y, :x => :x, :y => :y, :z => :z }.should_not raise_error
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should not enforce named parameters for un-instrumented instance methods" do
|
69
|
+
lambda{ @foo = Foo.new :x => :x, :y => :y, :z => :z }.should_not raise_error
|
70
|
+
lambda{ @foo.method_two :x }.should raise_error ArgumentError
|
71
|
+
lambda{ @foo.method_two :x, :y }.should_not raise_error ArgumentError
|
72
|
+
lambda{ @foo.method_two :x, :y, :w => :w }.should_not raise_error ArgumentError
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should enforce named parameters for instrumented class methods" do
|
76
|
+
lambda{ Foo.method_three :x }.should raise_error ArgumentError
|
77
|
+
lambda{ Foo.method_three :x, :y }.should raise_error ArgumentError
|
78
|
+
lambda{ Foo.method_three :x, :y, :x => :x, :y => :y, :z => :z, :w => :w }.should raise_error ArgumentError
|
79
|
+
lambda{ Foo.method_three :x => :x, :y => :y, :z => :z }.should raise_error ArgumentError
|
80
|
+
lambda{ Foo.method_three :x, :y, :w => :w }.should raise_error ArgumentError
|
81
|
+
lambda{ Foo.method_three :x, :y, :x => :x }.should_not raise_error
|
82
|
+
lambda{ Foo.method_three :x, :y, :x => :x, :y => :y }.should_not raise_error
|
83
|
+
lambda{ Foo.method_three :x, :y, :x => :x, :y => :y, :z => :z }.should_not raise_error
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not enforce named parameters for un-instrumented class methods" do
|
87
|
+
lambda{ Foo.method_four :x }.should raise_error ArgumentError
|
88
|
+
lambda{ Foo.method_four :x, :y }.should_not raise_error ArgumentError
|
89
|
+
lambda{ Foo.method_four :x, :y, :w => :w }.should_not raise_error ArgumentError
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should require all :required parameters" do
|
93
|
+
bar = Bar.new
|
94
|
+
lambda{ bar.method_with_one_required }.should raise_error ArgumentError
|
95
|
+
lambda{ bar.method_with_one_required :a => :a }.should raise_error ArgumentError
|
96
|
+
lambda{ bar.method_with_one_required :x => :x }.should_not raise_error
|
97
|
+
|
98
|
+
lambda{ bar.method_with_many_required }.should raise_error ArgumentError
|
99
|
+
lambda{ bar.method_with_many_required :x => :x }.should raise_error ArgumentError
|
100
|
+
lambda{ bar.method_with_many_required :x => :x, :y => :y }.should_not raise_error
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should require one and only one of :oneof parameters" do
|
104
|
+
bar = Bar.new
|
105
|
+
lambda{ bar.method_with_one_oneof }.should raise_error ArgumentError
|
106
|
+
lambda{ bar.method_with_one_oneof :a => :a }.should raise_error ArgumentError
|
107
|
+
lambda{ bar.method_with_one_oneof :x => :x }.should_not raise_error
|
108
|
+
|
109
|
+
lambda{ bar.method_with_many_oneof }.should raise_error ArgumentError
|
110
|
+
lambda{ bar.method_with_many_oneof :a => :a }.should raise_error ArgumentError
|
111
|
+
lambda{ bar.method_with_many_oneof :x => :x }.should_not raise_error
|
112
|
+
lambda{ bar.method_with_many_oneof :y => :y }.should_not raise_error
|
113
|
+
lambda{ bar.method_with_many_oneof :x => :x, :y => :y }.should raise_error ArgumentError
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should reject parameters not declared in :required, :optional, or :oneof" do
|
117
|
+
bar = Bar.new
|
118
|
+
lambda{ bar.method_with_one_optional }.should_not raise_error
|
119
|
+
lambda{ bar.method_with_one_optional :x => :x }.should_not raise_error
|
120
|
+
lambda{ bar.method_with_one_optional :a => :a }.should raise_error ArgumentError
|
121
|
+
lambda{ bar.method_with_one_optional :x => :x, :y => :y }.should raise_error ArgumentError
|
122
|
+
|
123
|
+
lambda{ bar.method_with_many_optional }.should_not raise_error
|
124
|
+
lambda{ bar.method_with_many_optional :x => :x }.should_not raise_error
|
125
|
+
lambda{ bar.method_with_many_optional :y => :y }.should_not raise_error
|
126
|
+
lambda{ bar.method_with_many_optional :x => :x, :y => :y }.should_not raise_error
|
127
|
+
lambda{ bar.method_with_many_optional :x => :x, :y => :y, :z => :z }.should raise_error ArgumentError
|
128
|
+
|
129
|
+
lambda{ bar.method_with_one_of_each_requirement }.should raise_error ArgumentError
|
130
|
+
lambda{ bar.method_with_one_of_each_requirement :w => :w }.should raise_error ArgumentError
|
131
|
+
lambda{ bar.method_with_one_of_each_requirement :w => :w, :x => :x }.should_not raise_error
|
132
|
+
lambda{ bar.method_with_one_of_each_requirement :w => :w, :y => :y }.should_not raise_error
|
133
|
+
lambda{ bar.method_with_one_of_each_requirement :w => :w, :x => :x, :y => :y }.should raise_error ArgumentError
|
134
|
+
lambda{ bar.method_with_one_of_each_requirement :w => :w, :x => :x, :z => :z }.should_not raise_error
|
135
|
+
lambda{ bar.method_with_one_of_each_requirement :w => :w, :y => :y, :z => :z }.should_not raise_error
|
136
|
+
lambda{ bar.method_with_one_of_each_requirement :w => :w, :x => :x, :z => :z, :a => :a }.should raise_error ArgumentError
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should be able to supply the default values for optional parameters" do
|
140
|
+
class Zoo
|
141
|
+
has_named_parameters :method_with_one_optional_parameter, :optional => { :x => 1 }
|
142
|
+
def method_with_one_optional_parameter opts = { }; opts[:x]; end
|
143
|
+
|
144
|
+
has_named_parameters :method_with_many_optional_parameters, :optional => [ [ :x, 1 ], [ :y, 2 ] ]
|
145
|
+
def method_with_many_optional_parameters opts = { }; opts[:x] + opts[:y]; end
|
146
|
+
|
147
|
+
has_named_parameters :method_with_many_optional_parameters_too, :optional => [ { :x => 1 }, { :y => 2 } ]
|
148
|
+
def method_with_many_optional_parameters_too opts = { }; opts[:x] + opts[:y]; end
|
149
|
+
end
|
150
|
+
|
151
|
+
zoo = Zoo.new
|
152
|
+
zoo.method_with_one_optional_parameter.should eql 1
|
153
|
+
zoo.method_with_one_optional_parameter(:x => 2).should eql 2
|
154
|
+
|
155
|
+
zoo.method_with_many_optional_parameters.should eql 3
|
156
|
+
zoo.method_with_many_optional_parameters(:x => 2).should eql 4
|
157
|
+
zoo.method_with_many_optional_parameters(:x => 2, :y => 3).should eql 5
|
158
|
+
|
159
|
+
zoo.method_with_many_optional_parameters_too.should eql 3
|
160
|
+
zoo.method_with_many_optional_parameters_too(:x => 2).should eql 4
|
161
|
+
zoo.method_with_many_optional_parameters_too(:x => 2, :y => 3).should eql 5
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should be able to instrument the class method new" do
|
165
|
+
class Quux
|
166
|
+
has_named_parameters :new, :required => :x
|
167
|
+
def self.new opts = { }; end
|
168
|
+
def initialize opts = { }; end
|
169
|
+
end
|
170
|
+
lambda { Quux.new }.should raise_error ArgumentError
|
171
|
+
lambda { Quux.new :y => :y }.should raise_error ArgumentError
|
172
|
+
lambda { Quux.new :x => :x, :y => :y }.should raise_error ArgumentError
|
173
|
+
lambda { Quux.new :x => :x }.should_not raise_error
|
45
174
|
end
|
46
175
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: named-parameters
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 6
|
10
|
+
version: 0.0.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Juris Galang
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-13 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -48,7 +48,7 @@ dependencies:
|
|
48
48
|
version: "0"
|
49
49
|
type: :development
|
50
50
|
version_requirements: *id002
|
51
|
-
description: This gem
|
51
|
+
description: "This gem simulates named-parameters in Ruby. It's a complement to the common \n Ruby idiom of using `Hash` args to emulate the use of named parameters. \n\n It does this by extending the language with a `has_named_parameters` clause \n that allows a class to declare the parameters that are acceptable to a method.\n\n The `has_named_parameters` dictates how the presence of these parameters are\n enforced and raises an `ArgumentError` when a method invocation is made that\n violates the rules for those parameters.\n "
|
52
52
|
email: jurisgalang@gmail.com
|
53
53
|
executables: []
|
54
54
|
|