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 CHANGED
@@ -1,143 +1,144 @@
1
- NamedParameters Gem
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
- See: http://en.wikipedia.org/wiki/named_parameter for more information on
6
- Named Parameters in general.
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
- Installation
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
- Usage
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
- And all your classes should be able to declare:
14
+ Get It
15
+ ------
16
+ You know you want it:
20
17
 
21
- has_named_parameters :method, :optional => [ ... ], :required => [ ... ]
18
+ gem install named-parameters
22
19
 
23
- If you want to be selective about which classes will use it, do:
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
- -- then mix-in the `NamedParameters` module into the class of your choice, for
28
- example:
30
+ Then include the `NamedParameters` module into your class:
29
31
 
30
- class FooBar
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
- Using the has_named_parameters Method
36
- -------------------------------------
37
- The `has_named_parameters` method is used to declare that a method accepts a
38
- `Hash` argument that should be treated like named-parameters:
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
- GoogleStorage.new # ArgumentError, GoogleStorage#initialize requires: access-key, secret-key
46
+ So when you invoke `your_method`, its parameter requirements will now be
47
+ enforced:
58
48
 
59
- On the other-hand, it declares that the `request` method may optionally accept
60
- a parameter named `timeout` - so the following invocations will not raise error:
61
-
62
- gs = GoogleStorage.new :'access-key' => '...', :'secret-key' => '...'
63
- gs.request '/some/path'
64
- gs.request '/some/path', :timeout => '500ms'
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
- gs.request '/some/path', :ssl => true # ArgumentError, GoogleStorage#request unrecognized parameter: ssl
57
+ has_named_parameters :send_mail, :required => :to
58
+ has_named_parameters :send_mail, :required => [ :to, :subject ]
69
59
 
70
- The `has_named_parameters` declaration may be used for either class or
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
- has_named_parameters :load, :optional => :translations
80
- def self.load filename, opts => { }
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
- Optional and Required Parameters
87
- --------------------------------
88
- Optional and required parameters may be declared in a single
89
- `has_named_parameters` declaration:
90
-
91
- has_named_parameters :request, :required => :path, :optional => :timeout
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
- To specify more than one optional or required parameter, use an `Array`:
75
+ You can also declare default values for `:required` and `:oneof` parameters,
76
+ but really, that's just silly.
94
77
 
95
- has_named_parameters :request, :required => :path, :optional => [ :timeout, :ssl ]
78
+ With `has_named_parameters`, you can mix-and-match parameter requirements:
96
79
 
97
- How It Works
98
- ------------
99
- The `has_named_parameters` declaration simply looks for the first `Hash`
100
- argument when a method that has been declared with `has_named_parameters` is
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
- It does not know the name of the `Hash` parameter for the method. So the
104
- following variations:
85
+ And is applicable to both class and instance methods:
105
86
 
106
- def service opts = { }
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
- def service options = { }
111
- # ...
112
- end
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
- def service params
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
- -- behave the same way, when the `has_named_parameter` clause is used:
113
+ So you can mix-and-match argument types in a method, and still declare that
114
+ it `has_named_parameters`:
119
115
 
120
- # the following...
121
- has_named_parameters :service, :optional => :timeout
122
- def service params
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
- # is essentially the same as...
127
- has_named_parameters :service, :optional => :timeout
128
- def service opts = { }
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
- # as well as...
133
- has_named_parameters :service, :optional => :timeout
134
- def service opts
135
- # ...
136
- end
134
+ # invocation:
135
+ request :accesskey => '0925'
137
136
 
138
- Since when the method is invoked, each one of the above could receive a `Hash`
137
+ # result isn't what's expected:
138
+ # => path: {:accesskey => '0925'}, options: {}
139
139
 
140
- service :timeout => '500ms'
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
  ------------
@@ -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 methods.
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 enables/simulates named-parameters in Ruby}
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.5
1
+ 0.0.6
@@ -1,2 +1,6 @@
1
+ require 'named-parameters/object'
1
2
  require 'named-parameters/module'
