methlab 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -139,6 +139,7 @@ consequences.
139
139
  (e.g., "def foo(&block)"). Proc can be used now, but it's
140
140
  not very "rubyish" syntax for the user.
141
141
  * Better handling in Modules (def self.meth(...))
142
+ * Default values
142
143
 
143
144
  === THANKS
144
145
  --------
data/Rakefile CHANGED
@@ -63,3 +63,7 @@ task :build => [:gem, :repackage]
63
63
  task :distclean => [:clobber_package, :clobber_rdoc]
64
64
  desc "Clean the source tree"
65
65
  task :clean => [:distclean]
66
+
67
+ task :to_blog => [:clobber_rdoc, :rdoc] do
68
+ sh "rm -r $git/blog/content/docs/methlab && mv rdoc $git/blog/content/docs/methlab"
69
+ end
@@ -48,6 +48,10 @@
48
48
  # * Returning false/nil will raise a generic error.
49
49
  # * Returning a new exception object (e.g., ArgumentError.new) will raise your error as close to the call point as possible.
50
50
  # * Raising yourself will raise in the validation routine, which will probably be confusing. Please use the above method.
51
+ # * A symbol is a pragma that implies a constraint -- see below.
52
+ # * A hash is a way of specifying a pragma (or check) with a parameter:
53
+ # * :respond_to calls Object#respond_to? on the method named as the value (a symbol)
54
+ # * :default specifies a default argument. This is still checked, so get it right!
51
55
  # * If you need more than one constraint per parameter, enclose these constraints within an array.
52
56
  # * Depending on the type of method you're constructing, there will be additional constraints both implied and explictly allowed:
53
57
  # * named methods do not require any items by default, they must be specified as required.
@@ -55,7 +59,7 @@
55
59
  #
56
60
  module MethLab
57
61
 
58
- VERSION = "0.0.5"
62
+ VERSION = "0.0.6"
59
63
 
60
64
  # Integrates MethLab into all namespaces. It does this by patching itself
61
65
  # into ::main and Module.
@@ -67,6 +71,51 @@ module MethLab
67
71
  ::Module.send(:include, self)
68
72
  end
69
73
 
74
+ # internal, please do not use directly.
75
+ #
76
+ # used to set defaults on parameters that require one
77
+ def self.set_defaults(signature, params, kind=:array)
78
+ params = params[0] if kind == :hash
79
+
80
+ signature.each_with_index do |value, index|
81
+ case kind
82
+ when :array
83
+ if value.kind_of?(Array)
84
+ if hashes = value.find_all { |x| x.kind_of?(Hash) } and !hashes.empty?
85
+ hashes.each do |hash|
86
+ if hash.has_key?(:default) and (params.length - 1) < index
87
+ params[index] = hash[:default]
88
+ end
89
+ end
90
+ end
91
+ end
92
+ when :hash
93
+ if value[1].kind_of?(Array)
94
+ if hashes = value[1].find_all { |x| x.kind_of?(Hash) } and !hashes.empty?
95
+ hashes.each do |hash|
96
+ if hash.has_key?(:default) and !params.has_key?(value[0])
97
+ params[value[0]] = hash[:default]
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ # internal, please do not use directly.
107
+ #
108
+ # used to perform our standard checks that are supplied via hash.
109
+ def self.check_hash_types(value_key, value_value, value, key)
110
+ case value_key
111
+ when :respond_to
112
+ unless value.respond_to?(value_value)
113
+ return ArgumentError.new("value of argument '#{key}' does not respond to '#{value_value}'")
114
+ end
115
+ end
116
+ return nil
117
+ end
118
+
70
119
  # internal, please do not use directly.
71
120
  #
72
121
  # used to perform our standard checks.
@@ -75,7 +124,12 @@ module MethLab
75
124
  when Array
76
125
  value_sig.flatten.each do |vs|
77
126
  ret = check_type(vs, value, key)
78
- return ret unless ret.nil?
127
+ return ret if ret
128
+ end
129
+ when Hash
130
+ value_sig.each do |value_key, value_value| # GUH
131
+ ret = check_hash_types(value_key, value_value, value, key)
132
+ return ret if ret
79
133
  end
80
134
  when Class
81
135
  unless value.kind_of?(value_sig)
@@ -127,9 +181,9 @@ module MethLab
127
181
  return ArgumentError.new("argument #{key} does not exist in prototype")
128
182
  end
129
183
 
130
- if !signature[key].nil?
184
+ if signature[key]
131
185
  ret = check_type(signature[key], value, key)
132
- return ret unless ret.nil?
186
+ return ret if ret
133
187
  end
134
188
  end
135
189
 
@@ -151,9 +205,9 @@ module MethLab
151
205
  return ArgumentError.new("argument '#{key}' does not exist in prototype")
152
206
  end
153
207
 
154
- if !signature[key].nil?
208
+ if signature[key]
155
209
  ret = check_type(signature[key], value, key)
156
- return ret unless ret.nil?
210
+ return ret if ret
157
211
  end
158
212
  end
159
213
 
@@ -193,6 +247,7 @@ module MethLab
193
247
  end
194
248
 
195
249
  proc do |*args|
250
+ MethLab.set_defaults(signature, args, :array)
196
251
  params = MethLab.validate_array_params(signature, args)
197
252
  raise params if params.kind_of?(Exception)
198
253
  block.call(params)
@@ -204,7 +259,7 @@ module MethLab
204
259
  # or module. Currently cannot be a class method.
205
260
  def def_ordered(method_name, *args, &block)
206
261
  self.send(:define_method, method_name, &build_ordered(*args, &block))
207
- method_name
262
+ return method_name
208
263
  end
209
264
 
210
265
  # Builds an unbound method as a proc with named (Hash) parameters.
@@ -227,6 +282,8 @@ module MethLab
227
282
  signature = args[0]
228
283
 
229
284
  proc do |*args|
285
+ args = [{}] if args.empty?
286
+ MethLab.set_defaults(signature, args, :hash)
230
287
  params = MethLab.validate_params(signature, *args)
231
288
  raise params if params.kind_of?(Exception)
232
289
  block.call(params)
@@ -238,7 +295,7 @@ module MethLab
238
295
  # or module. Currently cannot be a class method.
239
296
  def def_named(method_name, *args, &block)
240
297
  self.send(:define_method, method_name, &build_named(*args, &block))
241
- method_name
298
+ return method_name
242
299
  end
243
300
 
244
301
  # Similar to MethLab#build_ordered, but builds attributes similar to
@@ -254,15 +311,22 @@ module MethLab
254
311
  # myobj.set_me = "String" # valid
255
312
  #
256
313
  def def_attr(method_name, arg)
314
+
257
315
  self.send(:define_method, (method_name.to_s + "=").to_sym) do |value|
258
316
  signature = [arg]
259
317
  params = MethLab.validate_array_params(signature, [value])
260
318
  raise params if params.kind_of?(Exception)
261
- send(:instance_variable_set, "@" + method_name.to_s, value)
319
+ send(:instance_variable_set, "@" + method_name.to_s, params[0])
262
320
  end
263
321
 
264
322
  self.send(:define_method, method_name) do
265
- instance_variable_get("@" + method_name.to_s)
323
+ unless self.instance_variables.select { |x| x == "@#{method_name}" }[0]
324
+ args = []
325
+ MethLab.set_defaults([arg], args, :array)
326
+ send(:instance_variable_set, "@#{method_name}", args[0])
327
+ end
328
+
329
+ instance_variable_get("@#{method_name}")
266
330
  end
267
331
  end
268
332
 
@@ -33,6 +33,16 @@ class CheckedClass
33
33
  def_ordered(:proc_raise, proc { |x| ArgumentError.new("foo") }) do |params|
34
34
  params
35
35
  end
36
+
37
+ def_named(:has_named_rt, :stuff => {:respond_to => :replace}) do |params|
38
+ params[:stuff]
39
+ end
40
+
41
+ def_ordered(:has_ordered_rt, {:respond_to => :replace}) do |params|
42
+ params[0]
43
+ end
44
+
45
+ def_attr :rt, {:respond_to => :replace}
36
46
  end
