methlab 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 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