2
- require 'named-parameters/object'
3
+
4
+ # Extend object to automatically make it available for all
5
+ # user defined classes...
6
+ Object.extend NamedParameters::ClassMethods
@@ -1,5 +1,8 @@
1
- # When mixed-in, this module adds has_named_parameters class method, which
2
- # can be used to declare methods that are supposed to accepts named-parameters.
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.validate name, params, spec # :nodoc:
36
- spec[:required] ||= []
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
- spec = Hash[ spec.map{ |k, v|
40
- v = [ v ] unless v.instance_of? Array
41
- [ k, v ]
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
- sorter = lambda{ |x, y| x.to_s <=> y.to_s }
45
- allowed = (spec[:optional] + spec[:required]).sort &sorter
46
- keys = params.keys.map{ |k| k.to_sym }
47
-
48
- keys.sort! &sorter
49
- spec[:required].sort! &sorter
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
- unless spec[:required].empty?
54
- k = spec[:required] & keys
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} requires arguments for parameters: #{list[spec[:required] - k]}" \
57
- unless k == spec[:required]
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 `required` and/or `optional`
70
- # parameters will raise an `ArgumentError` if it is invoked without its
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] `method` the name of the method that is supposed to
91
+ # @param [Symbol] method the name of the method that is supposed to
79
92
  # enforce named parameters behavior.
80
93
  #
81
- # @param [Hash] `spec` the list of required and optional parameters.
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
- # @return [Hash] the specified `spec`
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
- params = args.find{ |arg| arg.instance_of? Hash }
127
- fullname = "#{owner}#{name}"
128
- NamedParameters::validate fullname, params || {}, spec
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
@@ -1,3 +1,7 @@
1
- # Extend object to automatically make it available for all
2
- # user defined classes...
3
- Object.extend NamedParameters::ClassMethods
1
+ # Do the eigenclass thingy
2
+ class Object
3
+ protected
4
+ def eigenclass # :nodoc:
5
+ class << self; self; end
6
+ end
7
+ end
@@ -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.5"
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-11}
13
- s.description = %q{This gem enables/simulates named-parameters in Ruby}
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 FooBar
5
+ class Foo
6
6
  has_named_parameters :initialize, :required => :x, :optional => [ :y, :z ]
7
- def initialize(opts = {}); end
7
+ def initialize opts = {}; end
8
8
 
9
9
  has_named_parameters :method_one, :required => :x, :optional => [ :y, :z ]
10
- def method_one(x, y, opts = {}); end
10
+ def method_one x, y, opts = {}; end
11
11
 
12
- def method_two(x, y, opts = {}); end
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
- FooBar.should respond_to :has_named_parameters
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{ FooBar.new }.should raise_error ArgumentError
22
- lambda{ FooBar.new :w => :w }.should raise_error ArgumentError
23
- lambda{ FooBar.new :x => :x }.should_not raise_error
24
- lambda{ FooBar.new :x => :x, :y => :y }.should_not raise_error
25
- lambda{ FooBar.new :x => :x, :y => :y, :z => :z }.should_not raise_error
26
- end
27
-
28
- it "should enforce named parameters for instrumented methods" do
29
- lambda{ @foobar = FooBar.new :x => :x, :y => :y, :z => :z }.should_not raise_error
30
- lambda{ @foobar.method_one :x }.should raise_error ArgumentError
31
- lambda{ @foobar.method_one :x, :y }.should raise_error ArgumentError
32
- lambda{ @foobar.method_one :x, :y, :x => :x, :y => :y, :z => :z, :w => :w }.should raise_error ArgumentError
33
- lambda{ @foobar.method_one :x => :x, :y => :y, :z => :z }.should raise_error ArgumentError
34
- lambda{ @foobar.method_one :x, :y, :w => :w }.should raise_error ArgumentError
35
- lambda{ @foobar.method_one :x, :y, :x => :x }.should_not raise_error
36
- lambda{ @foobar.method_one :x, :y, :x => :x, :y => :y }.should_not raise_error
37
- lambda{ @foobar.method_one :x, :y, :x => :x, :y => :y, :z => :z }.should_not raise_error
38
- end
39
-
40
- it "should not enforce named parameters for un-instrumented methods" do
41
- lambda{ @foobar = FooBar.new :x => :x, :y => :y, :z => :z }.should_not raise_error
42
- lambda{ @foobar.method_two :x }.should raise_error ArgumentError
43
- lambda{ @foobar.method_two :x, :y }.should_not raise_error ArgumentError
44
- lambda{ @foobar.method_two :x, :y, :w => :w }.should_not raise_error ArgumentError
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: 21
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 5
10
- version: 0.0.5
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-11 00:00:00 -08:00
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 enables/simulates named-parameters in Ruby
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