named-parameters 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,15 +1,7 @@
1
1
  This gem simulates named-parameters in Ruby. It's a complement to the common
2
2
  Ruby idiom of using `Hash` args to emulate the use of named parameters.
3
3
 
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.
6
-
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.
10
-
11
- See: the [Named Parameter](http://en.wikipedia.org/wiki/named_parameter)
12
- article from Wikipedia for more information.
4
+ Related: [Named Parameters in Ruby](http://www.jurisgalang.com/2010/11/09/named-parameters-in-ruby/)
13
5
 
14
6
  Get It
15
7
  ------
@@ -95,7 +87,7 @@ And is applicable to both class and instance methods:
95
87
  # ... do send mail stuff here ...
96
88
  end
97
89
 
98
- has_named_parameters :archive, :optional => [ :method => 'zip' ]
90
+ has_named_parameters :'self.archive', :optional => [ :method => 'zip' ]
99
91
  def self.archive options = { }
100
92
  # ... do mail archiving stuff here ...
101
93
  end
@@ -104,23 +96,25 @@ And is applicable to both class and instance methods:
104
96
  Shortcuts
105
97
  ---------
106
98
  In addition to the `has_named_parameters` method, `NamedParameters` also comes
107
- with two convenience methods for applying a parameter spec for constructors:
99
+ with two convenience methods for implicitly applying parameter specs for
100
+ constructors.
108
101
 
109
- Use the **`requires`** clause to declare what parameters a class expects when it
102
+ Use the `requires` clause to declare what parameters a class expects when it
110
103
  is instantiated:
111
104
 
112
105
  class GoogleStorage
113
- requires [ :'access-key', :'secret-key' ]
106
+ requires :'access-key', :'secret-key'
114
107
 
115
108
  def initialize options
116
109
  # ... do googly stuff here ...
117
110
  end
118
111
  end
119
112
 
120
- Use the **`recognizes`** clause to specify optional parameters for constructors:
113
+ Use the `recognizes` clause to specify the optional parameters for a class
114
+ when it is instantiated:
121
115
 
122
116
  class GoogleStorage
123
- recognizes [ :'group-email', :'apps-domain' ]
117
+ recognizes :'group-email', :'apps-domain'
124
118
 
125
119
  def initialize options
126
120
  # ... do googly stuff here ...
@@ -130,14 +124,22 @@ Use the **`recognizes`** clause to specify optional parameters for constructors:
130
124
  You may also specify default values for parameters when using these clauses:
131
125
 
132
126
  class GoogleStorage
133
- requires [ :'access-key', :'secret-key' ]
134
- recognizes [ [ :'group-email', 'group@example.org' ], [ :'apps-domain', 'example.org' ] ]
127
+ requires :'access-key', :'secret-key'
128
+ recognizes [ :'group-email', 'group@example.org' ], [ :'apps-domain', 'example.org' ]
135
129
 
136
130
  def initialize options
137
131
  # ... do googly stuff here ...
138
132
  end
139
133
  end
140
134
 
135
+ The `requires` and `recognizes` clause is equivalent to declaring the lines
136
+ in a class definition:
137
+
138
+ has_named_parameters :'self.new', :required => params, :strict
139
+ has_named_parameters :initialize, :required => params, :strict
140
+ has_named_parameters :'self.new', :optional => params, :strict
141
+ has_named_parameters :initialize, :optional => params, :strict
142
+
141
143
  Permissive Mode
142
144
  ---------------
143
145
  When a method is declared with `has_named_parameters` that method will only
@@ -173,15 +175,15 @@ The `:required` and `:oneof` parameters will still be expected:
173
175
  For clarity you should skip the `:optional` parameters list altogether when
174
176
  using the `:permissive` mode.
175
177
 
176
- The `requires` and `recognizes` clause for constructors will also accept a
177
- `mode` setting:
178
+ However, the `requires` and `recognizes` clauses does not accept the `mode` argument.
179
+ If you need to make a constructor's optional parameter spec permissive, use
180
+ the `has_named_parameters` clause instead:
178
181
 
179
- requires [ :x ], :permissive
180
- recognizes [ :y, :z ], :permissive
182
+ has_named_parameters :'self.new', :required => params, :permissive
183
+ has_named_parameters :initialize, :required => params, :permissive
181
184
 
182
- And just like the `:optional` parameter list in the `has_named_parameters`
183
- clause, when `:permissive` mode is used, it's clearer to omit the `recognizes`
184
- clause altogether.
185
+ For brevity, since the mode is `:permissive`, the `:optional` parameters list
186
+ is skipped.
185
187
 
186
188
  How It Works
187
189
  ------------
@@ -246,6 +248,69 @@ For the above case, it might be better to refactor:
246
248
 
247
249
  # result:
248
250
  # => path: /xxx, options: {}
251
+
252
+ Class vs Instance Methods
253
+ -------------------------
254
+ Parameter spec declarations are not shared between class and instance
255
+ methods even if they share the same name.
256
+
257
+ For example, the following `has_named_parameters` declaration below is only
258
+ applicable to the instance method `exec`:
259
+
260
+ class Command
261
+ has_named_parameters :exec, :required => :x
262
+ def self.exec opts
263
+ # ...
264
+ end
265
+
266
+ def exec opts
267
+ # ...
268
+ end
269
+ end
270
+
271
+ # the following will *not* raise an ArgumentError because
272
+ # the has_named_parameter declaration applies only to the
273
+ # instance method exec...
274
+ Command.exec
275
+
276
+ # the following will raise an ArgumentError (as expected)
277
+ command = Command.new
278
+ command.exec
279
+
280
+ Prefix the method name with `self.` to apply parameter spec for class methods:
281
+
282
+ class Command
283
+ has_named_parameters :'self.exec', :required => :x
284
+ def self.exec opts
285
+ # ...
286
+ end
287
+ end
288
+
289
+ # the following will now raise an ArgumentError (as expected)
290
+ Command.exec
291
+
292
+ In general, however, when a class has an instance and a class method using
293
+ the same name, for most cases, one simply delegates to another and will share
294
+ the same requirements. So the examples cited above can be refactored:
295
+
296
+ class Command
297
+ has_named_parameters :'self.exec', :required => :x
298
+ def self.exec opts
299
+ # ...
300
+ end
301
+
302
+ def exec opts
303
+ Command.exec
304
+ end
305
+ end
306
+
307
+ # the following will raise an ArgumentError (as expected)
308
+ Command.exec
309
+
310
+ # the following will also raise an ArgumentError as it delegates to the
311
+ # class method and violates the parameter requirements
312
+ command = Command.new
313
+ command.exec
249
314
 
250
315
  Dependencies
251
316
  ------------
@@ -1,3 +1,11 @@
1
+ 0.0.8 [Nov 22, 2010]
2
+ - [INTERNAL] Parameter spec will no longer be shared between singleton and
3
+ instance methods. Bonus performance improvement: it no longer needs to keep
4
+ track of the parameter specs after the class is declared.
5
+ - [INTERNAL] The mode argument is no longer entertained by the requires and
6
+ recognizes clause. Use the has_named_parameters clause on constructors if
7
+ permissive behavior is required on optional parameters.
8
+
1
9
  0.0.7 [Nov 18, 2010]
2
10
  - [FEATURE] Added support to distinguish named parameters declaration for
3
11
  class and instance methods that uses the same names. So now you could do:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.7
1
+ 0.0.8
@@ -122,45 +122,35 @@ module NamedParameters
122
122
 
123
123
  # Convenience method, equivalent to declaring:
124
124
  #
125
- # has_named_parameters :'self.new', :required => params
126
- # has_named_parameters :initialize, :required => params
125
+ # has_named_parameters :'self.new', :required => params, :strict
126
+ # has_named_parameters :initialize, :required => params, :strict
127
127
  #
128
128
  # @param [Array] params the lists of parameters. The list is expected
129
129
  # to be an `Array` of symbols matching the names of the required
130
130
  # parameters.
131
131
  #
132
- # @param [Symbol] mode enforces that only parameters that were named in
133
- # either the `:required`, `:optional`, and `:oneof` list may be allowed.
134
- # Set it to `:permissive` to relax the requirement - `:required` and `:oneof`
135
- # parameters will still be expected.
136
- #
137
- def requires params, mode = :strict
138
- [ :new, :initialize ].each do |method|
132
+ def requires *params
133
+ [ :'self.new', :initialize ].each do |method|
139
134
  spec = specs[key_for method] || { }
140
135
  spec.merge!(:required => params)
141
- has_named_parameters method, spec, mode
136
+ has_named_parameters method, spec, :strict
142
137
  end
143
138
  end
144
139
 
145
140
  # Convenience method, equivalent to declaring:
146
141
  #
147
- # has_named_parameters :'self.new', :optional => params
148
- # has_named_parameters :initialize, :optional => params
142
+ # has_named_parameters :'self.new', :optional => params, :strict
143
+ # has_named_parameters :initialize, :optional => params, :strict
149
144
  #
150
145
  # @param [Array] params the lists of parameters. The list is expected
151
146
  # to be an `Array` of symbols matching the names of the optional
152
147
  # parameters.
153
148
  #
154
- # @param [Symbol] mode enforces that only parameters that were named in
155
- # either the `:required`, `:optional`, and `:oneof` list may be allowed.
156
- # Set it to `:permissive` to relax the requirement - `:required` and `:oneof`
157
- # parameters will still be expected.
158
- #
159
- def recognizes params, mode = :strict
160
- [ :new, :initialize ].each do |method|
149
+ def recognizes *params
150
+ [ :'self.new', :initialize ].each do |method|
161
151
  spec = specs[key_for method] || { }
162
152
  spec.merge!(:optional => params)
163
- has_named_parameters method, spec, mode
153
+ has_named_parameters method, spec, :strict
164
154
  end
165
155
  end
166
156
 
@@ -193,15 +183,15 @@ module NamedParameters
193
183
  # ...
194
184
  # end
195
185
  #
196
- def validates_arguments method, param, &block
197
- # TODO: IMPLEMENT
198
- end
186
+ #def validates_arguments method, param, &block
187
+ # # TODO: IMPLEMENT
188
+ #end
199
189
 
200
190
  # add instrumentation for class methods
201
191
  def singleton_method_added name # :nodoc:
202
- instrument name do
192
+ instrument :"self.#{name}" do
203
193
  method = self.eigenclass.instance_method name
204
- spec = specs[key_for :"self.#{name}"] || specs[key_for name]
194
+ spec = specs.delete(key_for :"self.#{name}")
205
195
  owner = "#{self.name}::"
206
196
  eigenclass.instance_eval do
207
197
  intercept method, owner, name, spec
@@ -214,7 +204,7 @@ module NamedParameters
214
204
  def method_added name # :nodoc:
215
205
  instrument name do
216
206
  method = instance_method name
217
- spec = specs[key_for name] || specs[key_for :"self.#{name}"]
207
+ spec = specs.delete(key_for name)
218
208
  owner = "#{self.name}#"
219
209
  intercept method, owner, name, spec
220
210
  end
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{named-parameters}
8
- s.version = "0.0.7"
8
+ s.version = "0.0.8"
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-18}
12
+ s.date = %q{2010-11-22}
13
13
  s.description = %q{This gem simulates named-parameters in Ruby. It's a complement to the common
14
14
  Ruby idiom of using `Hash` args to emulate the use of named parameters.
15
15
 
@@ -26,29 +26,27 @@ Gem::Specification.new do |s|
26
26
  ]
27
27
  s.files = [
28
28
  ".document",
29
- ".gitignore",
30
- "GPL-LICENSE",
31
- "MIT-LICENSE",
32
- "README.md",
33
- "RELEASENOTES",
34
- "Rakefile",
35
- "VERSION",
36
- "lib/named-parameters.rb",
37
- "lib/named-parameters/module.rb",
38
- "lib/named-parameters/object.rb",
39
- "named-parameters.gemspec",
40
- "spec/named-parameters_spec.rb",
41
- "spec/spec.opts",
42
- "spec/spec_helper.rb"
29
+ "GPL-LICENSE",
30
+ "MIT-LICENSE",
31
+ "README.md",
32
+ "RELEASENOTES",
33
+ "Rakefile",
34
+ "VERSION",
35
+ "lib/named-parameters.rb",
36
+ "lib/named-parameters/module.rb",
37
+ "lib/named-parameters/object.rb",
38
+ "named-parameters.gemspec",
39
+ "spec/named-parameters_spec.rb",
40
+ "spec/spec.opts",
41
+ "spec/spec_helper.rb"
43
42
  ]
44
43
  s.homepage = %q{http://github.com/jurisgalang/named-parameters}
45
- s.rdoc_options = ["--charset=UTF-8"]
46
44
  s.require_paths = ["lib"]
47
45
  s.rubygems_version = %q{1.3.7}
48
46
  s.summary = %q{Poor man's named-parameters in Ruby}
49
47
  s.test_files = [
50
48
  "spec/named-parameters_spec.rb",
51
- "spec/spec_helper.rb"
49
+ "spec/spec_helper.rb"
52
50
  ]
53
51
 
54
52
  if s.respond_to? :specification_version then
@@ -1,17 +1,20 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
+ # TODO: reorganize the tests for clarity
4
+ # TODO: need separate spec for the NamedParameters.validate_specs method
5
+ # TODO: factor out specs for required, recognizes, and has_named_parameters
3
6
  describe "NamedParameters" do
4
7
  before :all do
5
8
  class Foo
6
9
  has_named_parameters :initialize, :required => :x, :optional => [ :y, :z ]
7
10
  def initialize opts = {}; end
8
-
11
+
9
12
  has_named_parameters :method_one, :required => :x, :optional => [ :y, :z ]
10
13
  def method_one x, y, opts = {}; end
11
-
14
+
12
15
  def method_two x, y, opts = {}; end
13
16
 
14
- has_named_parameters :method_three, :required => :x, :optional => [ :y, :z ]
17
+ has_named_parameters :'self.method_three', :required => :x, :optional => [ :y, :z ]
15
18
  def self.method_three x, y, opts = {}; end
16
19
 
17
20
  def self.method_four x, y, opts = {}; end
@@ -35,7 +38,7 @@ describe "NamedParameters" do
35
38
 
36
39
  has_named_parameters :method_with_many_optional, :optional => [ :x, :y ]
37
40
  def method_with_many_optional opts = {}; end
38
-
41
+
39
42
  has_named_parameters :method_with_one_of_each_requirement, :required => :w, :oneof => [ :x, :y ], :optional => :z
40
43
  def method_with_one_of_each_requirement opts = {}; end
41
44
  end
@@ -52,7 +55,7 @@ describe "NamedParameters" do
52
55
  lambda{ Foo.new :x => :x, :y => :y }.should_not raise_error
53
56
  lambda{ Foo.new :x => :x, :y => :y, :z => :z }.should_not raise_error
54
57
  end
55
-
58
+
56
59
  it "should enforce named parameters for instrumented instance methods" do
57
60
  lambda{ @foo = Foo.new :x => :x, :y => :y, :z => :z }.should_not raise_error
58
61
  lambda{ @foo.method_one :x }.should raise_error ArgumentError
@@ -64,7 +67,7 @@ describe "NamedParameters" do
64
67
  lambda{ @foo.method_one :x, :y, :x => :x, :y => :y }.should_not raise_error
65
68
  lambda{ @foo.method_one :x, :y, :x => :x, :y => :y, :z => :z }.should_not raise_error
66
69
  end
67
-
70
+
68
71
  it "should not enforce named parameters for un-instrumented instance methods" do
69
72
  lambda{ @foo = Foo.new :x => :x, :y => :y, :z => :z }.should_not raise_error
70
73
  lambda{ @foo.method_two :x }.should raise_error ArgumentError
@@ -135,15 +138,15 @@ describe "NamedParameters" do
135
138
  lambda{ bar.method_with_one_of_each_requirement :w => :w, :y => :y, :z => :z }.should_not raise_error
136
139
  lambda{ bar.method_with_one_of_each_requirement :w => :w, :x => :x, :z => :z, :a => :a }.should raise_error ArgumentError
137
140
  end
138
-
141
+
139
142
  it "should be able to supply the default values for optional parameters" do
140
143
  class Zoo
141
144
  has_named_parameters :method_with_one_optional_parameter, :optional => { :x => 1 }
142
145
  def method_with_one_optional_parameter opts = { }; opts[:x]; end
143
-
146
+
144
147
  has_named_parameters :method_with_many_optional_parameters, :optional => [ [ :x, 1 ], [ :y, 2 ] ]
145
148
  def method_with_many_optional_parameters opts = { }; opts[:x] + opts[:y]; end
146
-
149
+
147
150
  has_named_parameters :method_with_many_optional_parameters_too, :optional => [ { :x => 1 }, { :y => 2 } ]
148
151
  def method_with_many_optional_parameters_too opts = { }; opts[:x] + opts[:y]; end
149
152
  end
@@ -151,11 +154,11 @@ describe "NamedParameters" do
151
154
  zoo = Zoo.new
152
155
  zoo.method_with_one_optional_parameter.should eql 1
153
156
  zoo.method_with_one_optional_parameter(:x => 2).should eql 2
154
-
157
+
155
158
  zoo.method_with_many_optional_parameters.should eql 3
156
159
  zoo.method_with_many_optional_parameters(:x => 2).should eql 4
157
160
  zoo.method_with_many_optional_parameters(:x => 2, :y => 3).should eql 5
158
-
161
+
159
162
  zoo.method_with_many_optional_parameters_too.should eql 3
160
163
  zoo.method_with_many_optional_parameters_too(:x => 2).should eql 4
161
164
  zoo.method_with_many_optional_parameters_too(:x => 2, :y => 3).should eql 5
@@ -163,8 +166,10 @@ describe "NamedParameters" do
163
166
 
164
167
  it "should be able to instrument the class method new" do
165
168
  class Quux
166
- has_named_parameters :new, :required => :x
167
- def self.new opts = { }; end
169
+ has_named_parameters :'self.new', :required => :x
170
+ class << self
171
+ def new opts = { }; end
172
+ end
168
173
  def initialize opts = { }; end
169
174
  end
170
175
  lambda { Quux.new }.should raise_error ArgumentError
@@ -175,7 +180,7 @@ describe "NamedParameters" do
175
180
 
176
181
  it "should be able to specify optional parameters using the recognizes method" do
177
182
  class Recognizes
178
- recognizes [ :x, :y ]
183
+ recognizes :x, :y
179
184
  def self.new opts = { }; end
180
185
  def initialize opts = { }; end
181
186
  end
@@ -185,10 +190,10 @@ describe "NamedParameters" do
185
190
  lambda { Recognizes.new :x => :x, :y => :y }.should_not raise_error
186
191
  lambda { Recognizes.new :z => :z }.should raise_error ArgumentError
187
192
  end
188
-
193
+
189
194
  it "should be able to specify required parameters using the recognizes method" do
190
195
  class Required
191
- requires [ :x, :y ]
196
+ requires :x, :y
192
197
  def self.new opts = { }; end
193
198
  def initialize opts = { }; end
194
199
  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: 17
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 7
10
- version: 0.0.7
9
+ - 8
10
+ version: 0.0.8
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 00:00:00 -08:00
18
+ date: 2010-11-22 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -58,7 +58,6 @@ extra_rdoc_files:
58
58
  - README.md
59
59
  files:
60
60
  - .document
61
- - .gitignore
62
61
  - GPL-LICENSE
63
62
  - MIT-LICENSE
64
63
  - README.md
@@ -77,8 +76,8 @@ homepage: http://github.com/jurisgalang/named-parameters
77
76
  licenses: []
78
77
 
79
78
  post_install_message:
80
- rdoc_options:
81
- - --charset=UTF-8
79
+ rdoc_options: []
80
+
82
81
  require_paths:
83
82
  - lib
84
83
  required_ruby_version: !ruby/object:Gem::Requirement
data/.gitignore DELETED
@@ -1,21 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC