json-inference 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- json-inference (0.0.1)
4
+ json-inference (0.0.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -3,147 +3,84 @@ module JsonInference
3
3
  Report.new
4
4
  end
5
5
 
6
- class BaseNode
7
- def initialize
8
- @value_classes = Hash.new 0
9
- @sub_nodes = Hash.new { |h,k|
10
- if k == :nth_child
11
- sub_node = NthChildNode.new(self)
12
- else
13
- sub_node = Node.new(k, self)
14
- end
15
- h[k] = sub_node
16
- }
17
- end
18
-
19
- def <<(value)
20
- if value.is_a?(Hash)
21
- value.each do |key, sub_value|
22
- @sub_nodes[key] << sub_value
23
- end
24
- elsif value.is_a?(Array)
25
- @sub_nodes[:nth_child]
26
- value.each do |sub_value|
27
- @sub_nodes[:nth_child] << sub_value
28
- end
29
- end
30
- if value.class == String && value =~ /^(\d){4}-(\d){2}-(\d){2}T(\d){2}:(\d){2}:(\d){2}\.(\d){3}Z$/
31
- @value_classes[Date] += 1
32
- elsif [true, false].include?(value)
33
- @value_classes['Boolean'] += 1
34
- else
35
- @value_classes[value.class] += 1
36
- end
37
- end
38
-
39
- def each_sub_node
40
- @sub_nodes.keys.sort.each do |key|
41
- sub_node = @sub_nodes[key]
42
- yield sub_node
43
- end
44
- end
45
-
46
- def indent_level
47
- @parent.indent_level + 1
48
- end
49
-
50
- def indent
51
- ' ' * indent_level
52
- end
53
-
54
- def total_count
55
- @value_classes.values.inject { |sum, i| sum + i } || 0
56
- end
6
+ def self.percent_string(numerator, denominator)
7
+ "#{(numerator / denominator.to_f * 100).round}%"
57
8
  end
58
9
 
59
- class Node < BaseNode
60
- def initialize(name = nil, parent = nil)
61
- super()
62
- @name, @parent = name, parent
63
- end
64
-
65
- def selector
66
- "#{@parent.selector} > .#{@name}"
10
+ class Report
11
+ def initialize
12
+ @documents = []
13
+ @root = RootNode.new
67
14
  end
68
15
 
69
- def selector_line(documents_count)
70
- "#{indent}#{selector}: #{total_count}/#{documents_count} (#{(total_count.to_f / documents_count * 100).round}%)\n"
16
+ def <<(document)
17
+ @documents << document
18
+ @root << document
71
19
  end
72
20
 
73
- def to_s(documents_count)
74
- str = ""
75
- str << selector_line(documents_count)
76
- @value_classes.each do |klass, count|
77
- str << " #{indent}#{klass}: #{(count / total_count.to_f * 100).round}%\n"
78
- end
79
- each_sub_node do |sub_node|
80
- str << sub_node.to_s(documents_count)
81
- end
21
+ def to_s
22
+ str = "JsonInference report: #{@documents.size} documents\n"
23
+ str << @root.to_s(@documents.size)
82
24
  str
83
25
  end
84
26
  end
85
27
 
86
- class NthChildNode < BaseNode
87
- def initialize(parent)
88
- super()
89
- @parent = parent
28
+ class NodeValuesCollection
29
+ def initialize
30
+ @value_counters = Hash.new { |h,k| h[k] = ValueCounter.new(k) }
90
31
  end
91
32
 
92
- def selector
93
- "#{@parent.selector}:nth-child()"
33
+ def <<(value)
34
+ if value.class == String && value =~ /^(\d){4}-(\d){2}-(\d){2}T(\d){2}:(\d){2}:(\d){2}\.(\d){3}Z$/
35
+ @value_counters[Date] << value
36
+ elsif [true, false].include?(value)
37
+ @value_counters['Boolean'] << value
38
+ else
39
+ @value_counters[value.class] << value
40
+ end
94
41
  end
95
42
 
96
- def selector_line(documents_count)
97
- "#{indent}#{selector}: #{total_count} child#{'ren' unless total_count == 1}\n"
43
+ def size
44
+ @value_counters.values.inject(0) { |sum, counter| sum + counter.size } || 0
98
45
  end
99
46
 
100
- def to_s(documents_count)
47
+ def to_s(indent)
101
48
  str = ""
102
- str << selector_line(documents_count)
103
- @value_classes.each do |klass, count|
104
- str << " #{indent}#{klass}: #{(count / total_count.to_f * 100).round}%\n"
105
- end
106
- each_sub_node do |sub_node|
107
- str << sub_node.to_s(total_count)
49
+ @value_counters.values.each do |value_counter|
50
+ str << " #{indent}#{value_counter.to_s(size)}\n"
108
51
  end
109
52
  str
110
53
  end
111
- end
112
54
 
113
- class RootNode < BaseNode
114
- def indent_level
115
- -1
116
- end
55
+ class ValueCounter
56
+ attr_reader :size
117
57
 
118
- def selector
119
- ':root'
120
- end
121
-
122
- def to_s(documents_count)
123
- str = ""
124
- each_sub_node do |sub_node|
125
- str << sub_node.to_s(documents_count)
126
- str << "\n"
58
+ def initialize(reported_class)
59
+ @reported_class = reported_class
60
+ @size = 0
61
+ @empties = 0
127
62
  end
128
- str
129
- end
130
- end
131
63
 
132
- class Report
133
- def initialize
134
- @documents = []
135
- @root = RootNode.new
136
- end
137
-
138
- def <<(document)
139
- @documents << document
140
- @root << document
141
- end
64
+ def <<(value)
65
+ @size += 1
66
+ if [Array, String].include?(@reported_class)
67
+ @empties += 1 if value.empty?
68
+ end
69
+ end
142
70
 
143
- def to_s
144
- str = "JsonInference report: #{@documents.size} documents\n"
145
- str << @root.to_s(@documents.size)
146
- str
71
+ def to_s(all_values_count)
72
+ str = "#{@reported_class}: #{JsonInference.percent_string(size, all_values_count)}"
73
+ if [Array, String].include?(@reported_class)
74
+ str << ", #{JsonInference.percent_string(@empties, size)} empty"
75
+ end
76
+ str
77
+ end
147
78
  end
148
79
  end
149
80
  end
81
+
82
+ dir = File.dirname(__FILE__) + "/json-inference"
83
+ require "#{dir}/base_node"
84
+ require "#{dir}/node"
85
+ require "#{dir}/nth_child_node"
86
+ require "#{dir}/root_node"
@@ -0,0 +1,44 @@
1
+ module JsonInference
2
+ class BaseNode
3
+ def initialize
4
+ @values = NodeValuesCollection.new
5
+ @sub_nodes = Hash.new { |h,k|
6
+ if k == :nth_child
7
+ sub_node = JsonInference::NthChildNode.new(self)
8
+ else
9
+ sub_node = JsonInference::Node.new(k, self)
10
+ end
11
+ h[k] = sub_node
12
+ }
13
+ end
14
+
15
+ def <<(value)
16
+ if value.is_a?(Hash)
17
+ value.each do |key, sub_value|
18
+ @sub_nodes[key] << sub_value
19
+ end
20
+ elsif value.is_a?(Array)
21
+ @sub_nodes[:nth_child]
22
+ value.each do |sub_value|
23
+ @sub_nodes[:nth_child] << sub_value
24
+ end
25
+ end
26
+ @values << value
27
+ end
28
+
29
+ def each_sub_node
30
+ @sub_nodes.keys.sort.each do |key|
31
+ sub_node = @sub_nodes[key]
32
+ yield sub_node
33
+ end
34
+ end
35
+
36
+ def indent_level
37
+ @parent.indent_level + 1
38
+ end
39
+
40
+ def indent
41
+ ' ' * indent_level
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,26 @@
1
+ module JsonInference
2
+ class Node < BaseNode
3
+ def initialize(name = nil, parent = nil)
4
+ super()
5
+ @name, @parent = name, parent
6
+ end
7
+
8
+ def selector
9
+ "#{@parent.selector} > .#{@name}"
10
+ end
11
+
12
+ def selector_line(documents_count)
13
+ "#{indent}#{selector}: #{@values.size}/#{documents_count} (#{JsonInference.percent_string(@values.size, documents_count)})\n"
14
+ end
15
+
16
+ def to_s(documents_count)
17
+ str = ""
18
+ str << selector_line(documents_count)
19
+ str << @values.to_s(indent)
20
+ each_sub_node do |sub_node|
21
+ str << sub_node.to_s(documents_count)
22
+ end
23
+ str
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module JsonInference
2
+ class NthChildNode < BaseNode
3
+ def initialize(parent)
4
+ super()
5
+ @parent = parent
6
+ end
7
+
8
+ def selector
9
+ "#{@parent.selector}:nth-child()"
10
+ end
11
+
12
+ def selector_line(documents_count)
13
+ "#{indent}#{selector}: #{@values.size} child#{'ren' unless @values.size == 1}\n"
14
+ end
15
+
16
+ def to_s(documents_count)
17
+ str = ""
18
+ str << selector_line(documents_count)
19
+ str << @values.to_s(indent)
20
+ each_sub_node do |sub_node|
21
+ str << sub_node.to_s(@values.size)
22
+ end
23
+ str
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,20 @@
1
+ module JsonInference
2
+ class RootNode < BaseNode
3
+ def indent_level
4
+ -1
5
+ end
6
+
7
+ def selector
8
+ ':root'
9
+ end
10
+
11
+ def to_s(documents_count)
12
+ str = ""
13
+ each_sub_node do |sub_node|
14
+ str << sub_node.to_s(documents_count)
15
+ str << "\n"
16
+ end
17
+ str
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,5 @@
1
1
  module Json
2
2
  module Inference
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -158,4 +158,18 @@ class JsonInferenceTestCase < Test::Unit::TestCase
158
158
  assert_match(/:root > .items:nth-child\(\): 0 children$/, @string)
159
159
  end
160
160
  end
161
+
162
+ context "field with empty strings" do
163
+ setup do
164
+ report = JsonInference.new_report
165
+ report << {foo: 'one'}
166
+ report << {foo: '', bar: 'ONE'}
167
+ report << {foo: '', baz: 'won'}
168
+ @string = report.to_s
169
+ end
170
+
171
+ should "note how likely it is to be empty" do
172
+ assert_match(/String: 100%, 67% empty/, @string)
173
+ end
174
+ end
161
175
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-inference
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-20 00:00:00.000000000 Z
12
+ date: 2014-01-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -59,6 +59,10 @@ files:
59
59
  - Rakefile
60
60
  - json-inference.gemspec
61
61
  - lib/json-inference.rb
62
+ - lib/json-inference/base_node.rb
63
+ - lib/json-inference/node.rb
64
+ - lib/json-inference/nth_child_node.rb
65
+ - lib/json-inference/root_node.rb
62
66
  - lib/json-inference/version.rb
63
67
  - test/json_inference_test.rb
64
68
  homepage: ''
@@ -76,7 +80,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
76
80
  version: '0'
77
81
  segments:
78
82
  - 0
79
- hash: -2986096997133027698
83
+ hash: -3344776264180278235
80
84
  required_rubygems_version: !ruby/object:Gem::Requirement
81
85
  none: false
82
86
  requirements:
@@ -85,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
89
  version: '0'
86
90
  segments:
87
91
  - 0
88
- hash: -2986096997133027698
92
+ hash: -3344776264180278235
89
93
  requirements: []
90
94
  rubyforge_project:
91
95
  rubygems_version: 1.8.23