must 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -148,6 +148,20 @@ NOTE
148
148
  Fixnum.must(1) # => Fixnum
149
149
 
150
150
 
151
+ Bundled Class
152
+ =============
153
+
154
+ struct = Must::StructInfo.new({"1.1" => {"jp"=>[{:a=>0},{:b=>2}]}})
155
+ struct.types # => [Hash, String, Array, Symbol, Fixnum]
156
+ struct.compact # => {String=>{String=>[{Symbol=>Fixnum}]}}
157
+ struct.inspect # => "{String=>{String=>[{Symbol=>Fixnum}]}}"
158
+
159
+
160
+ TODO
161
+ ====
162
+ * add proper error messages
163
+
164
+
151
165
  Install
152
166
  =======
153
167
  gem install must
data/lib/must/rule.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'set'
2
- require "must/same_struct"
2
+ require "must/struct_info"
3
3
 
4
4
  module Must
5
5
  class Rule
@@ -39,12 +39,13 @@ module Must
39
39
  be(nil, &block)
40
40
  end
41
41
 
42
- def kind_of(*targets)
42
+ def kind_of(*targets, &block)
43
43
  bool = targets.any?{|klass| is_a?(klass)}
44
- valid?(bool) {
44
+ block ||= proc {
45
45
  target = targets.map{|i| instance?(i) ? i.class.name : i.name}.join('/')
46
46
  raise Invalid, "expected #{target} but got #{object.class}"
47
47
  }
48
+ valid?(bool, &block)
48
49
  end
49
50
 
50
51
  def one_of(target, &block)
@@ -89,7 +90,7 @@ module Must
89
90
  end
90
91
 
91
92
  def struct?(target)
92
- Must::SameStruct.check(@object, target)
93
+ Must::StructInfo.new(@object).same?(target)
93
94
  end
94
95
 
95
96
  def struct(target, &block)
@@ -0,0 +1,101 @@
1
+ module Must
2
+ class StructInfo
3
+
4
+ module Classify
5
+ def classify(obj)
6
+ class?(obj) ? obj : obj.class
7
+ end
8
+
9
+ def class?(obj)
10
+ obj.class.to_s =~ /\A(Class|Module)\Z/o
11
+ end
12
+ end
13
+
14
+ module Browser
15
+ include Classify
16
+
17
+ def compact(obj)
18
+ case obj
19
+ when Hash
20
+ Hash[*(obj.first || []).map{|i| compact(i)}]
21
+ when Array
22
+ obj.empty? ? [] : [compact(obj.first)]
23
+ else
24
+ classify(obj)
25
+ end
26
+ end
27
+
28
+ def types(obj)
29
+ case obj
30
+ when Hash
31
+ ([Hash] + (obj.first || []).map{|i| types(i)}.flatten).uniq
32
+ when Array
33
+ ([Array] + obj.map{|i| types(i)}.flatten).uniq
34
+ else
35
+ [classify(obj)]
36
+ end
37
+ end
38
+
39
+ def same?(src, dst)
40
+ case src
41
+ when Hash
42
+ return true if dst == Hash
43
+ dst.must(Hash)
44
+ return true if src.empty?
45
+ return true if dst.empty?
46
+ key1, val1 = src.first
47
+ key2, val2 = dst.first
48
+ key1.must(key2)
49
+ val1.must(val2)
50
+
51
+ when Array
52
+ return true if dst == Array
53
+ dst.must(Array)
54
+ return true if src.empty?
55
+ return true if dst.empty?
56
+ src.first.must(dst.first)
57
+
58
+ else
59
+ # 1.must.struct(2)
60
+ # 1.must.struct(Integer)
61
+ dst_class = classify(dst)
62
+ return true if classify(src).ancestors.include?(dst_class)
63
+
64
+ # Fixnum.must.struct(2)
65
+ return true if class?(src) and src.ancestors.include?(dst_class)
66
+
67
+ return false
68
+ end
69
+ return true
70
+
71
+ rescue Must::Invalid
72
+ return false
73
+ end
74
+
75
+ extend self
76
+ end
77
+
78
+ ######################################################################
79
+ ### StructInfo
80
+
81
+ def initialize(obj)
82
+ @obj = obj
83
+ end
84
+
85
+ def types
86
+ Browser.types(@obj)
87
+ end
88
+
89
+ def compact
90
+ Browser.compact(@obj)
91
+ end
92
+
93
+ def same?(dst)
94
+ Browser.same?(@obj, dst)
95
+ end
96
+
97
+ def inspect
98
+ compact.inspect
99
+ end
100
+ end
101
+ end
data/lib/must/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Must
2
- VERSION = "0.2.4"
2
+ VERSION = "0.2.5"
3
3
  end
data/lib/must.rb CHANGED
@@ -5,9 +5,9 @@ module Must
5
5
  class Invalid < StandardError; end
6
6
  class ShouldNotEmpty < Invalid; end
7
7
 
8
- def must(*args)
8
+ def must(*args, &block)
9
9
  if args.size > 0
10
- Rule.new(self).be.kind_of(*args)
10
+ Rule.new(self).be.kind_of(*args, &block)
11
11
  else
12
12
  Rule.new(self)
13
13
  end
data/test/must_test.rb CHANGED
@@ -4,6 +4,9 @@ require File.join(File.dirname(__FILE__), '../init')
4
4
 
5
5
  class MustTest < Test::Unit::TestCase
6
6
 
7
+ ######################################################################
8
+ ### must be
9
+
7
10
  def test_must_be
8
11
  assert_nothing_raised {1.must.be 1}
9
12
  assert_nothing_raised {[1,2,3].must.be [1,2,3]}
@@ -28,6 +31,9 @@ class MustTest < Test::Unit::TestCase
28
31
  end
29
32
  end
30
33
 
34
+ ######################################################################
35
+ ### must(xxx)
36
+
31
37
  def test_must_accepts_args_as_kind_of
32
38
  assert_equal "ok", "ok".must(String)
33
39
  assert_raises(Invalid) {"ok".must(Integer)}
@@ -36,5 +42,23 @@ class MustTest < Test::Unit::TestCase
36
42
  # NOTE: this passes because 1(integer) is a kind of 2(integer)
37
43
  assert_equal 1, 1.must(2)
38
44
  end
45
+
46
+ def test_must_with_block
47
+ assert_equal :error, "ok".must(Integer) {:error}
48
+ end
49
+
50
+ ######################################################################
51
+ ### kind_of
52
+
53
+ def test_kind_of
54
+ assert_equal "ok", "ok".must.be.kind_of(String)
55
+ assert_raises(Invalid) {"ok".must.be.kind_of(Integer)}
56
+ end
57
+
58
+ def test_kind_of_several_args
59
+ assert_equal "ok", "ok".must.be.kind_of(Integer,String)
60
+ assert_equal "ok", "ok".must.be.kind_of(String,Integer)
61
+ assert_raises(Invalid) {"ok".must.be.kind_of(Integer, Array)}
62
+ end
39
63
  end
40
64
 
@@ -0,0 +1,53 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require File.join(File.dirname(__FILE__), '../init')
4
+
5
+ class StructInfoTest < Test::Unit::TestCase
6
+ ######################################################################
7
+ ### same?
8
+
9
+ def test_same_p
10
+ assert Must::StructInfo.new(1).same?(Integer)
11
+ assert Must::StructInfo.new(1).same?(Numeric)
12
+ assert ! Must::StructInfo.new(1).same?(String)
13
+
14
+ assert Must::StructInfo.new(Integer).same?(Integer)
15
+ assert Must::StructInfo.new(Integer).same?(Numeric)
16
+ assert Must::StructInfo.new(Fixnum).same?(1)
17
+ end
18
+
19
+ ######################################################################
20
+ ### types
21
+
22
+ def test_types
23
+ assert_equal [Fixnum], Must::StructInfo.new(1).types
24
+ assert_equal [Hash, Symbol, String, Float], Must::StructInfo.new({:a=>{"1"=>0.25}}).types
25
+ end
26
+
27
+ ######################################################################
28
+ ### struct
29
+
30
+ def test_compact
31
+ assert_equal(Fixnum, Must::StructInfo.new(1).compact)
32
+ assert_equal({}, Must::StructInfo.new({}).compact)
33
+ assert_equal({String=>Fixnum}, Must::StructInfo.new({"a"=>1}).compact)
34
+ assert_equal([{String=>Float}], Must::StructInfo.new([{"1"=>0.25}]).compact)
35
+ assert_equal({String=>{String=>[{Symbol=>Fixnum}]}}, Must::StructInfo.new({"1.1" => {"jp"=>[{:a=>0},{:b=>2}]}}).compact)
36
+ end
37
+
38
+ def test_compact_array_into_first_element
39
+ assert_equal [Fixnum], Must::StructInfo.new([1, "a"]).compact
40
+ assert_equal [String], Must::StructInfo.new(["a", 1]).compact
41
+ end
42
+
43
+ ######################################################################
44
+ ### pp
45
+
46
+ def test_inspect
47
+ assert_equal "Fixnum", Must::StructInfo.new(1).inspect
48
+ assert_equal "{}", Must::StructInfo.new({}).inspect
49
+ assert_equal "{String=>Fixnum}", Must::StructInfo.new({"a"=>1}).inspect
50
+ assert_equal "[{String=>Float}]", Must::StructInfo.new([{"1"=>0.25}]).inspect
51
+ assert_equal "{String=>{String=>[{Symbol=>Fixnum}]}}", Must::StructInfo.new({"1.1" => {"jp"=>[{:a=>0},{:b=>2}]}}).inspect
52
+ end
53
+ end
data/test/struct_test.rb CHANGED
@@ -3,39 +3,46 @@ require 'rubygems'
3
3
  require File.join(File.dirname(__FILE__), '../init')
4
4
 
5
5
  class StructTest < Test::Unit::TestCase
6
- def test_struct_test_successed
7
- assert_equal true, [].must.struct?([])
8
- assert_equal true, 1.must.struct?(Integer)
9
- assert_equal true, 1.must.struct?(Fixnum)
10
- assert_equal true, 1.must.struct?(2)
11
- assert_equal true, Fixnum.must.struct?(Fixnum)
12
- assert_equal true, Fixnum.must.struct?(2)
6
+ def test_struct_basic_object
7
+ assert [].must.struct?([])
8
+ assert ! [].must.struct?({})
13
9
 
14
- obj = {"foo" => 1}
15
- assert_equal true, obj.must.struct?({String => Integer})
16
-
17
- obj = {"foo" => [{:a=>1}, {:a=>3}]}
18
- assert_equal true, obj.must.struct?(Hash)
19
- assert_equal true, obj.must.struct?({String => Array})
20
- assert_equal true, obj.must.struct?({String => [Hash]})
10
+ assert 1.must.struct?(Integer)
11
+ assert 1.must.struct?(Fixnum)
12
+ assert 1.must.struct?(2)
13
+ assert ! 1.must.struct?(String)
14
+ assert Fixnum.must.struct?(Fixnum)
15
+ assert Fixnum.must.struct?(2)
16
+ assert ! Integer.must.struct?(Fixnum)
21
17
  end
22
18
 
23
- def test_struct_test_failed
24
- assert_equal false, [].must.struct?({})
25
- assert_equal false, Integer.must.struct?(Fixnum)
26
-
19
+ def test_struct_composite_objects
27
20
  obj = {"foo" => 1}
28
- assert_equal false, obj.must.struct?(String)
29
- assert_equal false, obj.must.struct?(Array)
30
- assert_equal false, obj.must.struct?([String])
31
- assert_equal false, obj.must.struct?({String => String})
21
+ assert obj.must.struct?({String => Integer})
22
+ assert ! obj.must.struct?(String)
23
+ assert ! obj.must.struct?(Array)
24
+ assert ! obj.must.struct?([String])
25
+ assert ! obj.must.struct?({String => String})
32
26
 
33
27
  obj = [{:a=>1}, {:a=>3}]
34
- assert_equal false, obj.must.struct?([Array])
28
+ assert obj.must.struct?([Hash])
29
+ assert ! obj.must.struct?([Array])
30
+
31
+ obj = {"foo" => [{:a=>1}, {:a=>3}]}
32
+ assert obj.must.struct?(Hash)
33
+ assert ! obj.must.struct?(Array)
34
+ assert obj.must.struct?({String => Array})
35
+ assert ! obj.must.struct?({Array => Array})
36
+ assert obj.must.struct?({String => [Hash]})
35
37
 
36
38
  obj = {"foo" => [{:a=>1}, {:a=>3}]}
37
- assert_equal false, obj.must.struct?({String => Hash})
38
- assert_equal false, obj.must.struct?({String => [Array]})
39
+ assert obj.must.struct?({String => []})
40
+ assert obj.must.struct?({String => Array})
41
+ assert ! obj.must.struct?({String => Hash})
42
+ assert obj.must.struct?({String => [Hash]})
43
+ assert obj.must.struct?({String => Array(Hash)})
44
+ assert ! obj.must.struct?({String => [Array]})
45
+ assert ! obj.must.struct?({String => Array(String)})
39
46
  end
40
47
 
41
48
  def test_struct_complicated
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: 31
4
+ hash: 29
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 4
10
- version: 0.2.4
9
+ - 5
10
+ version: 0.2.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - maiha
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-27 00:00:00 +09:00
18
+ date: 2012-02-09 00:00:00 +09:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -35,13 +35,14 @@ files:
35
35
  - install.rb
36
36
  - lib/must.rb
37
37
  - lib/must/rule.rb
38
- - lib/must/same_struct.rb
38
+ - lib/must/struct_info.rb
39
39
  - lib/must/version.rb
40
40
  - must.gemspec
41
41
  - test/coerced_test.rb
42
42
  - test/duck_test.rb
43
43
  - test/match_test.rb
44
44
  - test/must_test.rb
45
+ - test/struct_info_test.rb
45
46
  - test/struct_test.rb
46
47
  has_rdoc: true
47
48
  homepage: http://github.com/maiha/must
@@ -1,47 +0,0 @@
1
- module Must
2
- module SameStruct
3
- def self.check(src, dst)
4
- case src
5
- when Hash
6
- return true if dst == Hash
7
- dst.must(Hash)
8
- return true if src.empty?
9
- return true if dst.empty?
10
- key1, val1 = src.first
11
- key2, val2 = dst.first
12
- key1.must(key2)
13
- val1.must(val2)
14
-
15
- when Array
16
- return true if dst == Array
17
- dst.must(Array)
18
- return true if src.empty?
19
- return true if dst.empty?
20
- src.first.must(dst.first)
21
-
22
- else
23
- # 1.must.struct(2)
24
- # 1.must.struct(Integer)
25
- dst_class = classify(dst)
26
- return true if classify(src).ancestors.include?(dst_class)
27
-
28
- # Fixnum.must.struct(2)
29
- return true if class?(src) and src.ancestors.include?(dst_class)
30
-
31
- return false
32
- end
33
- return true
34
-
35
- rescue Must::Invalid
36
- return false
37
- end
38
-
39
- def self.classify(obj)
40
- class?(obj) ? obj : obj.class
41
- end
42
-
43
- def self.class?(obj)
44
- obj.class.to_s =~ /\A(Class|Module)\Z/o
45
- end
46
- end
47
- end