myrrha 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +41 -0
- data/LICENCE.md +22 -0
- data/Manifest.txt +13 -0
- data/README.md +337 -0
- data/Rakefile +23 -0
- data/examples/String#toXXX.rb +40 -0
- data/examples/coerce.rb +26 -0
- data/examples/coerce_foo.rb +12 -0
- data/examples/coerce_foo2.rb +17 -0
- data/examples/coerce_foo3.rb +23 -0
- data/examples/coerce_intro.rb +10 -0
- data/examples/coerce_noext.rb +6 -0
- data/examples/examples_helper.rb +17 -0
- data/examples/friendly_but_safe_api.rb +73 -0
- data/examples/to_ruby_literal.rb +16 -0
- data/examples/to_ruby_literal_foo.rb +14 -0
- data/examples/to_ruby_literal_foo2.rb +17 -0
- data/examples/to_ruby_literal_foo3.rb +21 -0
- data/examples/to_ruby_literal_noext.rb +5 -0
- data/lib/myrrha/coerce.rb +93 -0
- data/lib/myrrha/loader.rb +0 -0
- data/lib/myrrha/to_ruby_literal.rb +76 -0
- data/lib/myrrha/version.rb +14 -0
- data/lib/myrrha/with_core_ext.rb +2 -0
- data/lib/myrrha.rb +295 -0
- data/myrrha.gemspec +191 -0
- data/myrrha.noespec +37 -0
- data/spec/coercions/test_append.rb +11 -0
- data/spec/coercions/test_belongs_to.rb +29 -0
- data/spec/coercions/test_convert.rb +23 -0
- data/spec/coercions/test_dup.rb +21 -0
- data/spec/coercions/test_subdomain.rb +11 -0
- data/spec/shared/a_value.rb +33 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/test_assumptions.rb +18 -0
- data/spec/test_coerce.rb +119 -0
- data/spec/test_myrrha.rb +87 -0
- data/spec/test_to_ruby_literal.rb +19 -0
- data/spec/test_value.rb +6 -0
- data/tasks/debug_mail.rake +78 -0
- data/tasks/debug_mail.txt +13 -0
- data/tasks/examples.rake +13 -0
- data/tasks/gem.rake +68 -0
- data/tasks/spec_test.rake +79 -0
- data/tasks/unit_test.rake +77 -0
- data/tasks/yard.rake +51 -0
- metadata +195 -0
data/myrrha.gemspec
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
# We require your library, mainly to have access to the VERSION number.
|
2
|
+
# Feel free to set $version manually.
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
4
|
+
require "myrrha/version"
|
5
|
+
$version = Myrrha::Version.to_s
|
6
|
+
|
7
|
+
#
|
8
|
+
# This is your Gem specification. Default values are provided so that your library
|
9
|
+
# should be correctly packaged given what you have described in the .noespec file.
|
10
|
+
#
|
11
|
+
Gem::Specification.new do |s|
|
12
|
+
|
13
|
+
################################################################### ABOUT YOUR GEM
|
14
|
+
|
15
|
+
# Gem name (required)
|
16
|
+
s.name = "myrrha"
|
17
|
+
|
18
|
+
# Gem version (required)
|
19
|
+
s.version = $version
|
20
|
+
|
21
|
+
# A short summary of this gem
|
22
|
+
#
|
23
|
+
# This is displayed in `gem list -d`.
|
24
|
+
s.summary = "Myrrha provides the coercion framework which is missing to Ruby, IMHO."
|
25
|
+
|
26
|
+
# A long description of this gem (required)
|
27
|
+
#
|
28
|
+
# The description should be more detailed than the summary. For example,
|
29
|
+
# you might wish to copy the entire README into the description.
|
30
|
+
s.description = "Myrrha provides the coercion framework which is missing to Ruby, IMHO. Coercions\nare simply defined as a set of rules for converting values from source to target\ndomains (in an abstract sense). As a typical and useful example, it comes bundled\nwith a coerce() method providing a unique entry point for converting a string to \na numeric, a boolean, a date, a time, an URI, and so on. "
|
31
|
+
|
32
|
+
# The URL of this gem home page (optional)
|
33
|
+
s.homepage = "http://rubydoc.info/github/blambeau/myrrha/master/frames"
|
34
|
+
|
35
|
+
# Gem publication date (required but auto)
|
36
|
+
#
|
37
|
+
# Today is automatically used by default, uncomment only if
|
38
|
+
# you know what you do!
|
39
|
+
#
|
40
|
+
# s.date = Time.now.strftime('%Y-%m-%d')
|
41
|
+
|
42
|
+
# The license(s) for the library. Each license must be a short name, no
|
43
|
+
# more than 64 characters.
|
44
|
+
#
|
45
|
+
# s.licences = %w{}
|
46
|
+
|
47
|
+
# The rubyforge project this gem lives under (optional)
|
48
|
+
#
|
49
|
+
# s.rubyforge_project = nil
|
50
|
+
|
51
|
+
################################################################### ABOUT THE AUTHORS
|
52
|
+
|
53
|
+
# The list of author names who wrote this gem.
|
54
|
+
#
|
55
|
+
# If you are providing multiple authors and multiple emails they should be
|
56
|
+
# in the same order.
|
57
|
+
#
|
58
|
+
s.authors = ["Bernard Lambeau"]
|
59
|
+
|
60
|
+
# Contact emails for this gem
|
61
|
+
#
|
62
|
+
# If you are providing multiple authors and multiple emails they should be
|
63
|
+
# in the same order.
|
64
|
+
#
|
65
|
+
# NOTE: Somewhat strangly this attribute is always singular!
|
66
|
+
# Don't replace by s.emails = ...
|
67
|
+
s.email = ["blambeau@gmail.com"]
|
68
|
+
|
69
|
+
################################################################### PATHS, FILES, BINARIES
|
70
|
+
|
71
|
+
# Paths in the gem to add to $LOAD_PATH when this gem is
|
72
|
+
# activated (required).
|
73
|
+
#
|
74
|
+
# The default 'lib' is typically sufficient.
|
75
|
+
s.require_paths = ["lib"]
|
76
|
+
|
77
|
+
# Files included in this gem.
|
78
|
+
#
|
79
|
+
# By default, we take all files included in the Manifest.txt file on root
|
80
|
+
# of the project. Entries of the manifest are interpreted as Dir[...]
|
81
|
+
# patterns so that lazy people may use wilcards like lib/**/*
|
82
|
+
#
|
83
|
+
here = File.expand_path(File.dirname(__FILE__))
|
84
|
+
s.files = File.readlines(File.join(here, 'Manifest.txt')).
|
85
|
+
inject([]){|files, pattern| files + Dir[File.join(here, pattern.strip)]}.
|
86
|
+
collect{|x| x[(1+here.size)..-1]}
|
87
|
+
|
88
|
+
# Test files included in this gem.
|
89
|
+
#
|
90
|
+
s.test_files = Dir["test/**/*"] + Dir["spec/**/*"]
|
91
|
+
|
92
|
+
# The path in the gem for executable scripts (optional)
|
93
|
+
#
|
94
|
+
s.bindir = "bin"
|
95
|
+
|
96
|
+
# Executables included in the gem.
|
97
|
+
#
|
98
|
+
s.executables = (Dir["bin/*"]).collect{|f| File.basename(f)}
|
99
|
+
|
100
|
+
################################################################### REQUIREMENTS & INSTALL
|
101
|
+
# Remember the gem version requirements operators and schemes:
|
102
|
+
# = Equals version
|
103
|
+
# != Not equal to version
|
104
|
+
# > Greater than version
|
105
|
+
# < Less than version
|
106
|
+
# >= Greater than or equal to
|
107
|
+
# <= Less than or equal to
|
108
|
+
# ~> Approximately greater than
|
109
|
+
#
|
110
|
+
# Don't forget to have a look at http://lmgtfy.com/?q=Ruby+Versioning+Policies
|
111
|
+
# for setting your gem version.
|
112
|
+
#
|
113
|
+
# For your requirements to other gems, remember that
|
114
|
+
# ">= 2.2.0" (optimistic: specify minimal version)
|
115
|
+
# ">= 2.2.0", "< 3.0" (pessimistic: not greater than the next major)
|
116
|
+
# "~> 2.2" (shortcut for ">= 2.2.0", "< 3.0")
|
117
|
+
# "~> 2.2.0" (shortcut for ">= 2.2.0", "< 2.3.0")
|
118
|
+
#
|
119
|
+
|
120
|
+
#
|
121
|
+
# One call to add_dependency('gem_name', 'gem version requirement') for each
|
122
|
+
# runtime dependency. These gems will be installed with your gem.
|
123
|
+
# One call to add_development_dependency('gem_name', 'gem version requirement')
|
124
|
+
# for each development dependency. These gems are required for developers
|
125
|
+
#
|
126
|
+
s.add_development_dependency("rake", "~> 0.9.2")
|
127
|
+
s.add_development_dependency("bundler", "~> 1.0")
|
128
|
+
s.add_development_dependency("rspec", "~> 2.6.0")
|
129
|
+
s.add_development_dependency("yard", "~> 0.7.2")
|
130
|
+
s.add_development_dependency("bluecloth", "~> 2.0.9")
|
131
|
+
s.add_development_dependency("wlang", "~> 0.10.1")
|
132
|
+
s.add_development_dependency("noe", "~> 1.3.0")
|
133
|
+
|
134
|
+
|
135
|
+
# The version of ruby required by this gem
|
136
|
+
#
|
137
|
+
# Uncomment and set this if your gem requires specific ruby versions.
|
138
|
+
#
|
139
|
+
# s.required_ruby_version = ">= 0"
|
140
|
+
|
141
|
+
# The RubyGems version required by this gem
|
142
|
+
#
|
143
|
+
# s.required_rubygems_version = ">= 0"
|
144
|
+
|
145
|
+
# The platform this gem runs on. See Gem::Platform for details.
|
146
|
+
#
|
147
|
+
# s.platform = nil
|
148
|
+
|
149
|
+
# Extensions to build when installing the gem.
|
150
|
+
#
|
151
|
+
# Valid types of extensions are extconf.rb files, configure scripts
|
152
|
+
# and rakefiles or mkrf_conf files.
|
153
|
+
#
|
154
|
+
s.extensions = []
|
155
|
+
|
156
|
+
# External (to RubyGems) requirements that must be met for this gem to work.
|
157
|
+
# It’s simply information for the user.
|
158
|
+
#
|
159
|
+
s.requirements = nil
|
160
|
+
|
161
|
+
# A message that gets displayed after the gem is installed
|
162
|
+
#
|
163
|
+
# Uncomment and set this if you want to say something to the user
|
164
|
+
# after gem installation
|
165
|
+
#
|
166
|
+
s.post_install_message = nil
|
167
|
+
|
168
|
+
################################################################### SECURITY
|
169
|
+
|
170
|
+
# The key used to sign this gem. See Gem::Security for details.
|
171
|
+
#
|
172
|
+
# s.signing_key = nil
|
173
|
+
|
174
|
+
# The certificate chain used to sign this gem. See Gem::Security for
|
175
|
+
# details.
|
176
|
+
#
|
177
|
+
# s.cert_chain = []
|
178
|
+
|
179
|
+
################################################################### RDOC
|
180
|
+
|
181
|
+
# An ARGV style array of options to RDoc
|
182
|
+
#
|
183
|
+
# See 'rdoc --help' about this
|
184
|
+
#
|
185
|
+
s.rdoc_options = []
|
186
|
+
|
187
|
+
# Extra files to add to RDoc such as README
|
188
|
+
#
|
189
|
+
s.extra_rdoc_files = Dir["README.md"] + Dir["CHANGELOG.md"] + Dir["LICENCE.md"]
|
190
|
+
|
191
|
+
end
|
data/myrrha.noespec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Noe template for ruby gem libraries (https://github.com/blambeau/noe) - short version
|
2
|
+
# Run 'noe show-spec' and 'noe help show-spec' for additional details.
|
3
|
+
template-info:
|
4
|
+
name: "ruby"
|
5
|
+
version: 1.3.0
|
6
|
+
variables:
|
7
|
+
lower:
|
8
|
+
myrrha
|
9
|
+
upper:
|
10
|
+
Myrrha
|
11
|
+
version:
|
12
|
+
1.0.0
|
13
|
+
summary: |-
|
14
|
+
Myrrha provides the coercion framework which is missing to Ruby, IMHO.
|
15
|
+
description: |-
|
16
|
+
Myrrha provides the coercion framework which is missing to Ruby, IMHO. Coercions
|
17
|
+
are simply defined as a set of rules for converting values from source to target
|
18
|
+
domains (in an abstract sense). As a typical and useful example, it comes bundled
|
19
|
+
with a coerce() method providing a unique entry point for converting a string to
|
20
|
+
a numeric, a boolean, a date, a time, an URI, and so on.
|
21
|
+
authors:
|
22
|
+
- {name: Bernard Lambeau, email: blambeau@gmail.com}
|
23
|
+
links:
|
24
|
+
- http://rubydoc.info/github/blambeau/myrrha/master/frames
|
25
|
+
- http://github.com/blambeau/myrrha
|
26
|
+
- http://rubygems.org/gems/myrrha
|
27
|
+
dependencies:
|
28
|
+
- {name: rake, version: "~> 0.9.2", groups: [development]}
|
29
|
+
- {name: bundler, version: "~> 1.0", groups: [development]}
|
30
|
+
- {name: rspec, version: "~> 2.6.0", groups: [development]}
|
31
|
+
- {name: yard, version: "~> 0.7.2", groups: [development]}
|
32
|
+
- {name: bluecloth, version: "~> 2.0.9", groups: [development]}
|
33
|
+
- {name: wlang, version: "~> 0.10.1", groups: [development]}
|
34
|
+
- {name: noe, version: "~> 1.3.0", groups: [development]}
|
35
|
+
rake_tasks:
|
36
|
+
spec_test:
|
37
|
+
pattern: spec/**/test_*.rb
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Myrrha
|
3
|
+
describe "Coercions#belongs_to?" do
|
4
|
+
let(:rules){ Coercions.new }
|
5
|
+
|
6
|
+
specify "with a class" do
|
7
|
+
rules.belongs_to?(12, Integer).should be_true
|
8
|
+
end
|
9
|
+
|
10
|
+
specify "with a superclass" do
|
11
|
+
rules.belongs_to?(12, Numeric).should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
specify "with a proc or arity 1" do
|
15
|
+
rules.belongs_to?(12, lambda{|x| x>10}).should be_true
|
16
|
+
rules.belongs_to?(12, lambda{|x| x<10}).should be_false
|
17
|
+
end
|
18
|
+
|
19
|
+
specify "with a proc or arity 2" do
|
20
|
+
got = nil
|
21
|
+
l = lambda{|x,t| got = t; t == l }
|
22
|
+
rules.belongs_to?(12, l).should be_true
|
23
|
+
got.should eq(l)
|
24
|
+
rules.belongs_to?(12, l, :nosuch).should be_false
|
25
|
+
got.should eq(:nosuch)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Myrrha
|
3
|
+
describe "Coercions#convert" do
|
4
|
+
let(:graph){ Coercions.new }
|
5
|
+
|
6
|
+
subject{ graph.send(:convert, "value", String, converter) }
|
7
|
+
|
8
|
+
describe "when passed a proc of arity 2" do
|
9
|
+
let(:converter){ lambda{|v,t| [v,t]} }
|
10
|
+
it{ should eq(["value", String]) }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "when passed an object that respond to call" do
|
14
|
+
let(:converter){
|
15
|
+
o = Object.new
|
16
|
+
def o.call(arg, t); [arg, t]; end
|
17
|
+
o
|
18
|
+
}
|
19
|
+
it{ should eq(["value", String]) }
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Myrrha
|
3
|
+
describe "Coercions#dup" do
|
4
|
+
let(:rules){ Coercions.new{|r|
|
5
|
+
r.coercion String, Integer, lambda{|s,t| Integer(s)}
|
6
|
+
}}
|
7
|
+
|
8
|
+
it "should duplicate the rules" do
|
9
|
+
rules.dup.coerce("12", Integer).should eql(12)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should not touch the original" do
|
13
|
+
dupped = rules.dup.append do |r|
|
14
|
+
r.coercion String, Float, lambda{|s,t| Float(s)}
|
15
|
+
end
|
16
|
+
dupped.coerce("12", Float).should eql(12.0)
|
17
|
+
lambda{ rules.coerce("12", Float) }.should raise_error(Myrrha::Error)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
shared_examples_for "a value" do
|
2
|
+
|
3
|
+
def dup(val)
|
4
|
+
Kernel.eval(val.to_ruby_literal)
|
5
|
+
end
|
6
|
+
|
7
|
+
it "should implement == correctly" do
|
8
|
+
subject.should eq(dup(subject))
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should implement eql? correctly" do
|
12
|
+
{subject => true, dup(subject) => false}.size.should eq(1)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should implement class.parse / #to_s correctly" do
|
16
|
+
if subject.class.respond_to?(:parse) && subject.respond_to?(:to_s)
|
17
|
+
begin
|
18
|
+
subject.class.parse(subject.to_s).should eq(subject)
|
19
|
+
rescue
|
20
|
+
t1 = subject.class.parse(subject.to_s)
|
21
|
+
t2 = subject.class.parse(subject.to_s)
|
22
|
+
t1.should eq(t2)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should implement Kernel.eval / to_ruby_literal correctly" do
|
28
|
+
if subject.respond_to?(:to_ruby_literal)
|
29
|
+
Kernel.eval(subject.to_ruby_literal).should eq(subject)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require 'myrrha/with_core_ext'
|
3
|
+
require 'myrrha/coerce'
|
4
|
+
require 'myrrha/to_ruby_literal'
|
5
|
+
require 'date'
|
6
|
+
require 'time'
|
7
|
+
require 'shared/a_value'
|
8
|
+
|
9
|
+
unless defined?(SAFE_VALUES)
|
10
|
+
SAFE_VALUES = {
|
11
|
+
NilClass => [ nil ],
|
12
|
+
TrueClass => [ true ],
|
13
|
+
FalseClass => [ false ],
|
14
|
+
Fixnum => [ -(2**(0.size * 8 - 2)), -1, 0, 1, 10, (2**(0.size * 8 - 2) - 1)],
|
15
|
+
Bignum => [ -(2**(0.size * 8 - 2)) - 1, (2**(0.size * 8 - 2)) ],
|
16
|
+
Float => [ -0.10, 0.0, 0.10 ],
|
17
|
+
String => ['', 'hello'],
|
18
|
+
Symbol => [ :hello, :"s-b-y-c", :"12" ],
|
19
|
+
Class => [ Integer, ::Struct::Tms ],
|
20
|
+
Module => [ Kernel, Myrrha ],
|
21
|
+
Regexp => [ /a-z/, /^$/, /\s*/, /[a-z]{15}/ ],
|
22
|
+
Range => [ 0..10, 0...10 ],
|
23
|
+
Array => [ [], [nil], [1, "hello"] ],
|
24
|
+
Hash => [ {}, {1 => 2, :hello => "world"} ]
|
25
|
+
}
|
26
|
+
UNSAFE_VALUES = {
|
27
|
+
Date => [ Date.today ],
|
28
|
+
Time => [ Time.now ],
|
29
|
+
Array => [ [Date.today, Time.now] ],
|
30
|
+
Hash => [ {Date.today => Time.now} ],
|
31
|
+
Range => [ Date.today..(Date.today+1) ]
|
32
|
+
}
|
33
|
+
VALUES = SAFE_VALUES.values.inject([], :+) + UNSAFE_VALUES.values.inject([], :+)
|
34
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe "Ruby assumptions" do
|
3
|
+
|
4
|
+
describe "Proc#arity" do
|
5
|
+
specify{
|
6
|
+
lambda{|a| }.arity.should eq(1)
|
7
|
+
lambda{|a,b| }.arity.should eq(2)
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
class Object
|
12
|
+
def no_such_myrrha_method
|
13
|
+
end
|
14
|
+
end if false
|
15
|
+
|
16
|
+
specify{ Object.should_not respond_to(:no_such_myrrha_method) }
|
17
|
+
|
18
|
+
end
|
data/spec/test_coerce.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe "::Ruby's coercion " do
|
3
|
+
|
4
|
+
describe "from NilClass" do
|
5
|
+
it "should always return nil" do
|
6
|
+
coerce(nil, Integer).should be_nil
|
7
|
+
coerce(nil, Date).should be_nil
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "to Integer" do
|
12
|
+
specify "from Integer" do
|
13
|
+
coerce(12, Integer).should eql(12)
|
14
|
+
end
|
15
|
+
specify "from String" do
|
16
|
+
coerce("12", Integer).should eql(12)
|
17
|
+
coerce("-12", Integer).should eql(-12)
|
18
|
+
coerce("0", Integer).should eql(0)
|
19
|
+
end
|
20
|
+
specify "on error" do
|
21
|
+
lambda{coerce("abc", Integer)}.should raise_error(Myrrha::Error)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "to Float" do
|
26
|
+
specify "from Float" do
|
27
|
+
coerce(12.2, Float).should eql(12.2)
|
28
|
+
end
|
29
|
+
specify "from Integer" do
|
30
|
+
coerce(0, Float).should eql(0.0)
|
31
|
+
coerce(12, Float).should eql(12.0)
|
32
|
+
coerce(-12, Float).should eql(-12.0)
|
33
|
+
end
|
34
|
+
specify "from String" do
|
35
|
+
coerce("12.2", Float).should eql(12.2)
|
36
|
+
coerce("0", Float).should eql(0.0)
|
37
|
+
coerce("0.0", Float).should eql(0.0)
|
38
|
+
coerce("-12.2", Float).should eql(-12.2)
|
39
|
+
end
|
40
|
+
specify "on error" do
|
41
|
+
lambda{coerce("abc", Float)}.should raise_error(Myrrha::Error)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "to Numeric" do
|
46
|
+
specify "from String" do
|
47
|
+
coerce("12", Numeric).should eql(12)
|
48
|
+
coerce("12.2", Numeric).should eql(12.2)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "to Boolean" do
|
53
|
+
specify "from Boolean" do
|
54
|
+
coerce(true, Boolean).should eql(true)
|
55
|
+
coerce(false, Boolean).should eql(false)
|
56
|
+
end
|
57
|
+
specify "from String" do
|
58
|
+
coerce("true", Boolean).should eql(true)
|
59
|
+
coerce("false", Boolean).should eql(false)
|
60
|
+
end
|
61
|
+
specify "on error" do
|
62
|
+
lambda{coerce("abc", Boolean)}.should raise_error(Myrrha::Error)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "to Date" do
|
67
|
+
let(:expected){ Date.parse("2011-07-20") }
|
68
|
+
specify "from String" do
|
69
|
+
coerce("2011-07-20", Date).should eql(expected)
|
70
|
+
coerce("2011/07/20", Date).should eql(expected)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "to Time" do
|
75
|
+
let(:expected){ Time.parse("2011-07-20 10:53") }
|
76
|
+
specify "from String" do
|
77
|
+
coerce("2011-07-20 10:53", Time).should eql(expected)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "to Symbol" do
|
82
|
+
specify "from Symbol" do
|
83
|
+
coerce(:hello, Symbol).should eql(:hello)
|
84
|
+
end
|
85
|
+
specify "from String" do
|
86
|
+
coerce("hello", Symbol).should eql(:hello)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "to Regexp" do
|
91
|
+
specify "from Regexp" do
|
92
|
+
coerce(/[a-z]+/, Regexp).should eql(/[a-z]+/)
|
93
|
+
end
|
94
|
+
specify "from String" do
|
95
|
+
coerce("[a-z]+", Regexp).should eql(/[a-z]+/)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "to URI" do
|
100
|
+
require 'uri'
|
101
|
+
specify "from String" do
|
102
|
+
coerce("http://www.google.com/", URI).should eql(URI.parse("http://www.google.com/"))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
specify "to a class that respond to coerce" do
|
107
|
+
class Coerceable
|
108
|
+
def self.coerce(val)
|
109
|
+
[:coerced, val]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
coerce("hello", Coerceable).should eq([:coerced, "hello"])
|
113
|
+
end
|
114
|
+
|
115
|
+
specify "otherwise" do
|
116
|
+
lambda{ coerce("hallo", Myrrha) }.should raise_error(Myrrha::Error)
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
data/spec/test_myrrha.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
describe Myrrha do
|
3
|
+
|
4
|
+
it "should have a version number" do
|
5
|
+
Myrrha.const_defined?(:VERSION).should be_true
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should provide the abitity to define a coercion rules" do
|
9
|
+
rules = Myrrha.coercions do |g|
|
10
|
+
g.coercion String, Integer, lambda{|s,t| Integer(s)}
|
11
|
+
g.coercion String, Float, lambda{|s,t| Float(s) }
|
12
|
+
end
|
13
|
+
rules.coerce(12, Integer).should eq(12)
|
14
|
+
rules.coerce("12", Integer).should eq(12)
|
15
|
+
rules.coerce(12.2, Float).should eq(12.2)
|
16
|
+
rules.coerce("12.2", Float).should eq(12.2)
|
17
|
+
rules.coerce("12", Numeric).should eq(12)
|
18
|
+
rules.coerce("12.2", Numeric).should eq(12.2)
|
19
|
+
lambda{
|
20
|
+
rules.coerce(true, Integer)
|
21
|
+
}.should raise_error(Myrrha::Error, "Unable to coerce `true` to Integer")
|
22
|
+
lambda{
|
23
|
+
rules.coerce("12.2", Integer)
|
24
|
+
}.should raise_error(Myrrha::Error, /^Unable to coerce `12.2` to Integer \(invalid value /)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should support upon rules" do
|
28
|
+
rules = Myrrha.coercions do |g|
|
29
|
+
g.coercion(Integer, Symbol){|s,t| :coercion}
|
30
|
+
g.upon(lambda{|s| s<0}){|s,t| :upon}
|
31
|
+
end
|
32
|
+
rules.coerce(12, Symbol).should eq(:coercion)
|
33
|
+
rules.coerce(-12, Symbol).should eq(:upon)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should support fallback rules" do
|
37
|
+
rules = Myrrha.coercions do |g|
|
38
|
+
g.fallback String, lambda{|s,t| :world}
|
39
|
+
end
|
40
|
+
rules.coerce("hello", Symbol).should eq(:world)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should support using matchers" do
|
44
|
+
ArrayOfSymbols = proc{|val| val.is_a?(Array) && val.all?{|x| Symbol===x}}
|
45
|
+
rules = Myrrha.coercions do |g|
|
46
|
+
g.coercion ArrayOfSymbols, String, lambda{|x,t| x.join(', ')}
|
47
|
+
end
|
48
|
+
rules.coerce([:a, :b], ArrayOfSymbols).should eq([:a, :b])
|
49
|
+
rules.coerce([:a, :b], String).should eq("a, b")
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should support using any object that respond to call as converter" do
|
53
|
+
converter = Object.new
|
54
|
+
def converter.call(arg, t); [arg, t]; end
|
55
|
+
rules = Myrrha.coercions do |g|
|
56
|
+
g.coercion String, Symbol, converter
|
57
|
+
end
|
58
|
+
rules.coerce("hello", Symbol).should eq(["hello", Symbol])
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should support adding rules later" do
|
62
|
+
rules = Myrrha.coercions do |c|
|
63
|
+
c.coercion String, Symbol, lambda{|s,t| s.to_sym}
|
64
|
+
c.fallback Object, lambda{|s,t| :fallback}
|
65
|
+
end
|
66
|
+
rules.coerce("hello", Symbol).should eq(:hello)
|
67
|
+
rules.coerce(12, Symbol).should eq(:fallback)
|
68
|
+
|
69
|
+
rules.append do |c|
|
70
|
+
c.coercion Integer, Symbol, lambda{|s,t| s.to_s.to_sym}
|
71
|
+
end
|
72
|
+
rules.coerce(12, Symbol).should eq(:"12")
|
73
|
+
rules.coerce(true, Symbol).should eq(:fallback)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should support adding rules before" do
|
77
|
+
rules = Myrrha.coercions do |c|
|
78
|
+
c.coercion String, Symbol, lambda{|s,t| s.to_sym}
|
79
|
+
end
|
80
|
+
rules.coerce("hello", Symbol).should eq(:hello)
|
81
|
+
rules.prepend do |c|
|
82
|
+
c.coercion String, Symbol, lambda{|s,t| s.to_s.upcase.to_sym}
|
83
|
+
end
|
84
|
+
rules.coerce("hello", Symbol).should eq(:HELLO)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe "to_ruby_literal" do
|
3
|
+
|
4
|
+
VALUES.each do |value|
|
5
|
+
describe "on #{value.inspect}" do
|
6
|
+
specify{ Kernel.eval(value.to_ruby_literal).should eq(value) }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should work on objects that implement to_ruby_literal" do
|
11
|
+
class ToRubyLiteralizable
|
12
|
+
def to_ruby_literal
|
13
|
+
:foo
|
14
|
+
end
|
15
|
+
end
|
16
|
+
Myrrha.to_ruby_literal(ToRubyLiteralizable.new).should eq(:foo)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|