must 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|