37
47
 
38
48
  $named_proc = build_named(:stuff => String) do |params|
@@ -156,4 +166,28 @@ class TestChecks < Test::Unit::TestCase
156
166
 
157
167
  assert_equal(@checked.set_me, "Foo")
158
168
  end
169
+
170
+ def test_06_respond_to
171
+ assert(@checked.respond_to?(:has_named_rt))
172
+ assert(@checked.respond_to?(:has_ordered_rt))
173
+ assert(@checked.respond_to?(:rt))
174
+
175
+ assert_raises(ArgumentError.new("value of argument '0' does not respond to 'replace'")) do
176
+ @checked.rt = nil
177
+ end
178
+
179
+ assert_raises(ArgumentError.new("value of argument '0' does not respond to 'replace'")) do
180
+ @checked.has_ordered_rt(nil)
181
+ end
182
+
183
+ assert_raises(ArgumentError.new("value of argument 'stuff' does not respond to 'replace'")) do
184
+ @checked.has_named_rt(:stuff => nil)
185
+ end
186
+
187
+ @checked.rt = "foo"
188
+
189
+ assert(@checked.rt, "foo")
190
+ assert(@checked.has_ordered_rt("foo"), "foo")
191
+ assert(@checked.has_named_rt(:stuff => "foo"), "foo")
192
+ end
159
193
  end
@@ -0,0 +1,60 @@
1
+ begin
2
+ require 'rubygems'
3
+ gem 'test-unit'
4
+ rescue LoadError
5
+ end
6
+
7
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
8
+
9
+ require 'test/unit'
10
+ require 'methlab'
11
+
12
+ MethLab.integrate
13
+
14
+ class DefaultClass
15
+ def_named(:named,
16
+ :foo => [String, {:default => "foo"}, :required],
17
+ :bar => [String, {:default => "bar"}]
18
+ ) do |params|
19
+ params
20
+ end
21
+
22
+ def_ordered(:ordered,
23
+ [String, {:default => "foo"}, :required],
24
+ [String, {:default => "bar"}]
25
+ ) do |params|
26
+ params
27
+ end
28
+
29
+ def_attr :ml_attr, [String, {:default => "foo"}]
30
+ end
31
+
32
+ class TestDefaults < Test::Unit::TestCase
33
+ def setup
34
+ @default = DefaultClass.new
35
+ end
36
+
37
+ def test_01_named
38
+ assert(@default.respond_to?(:named))
39
+
40
+ assert_equal(@default.named, {:foo => "foo", :bar => "bar"})
41
+ assert_equal(@default.named(:foo => "fixme"), {:foo => "fixme", :bar => "bar"})
42
+ assert_equal(@default.named(:foo => "fixme", :bar => "woot"), {:foo => "fixme", :bar => "woot"})
43
+ end
44
+
45
+ def test_02_ordered
46
+ assert(@default.respond_to?(:ordered))
47
+
48
+ assert_equal(@default.ordered, ["foo", "bar"])
49
+ assert_equal(@default.ordered("fixme"), ["fixme", "bar"])
50
+ assert_equal(@default.ordered("fixme", "woot"), ["fixme", "woot"])
51
+ end
52
+
53
+ def test_03_attr
54
+ assert(@default.respond_to?(:ml_attr))
55
+
56
+ assert_equal(@default.ml_attr, "foo")
57
+ @default.ml_attr = "bar"
58
+ assert_equal(@default.ml_attr, "bar")
59
+ end
60
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 5
9
- version: 0.0.5
8
+ - 6
9
+ version: 0.0.6
10
10
  platform: ruby
11
11
  authors:
12
12
  - Erik Hollensbe
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-01 00:00:00 -04:00
17
+ date: 2010-05-10 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -29,6 +29,7 @@ extra_rdoc_files: []
29
29
  files:
30
30
  - lib/methlab.rb
31
31
  - test/test_checks.rb
32
+ - test/test_defaults.rb
32
33
  - test/test_integrate.rb
33
34
  - Rakefile
34
35
  - README