must 0.2.4 → 0.2.5

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
@@ -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