must 0.2.2 → 0.2.3

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
@@ -10,9 +10,14 @@ add Object#must method to constrain its origin and conversions
10
10
  num = params[:num].to_i
11
11
  num = 10 unless (1..300) === num
12
12
 
13
+ and has duck features
13
14
 
14
- Testing Methods
15
- ===============
15
+ 1.must.duck?(:to_s) # => true
16
+ io.must.duck(:write) { io.extend Writable }
17
+
18
+
19
+ Asking Methods
20
+ ==============
16
21
 
17
22
  be : check whether object equals to the argument
18
23
  kind_of : check whether object is a kind of the arguments
@@ -36,6 +41,15 @@ an : return self
36
41
  These effect nothing but exist only for English grammar.
37
42
 
38
43
 
44
+ Duck Methods
45
+ ============
46
+ duck("foo") : check whether object responds to "foo" method.
47
+ duck(:foo) : same above
48
+ duck(".foo") : same above
49
+ duck("#foo") : check whether object has "foo" instance method. (tested only in class/module)
50
+ duck?(...) : acts same as "duck", but this returns a just boolean
51
+
52
+
39
53
  Basic Examples
40
54
  ==============
41
55
 
@@ -114,8 +128,7 @@ Actual Examples
114
128
  Install
115
129
  =======
116
130
 
117
- gem install maiha-must
118
- # add source http://gems.github.com
131
+ gem install must
119
132
 
120
133
  % irb -r rubygems -r must
121
134
  irb(main):001:0> 1.must.be 1
data/lib/must/rule.rb CHANGED
@@ -48,6 +48,7 @@ module Must
48
48
  def one_of(target, &block)
49
49
  valid?(target === @object, &block)
50
50
  end
51
+ alias :match :one_of
51
52
 
52
53
  def valid?(condition, &block)
53
54
  if condition ^ @not
@@ -81,6 +82,31 @@ module Must
81
82
  retry
82
83
  end
83
84
 
