myrrha 1.0.0 → 1.1.0
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/CHANGELOG.md +71 -1
- data/Gemfile.lock +3 -3
- data/README.md +140 -16
- data/examples/coerce.rb +29 -9
- data/examples/sbyc_domain.rb +38 -0
- data/lib/myrrha.rb +92 -9
- data/lib/myrrha/coerce.rb +24 -27
- data/lib/myrrha/version.rb +1 -1
- data/myrrha.gemspec +1 -1
- data/myrrha.noespec +2 -2
- data/spec/coercions/test_dup.rb +7 -0
- data/spec/coercions/test_subdomain.rb +4 -3
- data/spec/myrrha/test_coercions.rb +14 -0
- data/spec/myrrha/test_domain.rb +79 -0
- data/spec/spec_helper.rb +0 -1
- data/spec/test_coerce.rb +58 -0
- data/spec/test_myrrha.rb +37 -0
- data/tasks/examples.rake +1 -0
- metadata +25 -20
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,75 @@
|
|
1
|
+
# 1.1.0 / 2011-07-28
|
2
|
+
|
3
|
+
## Enhancements to coerce()
|
4
|
+
|
5
|
+
* Added coercion rules from Symbol/String to Module/Class
|
6
|
+
|
7
|
+
coerce("Integer", Class) # => Integer
|
8
|
+
coerce(:Integer, Class) # => Integer
|
9
|
+
coerce("Myrrha::Version", Module) # => Myrrha::Version
|
10
|
+
[... and so on ...]
|
11
|
+
|
12
|
+
* Added following coercion rules for Booleans
|
13
|
+
|
14
|
+
coerce("true", TrueClass) # => true
|
15
|
+
coerce("false", FalseClass) # => false
|
16
|
+
|
17
|
+
* Added coercion rule from any Object to String through ruby's String(). Note
|
18
|
+
that even with this coercion rule, coerce(nil, String) returns nil as that
|
19
|
+
rule has higher priority.
|
20
|
+
|
21
|
+
* require('time') is automatically issued when trying to coerce a String to
|
22
|
+
a Time. Time.parse is obviously needed.
|
23
|
+
|
24
|
+
* Myrrha::Boolean (Boolean with core extensions) is now a factored domain (see
|
25
|
+
below). Therefore, it is now a true Class instance.
|
26
|
+
|
27
|
+
## Enhancements to the general coercion mechanism
|
28
|
+
|
29
|
+
* An optimistic coercion is tried when a rule is encountered whose target
|
30
|
+
domain is a super domain of the requested one. Coercion only succeeds if
|
31
|
+
the coerced value correctly belongs to the latter domain. Example:
|
32
|
+
|
33
|
+
rules = Myrrha.coercions do |r|
|
34
|
+
r.coercion String, Numeric, lambda{|s,t| Integer(s)}
|
35
|
+
end
|
36
|
+
rules.coerce("12", Integer) # => 12 in 1.1.0 while it failed in 1.0.0
|
37
|
+
rules.coerce("12", Float) # => Myrrha::Error
|
38
|
+
|
39
|
+
* You can now specify a coercion path, through an array of domains. For
|
40
|
+
example (completely contrived, of course):
|
41
|
+
|
42
|
+
rules = Myrrha.coercions do |r|
|
43
|
+
r.coercion String, Symbol, lambda{|s,t| s.to_sym }
|
44
|
+
r.coercion Float, String, lambda{|s,t| s.to_s }
|
45
|
+
r.coercion Integer, Float, lambda{|s,t| Float(s) }
|
46
|
+
r.coercion Integer, Symbol, [Float, String]
|
47
|
+
end
|
48
|
+
rules.coerce(12, Symbol) # => :"12.0" as Symbol(String(Float(12)))
|
49
|
+
|
50
|
+
* You can now define domains through specialization by constraint (sbyc) on ruby
|
51
|
+
classes, using Myrrha.domain:
|
52
|
+
|
53
|
+
# Create a positive integer domain, as ... positive integers
|
54
|
+
PosInt = Myrrha.domain(Integer){|i| i > 0 }
|
55
|
+
|
56
|
+
Created domain is a real Class instance, that correctly responds to :===
|
57
|
+
and :superclass. The feature is mainly introduced for supporting the following
|
58
|
+
kind of coercion scenarios (see README for more about this):
|
59
|
+
|
60
|
+
rules = Myrrha.coercions do |r|
|
61
|
+
r.coercion String, Integer, lambda{|s,t| Integer(s)}
|
62
|
+
end
|
63
|
+
rules.coerce("12", PosInt) # => 12
|
64
|
+
rules.coerce("-12", PosInt) # => ArgumentError, "Invalid value -12 for PosInt"
|
65
|
+
|
66
|
+
## Bug fixes
|
67
|
+
|
68
|
+
* Fixed Coercions#dup when a set of rules has a main target domain. This fixes
|
69
|
+
the duplication of ToRubyLiteral rules, among others.
|
70
|
+
|
1
71
|
# 1.0.0 / 2011-07-22
|
2
72
|
|
3
|
-
|
73
|
+
## Enhancements
|
4
74
|
|
5
75
|
* Birthday!
|
data/Gemfile.lock
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
myrrha (1.
|
4
|
+
myrrha (1.1.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
8
8
|
specs:
|
9
|
-
bluecloth (2.0
|
9
|
+
bluecloth (2.1.0)
|
10
10
|
diff-lcs (1.1.2)
|
11
11
|
highline (1.6.2)
|
12
12
|
noe (1.3.0)
|
@@ -31,7 +31,7 @@ PLATFORMS
|
|
31
31
|
ruby
|
32
32
|
|
33
33
|
DEPENDENCIES
|
34
|
-
bluecloth (~> 2.0
|
34
|
+
bluecloth (~> 2.1.0)
|
35
35
|
bundler (~> 1.0)
|
36
36
|
myrrha!
|
37
37
|
noe (~> 1.3.0)
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Myrrha
|
1
|
+
# Myrrha (v1.1.0)
|
2
2
|
|
3
3
|
## Description
|
4
4
|
|
@@ -17,15 +17,15 @@ a numeric, a boolean, a date, a time, an URI, and so on.
|
|
17
17
|
# Bug fixes (tiny) do not even add new default rules to coerce and
|
18
18
|
# to\_ruby\_literal. Minor version can, which could break your code.
|
19
19
|
# Therefore, please always use:
|
20
|
-
gem "
|
20
|
+
gem "myrrha", "~> 1.0.0"
|
21
21
|
|
22
22
|
## Links
|
23
23
|
|
24
|
-
* http://rubydoc.info/
|
24
|
+
* http://www.rubydoc.info/gems/myrrha/1.1.0/file/README.md (read this file there!)
|
25
25
|
* http://github.com/blambeau/myrrha (source code)
|
26
26
|
* http://rubygems.org/gems/myrrha (download)
|
27
27
|
|
28
|
-
## The
|
28
|
+
## The <code>coerce()</code> feature
|
29
29
|
|
30
30
|
Myrrha.coerce(:anything, Domain)
|
31
31
|
coerce(:anything, Domain) # with core extensions
|
@@ -48,34 +48,71 @@ possible and even straightforward:
|
|
48
48
|
end
|
49
49
|
# => [12, true, #<Date: 2011-07-20 (...)>]
|
50
50
|
|
51
|
-
###
|
51
|
+
### Implemented coercions
|
52
|
+
|
53
|
+
Implemented coercions are somewhat conservative, and only use a subset of what
|
54
|
+
ruby provides here and there. This is to avoid strangeness ala PHP... The
|
55
|
+
general philosophy is to provide the natural coercions we apply everyday.
|
56
|
+
|
57
|
+
The master rules are
|
58
|
+
|
59
|
+
* <code>coerce(value, Domain)</code> return <code>value</code> if
|
60
|
+
<code>belongs_to?(value, Domain)</code> is true (see last section below)
|
61
|
+
* <code>coerce(value, Domain)</code> returns <code>Domain.coerce(value)</code>
|
62
|
+
if the latter method exists.
|
63
|
+
* <code>coerce("any string", Domain)</code> returns <code>Domain.parse(value)</code>
|
64
|
+
if the latter method exists.
|
65
|
+
|
66
|
+
The specific implemented rules are
|
52
67
|
|
53
68
|
require 'myrrha/with_core_ext'
|
54
69
|
require 'myrrha/coerce'
|
55
70
|
|
56
|
-
#
|
71
|
+
# NilClass -> _Anything_ returns nil, always
|
72
|
+
coerce(nil, Integer) # => nil
|
73
|
+
|
74
|
+
# Object -> String, via ruby's String()
|
75
|
+
coerce("hello", String) # => "hello"
|
76
|
+
coerce(:hello, String) # => "hello"
|
77
|
+
|
78
|
+
# String -> Numeric, through ruby's Integer() and Float()
|
57
79
|
coerce("12", Integer) # => 12
|
58
80
|
coerce("12.0", Float) # => 12.0
|
59
81
|
|
60
|
-
#
|
82
|
+
# String -> Numeric is smart enough:
|
83
|
+
coerce("12", Numeric) # => 12 (Integer)
|
84
|
+
coerce("12.0", Numeric) # => 12.0 (Float)
|
85
|
+
|
86
|
+
# String -> Regexp, through Regexp.compile
|
61
87
|
coerce("[a-z]+", Regexp) # => /[a-z]+/
|
62
88
|
|
63
|
-
#
|
89
|
+
# String -> Symbol, through to_sym
|
90
|
+
coerce("hello", Symbol) # => :hello
|
91
|
+
|
92
|
+
# String -> Boolean (hum, sorry Matz!)
|
64
93
|
coerce("true", Boolean) # => true
|
65
94
|
coerce("false", Boolean) # => false
|
95
|
+
coerce("true", TrueClass) # => true
|
96
|
+
coerce("false", FalseClass) # => false
|
66
97
|
|
67
|
-
#
|
98
|
+
# String -> Date, through Date.parse
|
68
99
|
require 'date'
|
69
|
-
require 'time'
|
70
100
|
coerce("2011-07-20", Date) # => #<Date: 2011-07-20 (4911525/2,0,2299161)>
|
101
|
+
|
102
|
+
# String -> Time, through Time.parse (just in time issuing of require('time'))
|
71
103
|
coerce("2011-07-20 10:57", Time) # => 2011-07-20 10:57:00 +0200
|
72
104
|
|
73
|
-
#
|
105
|
+
# String -> URI, through URI.parse
|
74
106
|
require 'uri'
|
75
107
|
coerce('http://google.com', URI) # => #<URI::HTTP:0x8281ce0 URL:http://google.com>
|
76
108
|
|
77
|
-
#
|
78
|
-
coerce(
|
109
|
+
# String -> Class and Module through constant lookup
|
110
|
+
coerce("Integer", Class) # => Integer
|
111
|
+
coerce("Myrrha::Version", Module) # => Myrrha::Version
|
112
|
+
|
113
|
+
# Symbol -> Class and Module through constant lookup
|
114
|
+
coerce(:Integer, Class) # => Integer
|
115
|
+
coerce(:Enumerable, Module) # => Enumerable
|
79
116
|
|
80
117
|
### No core extension? no problem!
|
81
118
|
|
@@ -133,7 +170,7 @@ might be intrusive. Why not using your own set of coercion rules?
|
|
133
170
|
MyRules.apply(:hello, Foo)
|
134
171
|
# => #<Foo:0x8b7d254 @arg=:hello>
|
135
172
|
|
136
|
-
## The
|
173
|
+
## The <code>to\_ruby\_literal()</code> feature
|
137
174
|
|
138
175
|
Myrrha.to_ruby_literal([:anything])
|
139
176
|
[:anything].to_ruby_literal # with core extensions
|
@@ -291,7 +328,41 @@ which PRE holds are executed in order, until one succeed (chain of
|
|
291
328
|
responsibility design pattern). This means that coercions always execute in
|
292
329
|
<code>O(number of rules)</code>.
|
293
330
|
|
294
|
-
###
|
331
|
+
### Specifying converters
|
332
|
+
|
333
|
+
A converter is the third (resp. second) element specified in a coercion rules
|
334
|
+
(resp. an upon or fallback rule). A converter is generally a Proc of arity 2,
|
335
|
+
which is passed the source value and requested target domain.
|
336
|
+
|
337
|
+
Myrrha.coercions do |r|
|
338
|
+
r.coercion String, Numeric, lambda{|value,requested_domain|
|
339
|
+
# this is converter code
|
340
|
+
}
|
341
|
+
end
|
342
|
+
convert("12", Integer)
|
343
|
+
|
344
|
+
A converter may also be specified as an array of domains. In this case, it is
|
345
|
+
assumed that they for a path inside the convertion graph. Consider for example
|
346
|
+
the following coercion rules (contrived example)
|
347
|
+
|
348
|
+
rules = Myrrha.coercions do |r|
|
349
|
+
r.coercion String, Symbol, lambda{|s,t| s.to_sym } # 1
|
350
|
+
r.coercion Float, String, lambda{|s,t| s.to_s } # 2
|
351
|
+
r.coercion Integer, Float, lambda{|s,t| Float(s) } # 3
|
352
|
+
r.coercion Integer, Symbol, [Float, String] # 4
|
353
|
+
end
|
354
|
+
|
355
|
+
The last rule specifies a convertion path, through intermediate domains. The
|
356
|
+
complete rule specifies that applying the following path will work
|
357
|
+
|
358
|
+
Integer -> Float -> String -> Symbol
|
359
|
+
#3 #2 #1
|
360
|
+
|
361
|
+
Indeed,
|
362
|
+
|
363
|
+
rules.coerce(12, Symbol) # => :"12.0"
|
364
|
+
|
365
|
+
### Semantics of <code>belongs\_to?</code> and <code>subdomain?</code>
|
295
366
|
|
296
367
|
The pseudo-code given above relies on two main abstractions. Suppose the user
|
297
368
|
makes a call to <code>coerce(value, requested_domain)</code>:
|
@@ -305,6 +376,8 @@ makes a call to <code>coerce(value, requested_domain)</code>:
|
|
305
376
|
|
306
377
|
* <code>subdomain?(SourceDomain,TargetDomain)</code> is true iif
|
307
378
|
* <code>SourceDomain == TargetDomain</code> yields true
|
379
|
+
* TargetDomain respond to <code>:superdomain_of?</code> and answers true on
|
380
|
+
SourceDomain
|
308
381
|
* SourceDomain and TargetDomain are both classes and the latter is a super
|
309
382
|
class of the former
|
310
383
|
|
@@ -334,4 +407,55 @@ makes a call to <code>coerce(value, requested_domain)</code>:
|
|
334
407
|
# this is your last change, an Myrrha::Error will be raised if you fail
|
335
408
|
end
|
336
409
|
|
337
|
-
end
|
410
|
+
end
|
411
|
+
|
412
|
+
### Factoring domains through specialization by constraint
|
413
|
+
|
414
|
+
Specialization by constraint (SByC) is a theory of types for which the following
|
415
|
+
rules hold:
|
416
|
+
|
417
|
+
* A type (aka domain) is a set of values
|
418
|
+
* A sub-type is a subset
|
419
|
+
* A sub-type can therefore be specified through a predicate on the super domain
|
420
|
+
|
421
|
+
For example, "positive integers" is a sub type of "integers" where the predicate
|
422
|
+
is "value > 0".
|
423
|
+
|
424
|
+
Myrrha comes with a small feature allowing you to create types 'ala' SByC:
|
425
|
+
|
426
|
+
PosInt = Myrrha.domain(Integer){|i| i > 0}
|
427
|
+
PosInt.name # => "PosInt"
|
428
|
+
PosInt.class # => Class
|
429
|
+
PosInt.superclass # => Integer
|
430
|
+
PosInt.ancestors # => [PosInt, Integer, Numeric, Comparable, Object, Kernel, BasicObject]
|
431
|
+
PosInt === 10 # => true
|
432
|
+
PosInt === -1 # => false
|
433
|
+
PosInt.new(10) # => 10
|
434
|
+
PosInt.new(-10) # => ArgumentError, "Invalid value -10 for PosInt"
|
435
|
+
|
436
|
+
Note that the feature is very limited, and is not intended to provide a truly
|
437
|
+
coherent typing framework. For example:
|
438
|
+
|
439
|
+
10.is_a?(PosInt) # => false
|
440
|
+
10.kind_of?(PosInt) # => false
|
441
|
+
|
442
|
+
Instead, Myrrha domains are only provided as an helper to build sound coercions
|
443
|
+
rules easily while 1) keeping a Class-based approach to source and target
|
444
|
+
domains and 2) having friendly error messages 3) really supporting true
|
445
|
+
reasoning on types and value:
|
446
|
+
|
447
|
+
# Only a rule that converts String to Integer
|
448
|
+
rules = Myrrha.coercions do |r|
|
449
|
+
r.coercion String, Integer, lambda{|s,t| Integer(s)}
|
450
|
+
end
|
451
|
+
|
452
|
+
# it succeeds on both integers and positive integers
|
453
|
+
rules.coerce("12", Integer) # => 12
|
454
|
+
rules.coerce("12", PosInt) # => 12
|
455
|
+
|
456
|
+
# and correctly fails in each case!
|
457
|
+
rules.coerce("-12", Integer) # => -12
|
458
|
+
rules.coerce("-12", PosInt) # => ArgumentError, "Invalid value -12 for PosInt"
|
459
|
+
|
460
|
+
|
461
|
+
|
data/examples/coerce.rb
CHANGED
@@ -1,26 +1,46 @@
|
|
1
1
|
require 'myrrha/with_core_ext'
|
2
2
|
require 'myrrha/coerce'
|
3
3
|
|
4
|
-
#
|
4
|
+
# NilClass -> _Anything_ returns nil, always
|
5
|
+
coerce(nil, Integer) # => nil
|
6
|
+
|
7
|
+
# Object -> String, via ruby's String()
|
8
|
+
coerce("hello", String) # => "hello"
|
9
|
+
coerce(:hello, String) # => "hello"
|
10
|
+
|
11
|
+
# String -> Numeric, through ruby's Integer() and Float()
|
5
12
|
coerce("12", Integer) # => 12
|
6
13
|
coerce("12.0", Float) # => 12.0
|
7
14
|
|
8
|
-
#
|
15
|
+
# String -> Numeric is smart enough:
|
16
|
+
coerce("12", Numeric) # => 12 (Integer)
|
17
|
+
coerce("12.0", Numeric) # => 12.0 (Float)
|
18
|
+
|
19
|
+
# String -> Regexp, through Regexp.compile
|
9
20
|
coerce("[a-z]+", Regexp) # => /[a-z]+/
|
10
21
|
|
11
|
-
#
|
22
|
+
# String -> Symbol, through to_sym
|
23
|
+
coerce("hello", Symbol) # => :hello
|
24
|
+
|
25
|
+
# String -> Boolean (hum, sorry Matz!)
|
12
26
|
coerce("true", Boolean) # => true
|
13
27
|
coerce("false", Boolean) # => false
|
14
28
|
|
15
|
-
#
|
29
|
+
# String -> Date, through Date.parse
|
16
30
|
require 'date'
|
17
|
-
require 'time'
|
18
31
|
coerce("2011-07-20", Date) # => #<Date: 2011-07-20 (4911525/2,0,2299161)>
|
32
|
+
|
33
|
+
# String -> Time, through Time.parse (just in time issuing of require('time'))
|
19
34
|
coerce("2011-07-20 10:57", Time) # => 2011-07-20 10:57:00 +0200
|
20
35
|
|
21
|
-
#
|
36
|
+
# String -> URI, through URI.parse
|
22
37
|
require 'uri'
|
23
|
-
coerce('http://google.com', URI) # => #<URI::HTTP:0x8281ce0 URL:http://google.com>
|
38
|
+
coerce('http://google.com', URI) # => #<URI::HTTP:0x8281ce0 URL:http://google.com>
|
39
|
+
|
40
|
+
# String -> Class and Module through constant lookup
|
41
|
+
coerce("Integer", Class) # => Integer
|
42
|
+
coerce("Myrrha::Version", Module) # => Myrrha::Version
|
24
43
|
|
25
|
-
#
|
26
|
-
coerce(
|
44
|
+
# Symbol -> Class and Module through constant lookup
|
45
|
+
coerce(:Integer, Class) # => Integer
|
46
|
+
coerce(:Enumerable, Module) # => Enumerable
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'myrrha'
|
2
|
+
|
3
|
+
PosInt = Myrrha.domain(Integer){|i| i>0}
|
4
|
+
|
5
|
+
###
|
6
|
+
|
7
|
+
PosInt.class
|
8
|
+
PosInt.superclass
|
9
|
+
PosInt.ancestors
|
10
|
+
PosInt === 10
|
11
|
+
PosInt === -1
|
12
|
+
PosInt.new(10)
|
13
|
+
begin
|
14
|
+
PosInt.new(-10)
|
15
|
+
raise "Unexpected case: PosInt.new(-10) succeeds"
|
16
|
+
rescue ArgumentError => ex
|
17
|
+
puts ex.message
|
18
|
+
end
|
19
|
+
|
20
|
+
###
|
21
|
+
|
22
|
+
10.is_a?(PosInt)
|
23
|
+
10.kind_of?(PosInt)
|
24
|
+
|
25
|
+
###
|
26
|
+
|
27
|
+
rules = Myrrha.coercions do |r|
|
28
|
+
r.coercion String, Integer, lambda{|s,t| Integer(s)}
|
29
|
+
end
|
30
|
+
rules.coerce("12", Integer)
|
31
|
+
rules.coerce("12", PosInt)
|
32
|
+
rules.coerce("-12", Integer)
|
33
|
+
begin
|
34
|
+
rules.coerce("-12", PosInt)
|
35
|
+
raise "Unexpected case: rules.coerce('-12', PosInt) succeeds"
|
36
|
+
rescue Myrrha::Error => ex
|
37
|
+
puts ex.message
|
38
|
+
end
|
data/lib/myrrha.rb
CHANGED
@@ -8,6 +8,23 @@ module Myrrha
|
|
8
8
|
#
|
9
9
|
class Error < StandardError; end
|
10
10
|
|
11
|
+
#
|
12
|
+
# Creates a domain instance by specialization by constraint
|
13
|
+
#
|
14
|
+
# @param [Class] superdom the superdomain of the created domain
|
15
|
+
# @param [Proc] pred the domain predicate
|
16
|
+
# @return [Class] the created domain
|
17
|
+
#
|
18
|
+
def self.domain(superdom = Object, subdoms=nil, &pred)
|
19
|
+
dom = Class.new(superdom).extend(Domain)
|
20
|
+
dom.instance_eval {
|
21
|
+
@sub_domains = subdoms
|
22
|
+
@super_domain = superdom
|
23
|
+
@predicate = pred
|
24
|
+
}
|
25
|
+
dom
|
26
|
+
end
|
27
|
+
|
11
28
|
#
|
12
29
|
# Builds a set of coercions rules.
|
13
30
|
#
|
@@ -26,6 +43,58 @@ module Myrrha
|
|
26
43
|
end
|
27
44
|
|
28
45
|
#
|
46
|
+
# Encapsulates class methods of created domains
|
47
|
+
#
|
48
|
+
module Domain
|
49
|
+
|
50
|
+
#
|
51
|
+
# Creates a new instance of this domain
|
52
|
+
#
|
53
|
+
def new(*args)
|
54
|
+
if (args.size == 1) && (superclass === args.first)
|
55
|
+
if self === args.first
|
56
|
+
args.first
|
57
|
+
else
|
58
|
+
raise ArgumentError, "Invalid value #{args.join(' ')} for #{self}"
|
59
|
+
end
|
60
|
+
elsif superclass.respond_to?(:new)
|
61
|
+
new(super(*args))
|
62
|
+
else
|
63
|
+
raise ArgumentError, "Invalid value #{args.join(' ')} for #{self}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# (see Class.superclass)
|
68
|
+
def superclass
|
69
|
+
@super_domain
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Checks if `value` belongs to this domain
|
74
|
+
#
|
75
|
+
def ===(value)
|
76
|
+
(superclass === value) && @predicate.call(value)
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# Returns true if clazz if an explicit sub domain of self or if it's the
|
81
|
+
# case in Ruby.
|
82
|
+
#
|
83
|
+
def superdomain_of?(child)
|
84
|
+
Array(@sub_domains).include?(child)
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Returns the specialization by constraint predicate
|
89
|
+
#
|
90
|
+
# @return [Proc] the domain predicate
|
91
|
+
#
|
92
|
+
def predicate
|
93
|
+
@predicate
|
94
|
+
end
|
95
|
+
|
96
|
+
end # module Domain
|
97
|
+
|
29
98
|
# Defines a set of coercion rules
|
30
99
|
#
|
31
100
|
class Coercions
|
@@ -36,11 +105,12 @@ module Myrrha
|
|
36
105
|
#
|
37
106
|
# Creates an empty list of coercion rules
|
38
107
|
#
|
39
|
-
def initialize(upons = [], rules = [], fallbacks = [])
|
108
|
+
def initialize(upons = [], rules = [], fallbacks = [], main_target_domain = nil)
|
40
109
|
@upons = upons
|
41
110
|
@rules = rules
|
42
111
|
@fallbacks = fallbacks
|
43
112
|
@appender = :<<
|
113
|
+
@main_target_domain = main_target_domain
|
44
114
|
yield(self) if block_given?
|
45
115
|
end
|
46
116
|
|
@@ -183,11 +253,16 @@ module Myrrha
|
|
183
253
|
error = nil
|
184
254
|
each_rule do |from,to,converter|
|
185
255
|
next unless from.nil? or belongs_to?(value, from, target_domain)
|
186
|
-
next unless to.nil? or subdomain?(to, target_domain)
|
187
256
|
begin
|
188
|
-
catch(:nextrule)
|
189
|
-
|
190
|
-
|
257
|
+
catch(:nextrule) do
|
258
|
+
if to.nil? or subdomain?(to, target_domain)
|
259
|
+
got = convert(value, target_domain, converter)
|
260
|
+
return got
|
261
|
+
elsif subdomain?(target_domain, to)
|
262
|
+
got = convert(value, to, converter)
|
263
|
+
return got if belongs_to?(got, target_domain)
|
264
|
+
end
|
265
|
+
end
|
191
266
|
rescue => ex
|
192
267
|
error = ex.message unless error
|
193
268
|
end
|
@@ -233,10 +308,15 @@ module Myrrha
|
|
233
308
|
# otherwise.
|
234
309
|
#
|
235
310
|
def subdomain?(child, parent)
|
236
|
-
|
237
|
-
|
238
|
-
|
311
|
+
if child == parent
|
312
|
+
true
|
313
|
+
elsif parent.respond_to?(:superdomain_of?)
|
314
|
+
parent.superdomain_of?(child)
|
315
|
+
elsif child.respond_to?(:superclass) && child.superclass
|
316
|
+
subdomain?(child.superclass, parent)
|
317
|
+
else
|
239
318
|
false
|
319
|
+
end
|
240
320
|
end
|
241
321
|
|
242
322
|
#
|
@@ -246,7 +326,7 @@ module Myrrha
|
|
246
326
|
# @return [Coercions] a copy of this set of rules
|
247
327
|
#
|
248
328
|
def dup
|
249
|
-
Coercions.new(@upons.dup, @rules.dup, @fallbacks.dup)
|
329
|
+
Coercions.new(@upons.dup, @rules.dup, @fallbacks.dup, main_target_domain)
|
250
330
|
end
|
251
331
|
|
252
332
|
private
|
@@ -273,6 +353,9 @@ module Myrrha
|
|
273
353
|
def convert(value, target_domain, converter)
|
274
354
|
if converter.respond_to?(:call)
|
275
355
|
converter.call(value, target_domain)
|
356
|
+
elsif converter.is_a?(Array)
|
357
|
+
path = converter + [target_domain]
|
358
|
+
path.inject(value){|cur,ndom| coerce(cur, ndom)}
|
276
359
|
else
|
277
360
|
raise ArgumentError, "Unable to use #{converter} for coercing"
|
278
361
|
end
|
data/lib/myrrha/coerce.rb
CHANGED
@@ -2,29 +2,12 @@ require 'myrrha'
|
|
2
2
|
module Myrrha
|
3
3
|
|
4
4
|
#
|
5
|
-
# Defines the missing Boolean
|
5
|
+
# Defines the missing Boolean as a Myrrha's domain
|
6
6
|
#
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
Boolean = Myrrha.domain(Object, [TrueClass, FalseClass]){|x|
|
8
|
+
(x==true) || (x==false)
|
9
|
+
}
|
10
10
|
|
11
|
-
#
|
12
|
-
# Returns Object, as the superclass of Boolean
|
13
|
-
#
|
14
|
-
# @return [Class] Object
|
15
|
-
#
|
16
|
-
def self.superclass; Object; end
|
17
|
-
|
18
|
-
#
|
19
|
-
# Returns true if `val` is <code>true</code> or <code>false</code>, false
|
20
|
-
# otherwise.
|
21
|
-
#
|
22
|
-
def self.===(val)
|
23
|
-
(val == true) || (val == false)
|
24
|
-
end
|
25
|
-
|
26
|
-
end # module Boolean
|
27
|
-
|
28
11
|
#
|
29
12
|
# Coerces _s_ to a Boolean
|
30
13
|
#
|
@@ -48,6 +31,14 @@ module Myrrha
|
|
48
31
|
# Defines basic coercions for Ruby, mostly from String
|
49
32
|
Coerce = coercions do |g|
|
50
33
|
|
34
|
+
# Returns a constant denoted by `s`
|
35
|
+
def g.constant_lookup(s, target_domain)
|
36
|
+
found = (s.split('::') - [""]).inject(Kernel){|cur,n|
|
37
|
+
cur.const_get(n.to_sym)
|
38
|
+
}
|
39
|
+
belongs_to?(found, target_domain) ? found : throw(:nextrule)
|
40
|
+
end
|
41
|
+
|
51
42
|
# NilClass should return immediately
|
52
43
|
g.upon(NilClass) do |s,t|
|
53
44
|
nil
|
@@ -59,12 +50,18 @@ module Myrrha
|
|
59
50
|
end
|
60
51
|
|
61
52
|
# Specific basic rules
|
62
|
-
g.coercion String,
|
63
|
-
g.coercion String,
|
64
|
-
g.coercion String,
|
65
|
-
g.coercion
|
66
|
-
g.coercion
|
67
|
-
g.coercion String,
|
53
|
+
g.coercion Object, String, lambda{|s,t| String(s) }
|
54
|
+
g.coercion String, Integer, lambda{|s,t| Integer(s) }
|
55
|
+
g.coercion String, Float, lambda{|s,t| Float(s) }
|
56
|
+
g.coercion String, Boolean, lambda{|s,t| Boolean(s) }
|
57
|
+
g.coercion Integer, Float, lambda{|s,t| Float(s) }
|
58
|
+
g.coercion String, Symbol, lambda{|s,t| s.to_sym }
|
59
|
+
g.coercion String, Regexp, lambda{|s,t| Regexp.compile(s) }
|
60
|
+
g.coercion Symbol, Class, lambda{|s,t| g.constant_lookup(s.to_s, t) }
|
61
|
+
g.coercion Symbol, Module, lambda{|s,t| g.constant_lookup(s.to_s, t) }
|
62
|
+
g.coercion String, Class, lambda{|s,t| g.constant_lookup(s, t) }
|
63
|
+
g.coercion String, Module, lambda{|s,t| g.constant_lookup(s, t) }
|
64
|
+
g.coercion String, Time, lambda{|s,t| require 'time'; Time.parse(s) }
|
68
65
|
|
69
66
|
# By default, we try to invoke :parse on the class
|
70
67
|
g.fallback(String) do |s,t|
|
data/lib/myrrha/version.rb
CHANGED
data/myrrha.gemspec
CHANGED
@@ -127,7 +127,7 @@ Gem::Specification.new do |s|
|
|
127
127
|
s.add_development_dependency("bundler", "~> 1.0")
|
128
128
|
s.add_development_dependency("rspec", "~> 2.6.0")
|
129
129
|
s.add_development_dependency("yard", "~> 0.7.2")
|
130
|
-
s.add_development_dependency("bluecloth", "~> 2.0
|
130
|
+
s.add_development_dependency("bluecloth", "~> 2.1.0")
|
131
131
|
s.add_development_dependency("wlang", "~> 0.10.1")
|
132
132
|
s.add_development_dependency("noe", "~> 1.3.0")
|
133
133
|
|
data/myrrha.noespec
CHANGED
@@ -9,7 +9,7 @@ variables:
|
|
9
9
|
upper:
|
10
10
|
Myrrha
|
11
11
|
version:
|
12
|
-
1.
|
12
|
+
1.1.0
|
13
13
|
summary: |-
|
14
14
|
Myrrha provides the coercion framework which is missing to Ruby, IMHO.
|
15
15
|
description: |-
|
@@ -29,7 +29,7 @@ variables:
|
|
29
29
|
- {name: bundler, version: "~> 1.0", groups: [development]}
|
30
30
|
- {name: rspec, version: "~> 2.6.0", groups: [development]}
|
31
31
|
- {name: yard, version: "~> 0.7.2", groups: [development]}
|
32
|
-
- {name: bluecloth, version: "~> 2.0
|
32
|
+
- {name: bluecloth, version: "~> 2.1.0", groups: [development]}
|
33
33
|
- {name: wlang, version: "~> 0.10.1", groups: [development]}
|
34
34
|
- {name: noe, version: "~> 1.3.0", groups: [development]}
|
35
35
|
rake_tasks:
|
data/spec/coercions/test_dup.rb
CHANGED
@@ -16,6 +16,13 @@ module Myrrha
|
|
16
16
|
dupped.coerce("12", Float).should eql(12.0)
|
17
17
|
lambda{ rules.coerce("12", Float) }.should raise_error(Myrrha::Error)
|
18
18
|
end
|
19
|
+
|
20
|
+
it "should not forget main_target_domain" do
|
21
|
+
rules = Coercions.new do |r|
|
22
|
+
r.main_target_domain = Integer
|
23
|
+
end
|
24
|
+
rules.dup.main_target_domain.should eql(Integer)
|
25
|
+
end
|
19
26
|
|
20
27
|
end
|
21
28
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
module Myrrha
|
3
3
|
describe "Coercions#subdomain?" do
|
4
|
-
let(:
|
4
|
+
let(:r){ Coercions.new }
|
5
5
|
|
6
6
|
specify {
|
7
|
-
|
7
|
+
r.subdomain?(Symbol, Object).should be_true
|
8
|
+
r.subdomain?(Class, Module).should be_true
|
8
9
|
}
|
9
|
-
|
10
|
+
|
10
11
|
end
|
11
12
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe "Myrrha.coercions" do
|
3
|
+
|
4
|
+
it "should support using user-defined domains" do
|
5
|
+
name = Myrrha.domain{|s| s.is_a?(Symbol)}
|
6
|
+
rules = Myrrha.coercions do |r|
|
7
|
+
r.coercion String, name, lambda{|s,t| s.to_sym}
|
8
|
+
r.coercion name, String, lambda{|s,t| s.to_s}
|
9
|
+
end
|
10
|
+
rules.coerce("hello", name).should eq(:hello)
|
11
|
+
rules.coerce(:hello, String).should eq("hello")
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Myrrha
|
3
|
+
describe "#domain" do
|
4
|
+
|
5
|
+
specify "the basic contract" do
|
6
|
+
subject = Myrrha.domain{|s| s == 12}
|
7
|
+
subject.should be_a(Class)
|
8
|
+
subject.superclass.should eq(Object)
|
9
|
+
(subject === 12).should be_true
|
10
|
+
(subject === 13).should be_false
|
11
|
+
end
|
12
|
+
|
13
|
+
specify "with a ruby superclass" do
|
14
|
+
subject = Myrrha.domain(Integer){|i| i > 0}
|
15
|
+
subject.should be_a(Class)
|
16
|
+
subject.superclass.should eq(Integer)
|
17
|
+
(subject === 12).should be_true
|
18
|
+
(subject === 0).should be_false
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "A factored sub domain of Integer" do
|
22
|
+
PosInt = Myrrha.domain(Integer){|i| i > 0}
|
23
|
+
specify("#name") {
|
24
|
+
PosInt.name.should eq("Myrrha::PosInt")
|
25
|
+
}
|
26
|
+
specify("#new") {
|
27
|
+
PosInt.new(12).should eq(12)
|
28
|
+
lambda {
|
29
|
+
PosInt.new(0)
|
30
|
+
}.should raise_error(ArgumentError)
|
31
|
+
}
|
32
|
+
specify("#superclass"){
|
33
|
+
PosInt.superclass.should eql(Integer)
|
34
|
+
}
|
35
|
+
specify("#superdomain_of?"){
|
36
|
+
PosInt.superdomain_of?(Object).should be_false
|
37
|
+
PosInt.superdomain_of?(Integer).should be_false
|
38
|
+
}
|
39
|
+
it "should be usable in a case" do
|
40
|
+
[-12, 12].collect{|i|
|
41
|
+
case i
|
42
|
+
when PosInt
|
43
|
+
:posint
|
44
|
+
when Integer
|
45
|
+
:integer
|
46
|
+
end
|
47
|
+
}.should eq([:integer, :posint])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "A factored sub domain of a user-defined Class" do
|
52
|
+
class Color
|
53
|
+
attr_reader :r
|
54
|
+
attr_reader :g
|
55
|
+
attr_reader :b
|
56
|
+
def initialize(r,g,b)
|
57
|
+
raise ArgumentError unless [r,g,b].all?{|i| i.is_a?(Integer)}
|
58
|
+
@r, @g, @b = r, g, b
|
59
|
+
end
|
60
|
+
end
|
61
|
+
RedToZero = Myrrha.domain(Color){|c| c.r == 0}
|
62
|
+
specify("#===") {
|
63
|
+
(RedToZero === Color.new(0,1,1)).should be_true
|
64
|
+
(RedToZero === Color.new(1,1,1)).should be_false
|
65
|
+
}
|
66
|
+
specify("#new") {
|
67
|
+
RedToZero.new(Color.new(0,1,1)).should be_a(Color)
|
68
|
+
RedToZero.new(0, 1, 1).should be_a(Color)
|
69
|
+
lambda{
|
70
|
+
RedToZero.new(Color.new(1,1,1))
|
71
|
+
}.should raise_error(ArgumentError)
|
72
|
+
lambda{
|
73
|
+
RedToZero.new(1, 1, 1)
|
74
|
+
}.should raise_error(ArgumentError)
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/test_coerce.rb
CHANGED
@@ -8,6 +8,18 @@ describe "::Ruby's coercion " do
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
describe "to String" do
|
12
|
+
specify "from Integer" do
|
13
|
+
coerce(12, String).should eql("12")
|
14
|
+
end
|
15
|
+
specify "from String" do
|
16
|
+
coerce("12", String).should eql("12")
|
17
|
+
end
|
18
|
+
specify "from NilClass" do
|
19
|
+
coerce(nil, String).should be_nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
11
23
|
describe "to Integer" do
|
12
24
|
specify "from Integer" do
|
13
25
|
coerce(12, Integer).should eql(12)
|
@@ -62,6 +74,20 @@ describe "::Ruby's coercion " do
|
|
62
74
|
lambda{coerce("abc", Boolean)}.should raise_error(Myrrha::Error)
|
63
75
|
end
|
64
76
|
end
|
77
|
+
|
78
|
+
describe "to TrueClass" do
|
79
|
+
specify "from String" do
|
80
|
+
coerce("true", TrueClass).should eql(true)
|
81
|
+
lambda{ coerce("false", TrueClass) }.should raise_error(Myrrha::Error)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "to FalseClass" do
|
86
|
+
specify "from String" do
|
87
|
+
coerce("false", FalseClass).should eql(false)
|
88
|
+
lambda{ coerce("true", FalseClass) }.should raise_error(Myrrha::Error)
|
89
|
+
end
|
90
|
+
end
|
65
91
|
|
66
92
|
describe "to Date" do
|
67
93
|
let(:expected){ Date.parse("2011-07-20") }
|
@@ -102,6 +128,38 @@ describe "::Ruby's coercion " do
|
|
102
128
|
coerce("http://www.google.com/", URI).should eql(URI.parse("http://www.google.com/"))
|
103
129
|
end
|
104
130
|
end
|
131
|
+
|
132
|
+
describe "to Module" do
|
133
|
+
specify "from String" do
|
134
|
+
coerce("Kernel", Module).should eql(Kernel)
|
135
|
+
coerce("::Kernel", Module).should eql(Kernel)
|
136
|
+
coerce("Myrrha::Version", Module).should eql(Myrrha::Version)
|
137
|
+
coerce("::Myrrha::Version", Module).should eql(Myrrha::Version)
|
138
|
+
coerce("Myrrha::Coercions", Module).should eql(Myrrha::Coercions)
|
139
|
+
end
|
140
|
+
specify "from Symbol" do
|
141
|
+
coerce(:Kernel, Module).should eql(Kernel)
|
142
|
+
end
|
143
|
+
it "should raise error if not a module" do
|
144
|
+
lambda{
|
145
|
+
coerce("Myrrha::VERSION", Module)
|
146
|
+
}.should raise_error(Myrrha::Error)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "to Class" do
|
151
|
+
specify "from String" do
|
152
|
+
coerce("Myrrha::Coercions", Class).should eql(Myrrha::Coercions)
|
153
|
+
end
|
154
|
+
specify "from Symbol" do
|
155
|
+
coerce(:Integer, Class).should eql(Integer)
|
156
|
+
end
|
157
|
+
it "should raise error if not a module" do
|
158
|
+
lambda{
|
159
|
+
coerce("Myrrha::Version", Class)
|
160
|
+
}.should raise_error(Myrrha::Error)
|
161
|
+
end
|
162
|
+
end
|
105
163
|
|
106
164
|
specify "to a class that respond to coerce" do
|
107
165
|
class Coerceable
|
data/spec/test_myrrha.rb
CHANGED
@@ -84,4 +84,41 @@ describe Myrrha do
|
|
84
84
|
rules.coerce("hello", Symbol).should eq(:HELLO)
|
85
85
|
end
|
86
86
|
|
87
|
+
it "should used superdomain rules in an optimistic strategy" do
|
88
|
+
rules = Myrrha.coercions do |c|
|
89
|
+
c.coercion String, Numeric, lambda{|s,t| Integer(s)}
|
90
|
+
end
|
91
|
+
rules.coerce("12", Integer).should eql(12)
|
92
|
+
lambda{ rules.coerce("12", Float) }.should raise_error(Myrrha::Error)
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "path convertions" do
|
96
|
+
let(:rules){
|
97
|
+
Myrrha.coercions do |c|
|
98
|
+
c.coercion Integer, String, lambda{|s,t| s.to_s}
|
99
|
+
c.coercion String, Float, lambda{|s,t| Float(s)}
|
100
|
+
c.coercion Integer, Float, [String]
|
101
|
+
c.coercion Float, String, lambda{|s,t| s.to_s}
|
102
|
+
c.coercion String, Symbol, lambda{|s,t| s.to_sym}
|
103
|
+
c.coercion Integer, Symbol, [Float, String]
|
104
|
+
end
|
105
|
+
}
|
106
|
+
it "should work with a simple and single" do
|
107
|
+
rules.coerce(12, Float).should eql(12.0)
|
108
|
+
end
|
109
|
+
it "should work with a complex and multiple path" do
|
110
|
+
rules.coerce(12, Symbol).should eql(:"12.0")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
specify "path convertions (from CHANGELOG)" do
|
115
|
+
rules = Myrrha.coercions do |r|
|
116
|
+
r.coercion String, Symbol, lambda{|s,t| s.to_sym }
|
117
|
+
r.coercion Float, String, lambda{|s,t| s.to_s }
|
118
|
+
r.coercion Integer, Float, lambda{|s,t| Float(s) }
|
119
|
+
r.coercion Integer, Symbol, [Float, String]
|
120
|
+
end
|
121
|
+
rules.coerce(12, Symbol).should eql(:"12.0")
|
122
|
+
end
|
123
|
+
|
87
124
|
end
|
data/tasks/examples.rake
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: myrrha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-07-
|
12
|
+
date: 2011-07-28 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &85576310 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.9.2
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *85576310
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: bundler
|
27
|
-
requirement: &
|
27
|
+
requirement: &85575520 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '1.0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *85575520
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &85574670 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 2.6.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *85574670
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: yard
|
49
|
-
requirement: &
|
49
|
+
requirement: &85573700 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,21 +54,21 @@ dependencies:
|
|
54
54
|
version: 0.7.2
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *85573700
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: bluecloth
|
60
|
-
requirement: &
|
60
|
+
requirement: &85572820 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
64
64
|
- !ruby/object:Gem::Version
|
65
|
-
version: 2.0
|
65
|
+
version: 2.1.0
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *85572820
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: wlang
|
71
|
-
requirement: &
|
71
|
+
requirement: &85550940 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: 0.10.1
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *85550940
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: noe
|
82
|
-
requirement: &
|
82
|
+
requirement: &85550220 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
version: 1.3.0
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *85550220
|
91
91
|
description: ! "Myrrha provides the coercion framework which is missing to Ruby, IMHO.
|
92
92
|
Coercions\nare simply defined as a set of rules for converting values from source
|
93
93
|
to target\ndomains (in an abstract sense). As a typical and useful example, it comes
|
@@ -113,6 +113,7 @@ files:
|
|
113
113
|
- examples/String#toXXX.rb
|
114
114
|
- examples/examples_helper.rb
|
115
115
|
- examples/coerce_foo2.rb
|
116
|
+
- examples/sbyc_domain.rb
|
116
117
|
- examples/to_ruby_literal_foo3.rb
|
117
118
|
- examples/to_ruby_literal_noext.rb
|
118
119
|
- examples/coerce_foo3.rb
|
@@ -123,6 +124,8 @@ files:
|
|
123
124
|
- lib/myrrha/version.rb
|
124
125
|
- lib/myrrha.rb
|
125
126
|
- spec/spec_helper.rb
|
127
|
+
- spec/myrrha/test_coercions.rb
|
128
|
+
- spec/myrrha/test_domain.rb
|
126
129
|
- spec/test_myrrha.rb
|
127
130
|
- spec/test_to_ruby_literal.rb
|
128
131
|
- spec/test_value.rb
|
@@ -164,7 +167,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
164
167
|
version: '0'
|
165
168
|
segments:
|
166
169
|
- 0
|
167
|
-
hash: -
|
170
|
+
hash: -900430961
|
168
171
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
172
|
none: false
|
170
173
|
requirements:
|
@@ -173,15 +176,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
176
|
version: '0'
|
174
177
|
segments:
|
175
178
|
- 0
|
176
|
-
hash: -
|
179
|
+
hash: -900430961
|
177
180
|
requirements: []
|
178
181
|
rubyforge_project:
|
179
|
-
rubygems_version: 1.8.
|
182
|
+
rubygems_version: 1.8.6
|
180
183
|
signing_key:
|
181
184
|
specification_version: 3
|
182
185
|
summary: Myrrha provides the coercion framework which is missing to Ruby, IMHO.
|
183
186
|
test_files:
|
184
187
|
- spec/spec_helper.rb
|
188
|
+
- spec/myrrha/test_coercions.rb
|
189
|
+
- spec/myrrha/test_domain.rb
|
185
190
|
- spec/test_myrrha.rb
|
186
191
|
- spec/test_to_ruby_literal.rb
|
187
192
|
- spec/test_value.rb
|