must 0.2.1
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 +132 -0
- data/Rakefile +48 -0
- data/lib/must/rule.rb +86 -0
- data/lib/must.rb +12 -0
- metadata +70 -0
data/README
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
Must
|
2
|
+
====
|
3
|
+
|
4
|
+
add Object#must method to constrain its origin and conversions
|
5
|
+
|
6
|
+
# can write like this
|
7
|
+
num = params[:num].to_i.must.match(1..300) {10}
|
8
|
+
|
9
|
+
# rather than
|
10
|
+
num = params[:num].to_i
|
11
|
+
num = 10 unless (1..300) === num
|
12
|
+
|
13
|
+
|
14
|
+
Testing Methods
|
15
|
+
===============
|
16
|
+
|
17
|
+
be : check whether object equals to the argument
|
18
|
+
kind_of : check whether object is a kind of the argument
|
19
|
+
coerced : check whether object can be coerced to the argument
|
20
|
+
blank : check whether object is blank?
|
21
|
+
exist : check whether object is not nil (NOTE: false is ok)
|
22
|
+
|
23
|
+
|
24
|
+
Logical Methods
|
25
|
+
===============
|
26
|
+
|
27
|
+
not : logical NOT
|
28
|
+
|
29
|
+
|
30
|
+
Nop Methods
|
31
|
+
===========
|
32
|
+
|
33
|
+
a : return self
|
34
|
+
an : return self
|
35
|
+
|
36
|
+
These effect nothing but exist only for English grammar.
|
37
|
+
|
38
|
+
|
39
|
+
Basic Examples
|
40
|
+
==============
|
41
|
+
|
42
|
+
# test its value exactly
|
43
|
+
1.must.be 1 # => 1
|
44
|
+
[1,2,3].must.be [1,2,3] # => [1,2,3]
|
45
|
+
|
46
|
+
# exceptions
|
47
|
+
1.must.be [] # Must::Invalid exception
|
48
|
+
1.must.be([]) {:ng} # => :ng
|
49
|
+
1.must.be(1) {:ng} # => 1
|
50
|
+
|
51
|
+
# as default value
|
52
|
+
name = params[:name].must.not.be.blank{ "No name" }
|
53
|
+
|
54
|
+
# existing test
|
55
|
+
1.must.exist # => 1
|
56
|
+
nil.must.exist # Must::Invalid exception
|
57
|
+
false.must.exist # => false
|
58
|
+
|
59
|
+
# test class : ensures that a class of the object is one of given arguments
|
60
|
+
1.must.be.kind_of(Integer) # => 1
|
61
|
+
1.must.be.kind_of(Integer, Array) # => 1
|
62
|
+
[].must.be.kind_of(Integer, Array) # => []
|
63
|
+
1.must.be.kind_of(String, Array) # Must::Invalid: expected String/Array but got Fixnum
|
64
|
+
|
65
|
+
# coercing : looks like kind_of except converting its value if possible
|
66
|
+
1.must.be.coerced(Integer, String => proc{|val| val.to_i}) # => 1
|
67
|
+
"1".must.be.coerced(Integer, String => proc{|val| val.to_i}) # => 1
|
68
|
+
"1".must.be.coerced(Integer, String => :to_i) # => 1 (NOTE: inline Symbol means sending the method)
|
69
|
+
"1".must.be.coerced(Integer, Symbol, String => proc{:to_i}) # => :to_i (NOTE: use proc to return Symbol itself)
|
70
|
+
|
71
|
+
|
72
|
+
Actual Examples
|
73
|
+
===============
|
74
|
+
|
75
|
+
1)
|
76
|
+
|
77
|
+
normal code:
|
78
|
+
|
79
|
+
def set_reader(reader)
|
80
|
+
if reader.is_a?(CSV::Reader)
|
81
|
+
@reader = reader
|
82
|
+
elsif file.is_a?(String)
|
83
|
+
@reader = CSV::Reader.create(i)
|
84
|
+
elsif file.is_a?(Pathname)
|
85
|
+
@reader = CSV::Reader.create(reader.read)
|
86
|
+
else
|
87
|
+
raise 'invalid reader'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
refactor above code with must plugin
|
92
|
+
|
93
|
+
def set_reader(reader)
|
94
|
+
@reader = reader.must.be.coerced(CSV::Reader, Pathname=>:read, String=>{|i| CSV::Reader.create(i)}) {raise 'invalid reader'}
|
95
|
+
end
|
96
|
+
|
97
|
+
2)
|
98
|
+
|
99
|
+
class DateFolder
|
100
|
+
def initialize(date)
|
101
|
+
@date = date.must.be.coerced(Date, String=>proc{|i| Date.new(*i.scan(/\d+/).map{|i|i.to_i})})
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# this can accept both formats
|
106
|
+
|
107
|
+
DateFolder.new Date.today
|
108
|
+
DateFolder.new "2008-12-9"
|
109
|
+
|
110
|
+
|
111
|
+
Install
|
112
|
+
=======
|
113
|
+
|
114
|
+
gem install maiha-must
|
115
|
+
# add source http://gems.github.com
|
116
|
+
|
117
|
+
% irb -r rubygems -r must
|
118
|
+
irb(main):001:0> 1.must.be 1
|
119
|
+
=> 1
|
120
|
+
|
121
|
+
|
122
|
+
Github
|
123
|
+
======
|
124
|
+
|
125
|
+
http://github.com/maiha/must
|
126
|
+
|
127
|
+
|
128
|
+
Author
|
129
|
+
======
|
130
|
+
|
131
|
+
maiha@wota.jp
|
132
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
GEM_NAME = "must"
|
5
|
+
AUTHOR = "maiha"
|
6
|
+
EMAIL = "maiha@wota.jp"
|
7
|
+
HOMEPAGE = "http://github.com/maiha/must"
|
8
|
+
SUMMARY = "constraint plugin"
|
9
|
+
GEM_VERSION = "0.2.1"
|
10
|
+
|
11
|
+
spec = Gem::Specification.new do |s|
|
12
|
+
s.rubyforge_project = 'asakusarb'
|
13
|
+
s.executables = []
|
14
|
+
s.name = GEM_NAME
|
15
|
+
s.version = GEM_VERSION
|
16
|
+
s.platform = Gem::Platform::RUBY
|
17
|
+
s.has_rdoc = true
|
18
|
+
s.extra_rdoc_files = ["README"]
|
19
|
+
s.summary = SUMMARY
|
20
|
+
s.description = s.summary
|
21
|
+
s.author = AUTHOR
|
22
|
+
s.email = EMAIL
|
23
|
+
s.homepage = HOMEPAGE
|
24
|
+
s.require_path = 'lib'
|
25
|
+
s.files = %w(README Rakefile) + Dir.glob("{lib,spec,app,public,stubs}/**/*")
|
26
|
+
end
|
27
|
+
|
28
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
29
|
+
pkg.gem_spec = spec
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Install the gem"
|
33
|
+
task :install do
|
34
|
+
Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Uninstall the gem"
|
38
|
+
task :uninstall do
|
39
|
+
Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "Create a gemspec file"
|
43
|
+
task :gemspec do
|
44
|
+
File.open("#{GEM_NAME}.gemspec", "w") do |file|
|
45
|
+
file.puts spec.to_ruby
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
data/lib/must/rule.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Must
|
4
|
+
class Rule
|
5
|
+
attr_reader :object
|
6
|
+
|
7
|
+
def initialize(object)
|
8
|
+
@object = object
|
9
|
+
@not = false
|
10
|
+
end
|
11
|
+
|
12
|
+
def a() self end
|
13
|
+
def an() self end
|
14
|
+
|
15
|
+
def not
|
16
|
+
@not = ! @not
|
17
|
+
return self
|
18
|
+
end
|
19
|
+
|
20
|
+
def be(*args, &block)
|
21
|
+
if args.empty?
|
22
|
+
self
|
23
|
+
else
|
24
|
+
valid?(object == args.shift, &block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def empty(&block)
|
29
|
+
valid?(object.empty?, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def blank(&block)
|
33
|
+
valid?(object.blank?, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def exist(&block)
|
37
|
+
self.not()
|
38
|
+
be(nil, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def kind_of(*targets)
|
42
|
+
valid?(targets.any?{|klass| object.is_a? klass}) {
|
43
|
+
target = targets.map{|i| i.name}.join('/')
|
44
|
+
raise Invalid, "expected #{target} but got #{object.class}"
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def one_of(target, &block)
|
49
|
+
valid?(target === @object, &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
def valid?(condition, &block)
|
53
|
+
if condition ^ @not
|
54
|
+
object
|
55
|
+
else
|
56
|
+
block_or_throw(&block)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def block_or_throw(&block)
|
61
|
+
if block
|
62
|
+
block.call
|
63
|
+
else
|
64
|
+
raise Invalid
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def coerced(*types, &block)
|
69
|
+
coecings ||= types.last.is_a?(Hash) ? types.pop : {}
|
70
|
+
already_coerced ||= Set.new
|
71
|
+
kind_of(*types)
|
72
|
+
rescue Invalid
|
73
|
+
block_or_throw(&block) if already_coerced.include?(@object.class)
|
74
|
+
already_coerced << @object.class
|
75
|
+
@object =
|
76
|
+
case (obj = coecings[@object.class])
|
77
|
+
when Symbol ; @object.send obj
|
78
|
+
when Proc ; obj.call(@object)
|
79
|
+
else ; obj
|
80
|
+
end
|
81
|
+
retry
|
82
|
+
end
|
83
|
+
|
84
|
+
alias :match :one_of
|
85
|
+
end
|
86
|
+
end
|
data/lib/must.rb
ADDED
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: must
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 1
|
10
|
+
version: 0.2.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- maiha
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-06-07 00:00:00 +09:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: constraint plugin
|
23
|
+
email: maiha@wota.jp
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- README
|
30
|
+
files:
|
31
|
+
- README
|
32
|
+
- Rakefile
|
33
|
+
- lib/must/rule.rb
|
34
|
+
- lib/must.rb
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/maiha/must
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
hash: 3
|
50
|
+
segments:
|
51
|
+
- 0
|
52
|
+
version: "0"
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 3
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project: asakusarb
|
65
|
+
rubygems_version: 1.3.7
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: constraint plugin
|
69
|
+
test_files: []
|
70
|
+
|