84
- alias :match :one_of
85
+ def duck(method_name, &block)
86
+ valid?(duck?(method_name), &block)
87
+ end
88
+
89
+ def duck?(method_name)
90
+ case method_name.to_s
91
+ when /^\./ then method_defined?($')
92
+ when /^#/ then instance_method_defined?($')
93
+ else ; method_defined?(method_name)
94
+ end
95
+ end
96
+
97
+ private
98
+ def instance?
99
+ @object.class.to_s !~ /\A(Class|Module)\Z/o
100
+ end
101
+
102
+ def instance_method_defined?(method_name)
103
+ return false if instance?
104
+ !! @object.instance_methods.find { |m| m.to_s == method_name.to_s}
105
+ end
106
+
107
+ def method_defined?(method_name)
108
+ @object.respond_to?(method_name)
109
+ end
110
+
85
111
  end
86
112
  end
@@ -0,0 +1,3 @@
1
+ module Must
2
+ VERSION = "0.2.3"
3
+ end
data/lib/must.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require "must/version"
2
+
1
3
  # Must
2
4
  module Must
3
5
  class Invalid < StandardError; end
@@ -12,5 +14,5 @@ module Must
12
14
  end
13
15
  end
14
16
 
15
- require File.dirname(__FILE__) + '/must/rule'
17
+ require "must/rule"
16
18
  Object.__send__ :include, Must
data/must.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "must/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "must"
7
+ s.version = Must::VERSION
8
+ s.authors = ["maiha"]
9
+ s.email = ["maiha@wota.jp"]
10
+ s.homepage = "http://github.com/maiha/must"
11
+ s.summary = %q{a runtime specification tool}
12
+ s.description = %q{add Object#must method to constrain its origin and conversions}
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ # specify any dependencies here; for example:
20
+ # s.add_development_dependency "rspec"
21
+ # s.add_runtime_dependency "rest-client"
22
+ end
@@ -0,0 +1,39 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require File.join(File.dirname(__FILE__), '../init')
4
+
5
+ class CoercedTest < Test::Unit::TestCase
6
+ def test_is_a_feature
7
+ assert_equal 1, 1.must.be.coerced(Integer)
8
+ assert_equal 1, 1.must.be.coerced(Integer, String)
9
+ assert_equal 1, 1.must.be.coerced(String, Numeric)
10
+
11
+ assert_raises(Invalid) { "1".must.be.coerced(Integer) }
12
+ assert_raises(Invalid) { "1".must.be.coerced(Integer, Range) }
13
+ assert_raises(NotImplementedError) { "1".must.be.coerced(Integer){raise NotImplementedError} }
14
+ end
15
+
16
+ def test_coecing_succeeded
17
+ assert_equal 1, 1.must.be.coerced(Integer, String=>proc{|i|i.to_i})
18
+ assert_equal 1, "1".must.be.coerced(Integer, String=>proc{|i|i.to_i})
19
+ assert_equal 1, "1".must.be.coerced(Integer, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
20
+ assert_equal 1, "1".must.be.coerced(Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
21
+ assert_equal 1, "1".must.be.coerced(File, Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
22
+ end
23
+
24
+ def test_coecing_failed
25
+ assert_raises(Invalid) { "1".must.be.coerced(Integer, String=>proc{|i| /a/}) }
26
+ assert_raises(NotImplementedError) { "1".must.be.coerced(Integer, String=>proc{|i| /a/}){raise NotImplementedError} }
27
+ end
28
+
29
+ def test_cascaded_coecing_succeeded
30
+ assert_equal 1, 1.must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
31
+ assert_equal 1, "1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
32
+ assert_equal 1, :"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
33
+ end
34
+
35
+ def test_detect_livelock
36
+ assert_raises(Invalid){ "1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}
37
+ assert_raises(Invalid){:"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}
38
+ end
39
+ end
data/test/duck_test.rb ADDED
@@ -0,0 +1,83 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require File.join(File.dirname(__FILE__), '../init')
4
+
5
+ class DuckTest < Test::Unit::TestCase
6
+ class ClassFoo
7
+ def foo; 1; end
8
+ end
9
+
10
+ module ModuleFoo
11
+ def foo; 1; end
12
+ end
13
+
14
+ def test_itself_duck_type
15
+ # succeeded
16
+ assert_equal 1, 1.must.duck(:to_s)
17
+ assert_equal 1, 1.must.duck("to_s")
18
+ assert_equal 1, 1.must.duck(".to_s")
19
+ assert_equal ClassFoo, ClassFoo.must.duck(:to_s)
20
+ assert_equal ClassFoo, ClassFoo.must.duck("to_s")
21
+ assert_equal ClassFoo, ClassFoo.must.duck(".to_s")
22
+ assert_equal ModuleFoo, ModuleFoo.must.duck(:to_s)
23
+ assert_equal ModuleFoo, ModuleFoo.must.duck("to_s")
24
+ assert_equal ModuleFoo, ModuleFoo.must.duck(".to_s")
25
+
26
+ # failed
27
+ assert_raises(Invalid) { 1.must.duck(:foo) }
28
+ assert_raises(Invalid) { 1.must.duck("foo") }
29
+ assert_raises(Invalid) { 1.must.duck(".foo") }
30
+ assert_raises(Invalid) { ClassFoo.must.duck(:foo) }
31
+ assert_raises(Invalid) { ClassFoo.must.duck("foo") }
32
+ assert_raises(Invalid) { ClassFoo.must.duck(".foo") }
33
+ assert_raises(Invalid) { ModuleFoo.must.duck(:foo) }
34
+ assert_raises(Invalid) { ModuleFoo.must.duck("foo") }
35
+ assert_raises(Invalid) { ModuleFoo.must.duck(".foo") }
36
+ end
37
+
38
+ def test_instance_duck_type
39
+ # succeeded
40
+ assert_equal ClassFoo, ClassFoo.must.duck("#foo")
41
+ assert_equal ModuleFoo, ModuleFoo.must.duck("#foo")
42
+
43
+ # failed
44
+ assert_raises(Invalid) { 1.must.duck("#bar") } # instance object
45
+ assert_raises(Invalid) { ClassFoo.must.duck("#bar") }
46
+ assert_raises(Invalid) { ModuleFoo.must.duck("#bar") }
47
+ end
48
+
49
+ def test_itself_duck_test
50
+ # succeeded
51
+ assert_equal true, 1.must.duck?(:to_s)
52
+ assert_equal true, 1.must.duck?("to_s")
53
+ assert_equal true, 1.must.duck?(".to_s")
54
+ assert_equal true, ClassFoo.must.duck?(:to_s)
55
+ assert_equal true, ClassFoo.must.duck?("to_s")
56
+ assert_equal true, ClassFoo.must.duck?(".to_s")
57
+ assert_equal true, ModuleFoo.must.duck?(:to_s)
58
+ assert_equal true, ModuleFoo.must.duck?("to_s")
59
+ assert_equal true, ModuleFoo.must.duck?(".to_s")
60
+
61
+ # failed
62
+ assert_equal false, 1.must.duck?(:foo)
63
+ assert_equal false, 1.must.duck?("foo")
64
+ assert_equal false, 1.must.duck?(".foo")
65
+ assert_equal false, ClassFoo.must.duck?(:foo)
66
+ assert_equal false, ClassFoo.must.duck?("foo")
67
+ assert_equal false, ClassFoo.must.duck?(".foo")
68
+ assert_equal false, ModuleFoo.must.duck?(:foo)
69
+ assert_equal false, ModuleFoo.must.duck?("foo")
70
+ assert_equal false, ModuleFoo.must.duck?(".foo")
71
+ end
72
+
73
+ def test_instance_duck_test
74
+ # succeeded
75
+ assert_equal true, ClassFoo.must.duck?("#foo")
76
+ assert_equal true, ModuleFoo.must.duck?("#foo")
77
+
78
+ # failed
79
+ assert_equal false, 1.must.duck?("#bar") # instance object
80
+ assert_equal false, ClassFoo.must.duck?("#bar")
81
+ assert_equal false, ModuleFoo.must.duck?("#bar")
82
+ end
83
+ end
@@ -0,0 +1,15 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require File.join(File.dirname(__FILE__), '../init')
4
+
5
+ class MatchTest < Test::Unit::TestCase
6
+ def test_match_range
7
+ # succeeded
8
+ assert_equal 1, 1.must.match(0..3)
9
+ assert_equal 'b', 'b'.must.match('a'..'c')
10
+
11
+ # failed
12
+ assert_raises(Invalid) { 1.must.match(2..3) }
13
+ assert_raises(Invalid) { 'a'.must.match('y'..'z') }
14
+ end
15
+ end
data/test/must_test.rb CHANGED
@@ -35,53 +35,3 @@ class MustTest < Test::Unit::TestCase
35
35
  end
36
36
  end
37
37
 
38
-
39
- class CoercedTest < Test::Unit::TestCase
40
- def test_is_a_feature
41
- assert_equal 1, 1.must.be.coerced(Integer)
42
- assert_equal 1, 1.must.be.coerced(Integer, String)
43
- assert_equal 1, 1.must.be.coerced(String, Numeric)
44
-
45
- assert_raises(Invalid) { "1".must.be.coerced(Integer) }
46
- assert_raises(Invalid) { "1".must.be.coerced(Integer, Range) }
47
- assert_raises(NotImplementedError) { "1".must.be.coerced(Integer){raise NotImplementedError} }
48
- end
49
-
50
- def test_coecing_succeeded
51
- assert_equal 1, 1.must.be.coerced(Integer, String=>proc{|i|i.to_i})
52
- assert_equal 1, "1".must.be.coerced(Integer, String=>proc{|i|i.to_i})
53
- assert_equal 1, "1".must.be.coerced(Integer, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
54
- assert_equal 1, "1".must.be.coerced(Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
55
- assert_equal 1, "1".must.be.coerced(File, Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
56
- end
57
-
58
- def test_coecing_failed
59
- assert_raises(Invalid) { "1".must.be.coerced(Integer, String=>proc{|i| /a/}) }
60
- assert_raises(NotImplementedError) { "1".must.be.coerced(Integer, String=>proc{|i| /a/}){raise NotImplementedError} }
61
- end
62
-
63
- def test_cascaded_coecing_succeeded
64
- assert_equal 1, 1.must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
65
- assert_equal 1, "1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
66
- assert_equal 1, :"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
67
- end
68
-
69
- def test_detect_livelock
70
- assert_raises(Invalid){ "1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}
71
- assert_raises(Invalid){:"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}
72
- end
73
-
74
- end
75
-
76
-
77
- class MatchTest < Test::Unit::TestCase
78
- def test_match_range
79
- # succeeded
80
- assert_equal 1, 1.must.match(0..3)
81
- assert_equal 'b', 'b'.must.match('a'..'c')
82
-
83
- # failed
84
- assert_raises(Invalid) { 1.must.match(2..3) }
85
- assert_raises(Invalid) { 'a'.must.match('y'..'z') }
86
- end
87
- end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: must
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 2
10
- version: 0.2.2
9
+ - 3
10
+ version: 0.2.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - maiha
@@ -15,12 +15,13 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-25 00:00:00 +09:00
18
+ date: 2012-01-26 00:00:00 +09:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
22
- description: ""
23
- email: maiha@wota.jp
22
+ description: add Object#must method to constrain its origin and conversions
23
+ email:
24
+ - maiha@wota.jp
24
25
  executables: []
25
26
 
26
27
  extensions: []
@@ -34,7 +35,11 @@ files:
34
35
  - install.rb
35
36
  - lib/must.rb
36
37
  - lib/must/rule.rb
37
- - tasks/expectation_tasks.rake
38
+ - lib/must/version.rb
39
+ - must.gemspec
40
+ - test/coerced_test.rb
41
+ - test/duck_test.rb
42
+ - test/match_test.rb
38
43
  - test/must_test.rb
39
44
  has_rdoc: true
40
45
  homepage: http://github.com/maiha/must
@@ -69,6 +74,6 @@ rubyforge_project:
69
74
  rubygems_version: 1.3.7
70
75
  signing_key:
71
76
  specification_version: 3
72
- summary: ""
77
+ summary: a runtime specification tool
73
78
  test_files: []
74
79
 
@@ -1,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :must do
3
- # # Task goes here
4
- # end