dataset_explorer 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 788e4dd9aa7ed70db9482c9eb8c5cc35fabae5039232dc2c10e0276fa97caf14
4
- data.tar.gz: 0d14ebb6e7ae2363dfe47236b1a89565fbda381fecb4dc8732448dd27fbe82bf
3
+ metadata.gz: e0325eced24214509e9177b70341bc1120ea26c5b523918501f2884fdd57c92a
4
+ data.tar.gz: face9b64530c6b771258d23f512c24955e6bd073d881802d6b538dd0f5b046b7
5
5
  SHA512:
6
- metadata.gz: eae4397828a7fb6c88da601ed429292893a9925089e37c4b7be57d3879c664605bcdeb40736e27da2522c7a8e1fdd587d91419d59b22fb5912d4b96523a0b1f2
7
- data.tar.gz: c41ee84d680ce45f9d22e46b732bf31fc6490b0ded9f18f7ad721df4d91b9670747a83d375fcf78128e7e06e78993f93d5874870882d668940d37e02316d782d
6
+ metadata.gz: a1c7aa73cd0f51295b1cf01b1ece8e7756c9a5e498a22f475efccecb2036f065844f0564e9fd6c05379cefe35729ec7cdc84aea57577f81c46a17e3ab628586b
7
+ data.tar.gz: 0d75d122ea2a1696a06215c631e14760b1d6cba3271c73462af85ade96f85b886f72f6fb5a0500fd2794720a5c46509c2d2e4c14ca3e7ab632a00ec4863e6532
@@ -7,6 +7,7 @@ Metrics/BlockLength:
7
7
  - 'spec/**/*'
8
8
 
9
9
  Metrics/MethodLength:
10
+ Max: 15
10
11
  Exclude:
11
12
  - 'db/migrate/**.rb'
12
13
 
data/README.md CHANGED
@@ -56,82 +56,82 @@ urls = {
56
56
  COLLECTOR = DatasetExplorer::Collector.instance
57
57
 
58
58
  urls.each do |provider, url|
59
- data = [JSON.parse(open(url).read)].flatten
60
-
61
- data.each do |item|
62
- COLLECTOR.collect(provider, item)
63
- end
59
+ data = JSON.parse(open(url).read)
60
+ COLLECTOR.collect(provider, data)
64
61
  end
65
62
 
66
- explanation = COLLECTOR.explain_all
63
+ COLLECTOR.explain_all(format: :table).each do |type, explanation|
64
+ puts type
65
+ puts explanation
66
+ end
67
67
  ```
68
68
 
69
69
  Explanation will be:
70
70
 
71
- ```ruby
72
- {
73
- github: [
74
- "jekyll",
75
- "jekyll-sass-converter",
76
- "kramdown",
77
- "jekyll-commonmark-ghpages",
78
- "liquid",
79
- "rouge",
80
- "github-pages-health-check",
81
- "jekyll-redirect-from",
82
- "jekyll-sitemap",
83
- "jekyll-feed",
84
- "jekyll-gist",
85
- "jekyll-paginate",
86
- "jekyll-coffeescript",
87
- "jekyll-seo-tag",
88
- "jekyll-github-metadata",
89
- "jekyll-avatar",
90
- "jekyll-remote-theme",
91
- "jemoji",
92
- "jekyll-mentions",
93
- "jekyll-relative-links",
94
- "jekyll-optional-front-matter",
95
- "jekyll-readme-index",
96
- "jekyll-default-layout",
97
- "jekyll-titles-from-headings",
98
- "jekyll-swiss",
99
- "minima",
100
- "jekyll-theme-primer",
101
- "jekyll-theme-architect",
102
- "jekyll-theme-cayman",
103
- "jekyll-theme-dinky",
104
- "jekyll-theme-hacker",
105
- "jekyll-theme-leap-day",
106
- "jekyll-theme-merlot",
107
- "jekyll-theme-midnight",
108
- "jekyll-theme-minimal",
109
- "jekyll-theme-modernist",
110
- "jekyll-theme-slate",
111
- "jekyll-theme-tactile",
112
- "jekyll-theme-time-machine",
113
- "ruby",
114
- "github-pages",
115
- "html-pipeline",
116
- "sass",
117
- "safe_yaml",
118
- "nokogiri",
119
- ],
120
- github_repo: [
121
- "name",
122
- "path",
123
- "sha",
124
- "size",
125
- "url",
126
- "html_url",
127
- "git_url",
128
- "download_url",
129
- "type",
130
- "_links.self",
131
- "_links.git",
132
- "_links.html"
133
- ]
134
- }
71
+ ```
72
+ github
73
+ +------------------------------+--------------------------------------------------------------------------+
74
+ | jekyll | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
75
+ | jekyll-sass-converter | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
76
+ | kramdown | Possible types: [string], NULL, Min/max Length: 6/6 |
77
+ | jekyll-commonmark-ghpages | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
78
+ | liquid | Possible types: [string], NULL, Min/max Length: 5/5 |
79
+ | rouge | Possible types: [string], NULL, Min/max Length: 6/6 |
80
+ | github-pages-health-check | Possible types: [string], NULL, Min/max Length: 6/6 |
81
+ | jekyll-redirect-from | Possible types: [string], NULL, Min/max Length: 6/6 |
82
+ | jekyll-sitemap | Possible types: [string], NULL, Min/max Length: 5/5 |
83
+ | jekyll-feed | Possible types: [string], NULL, Min/max Length: 6/6 |
84
+ | jekyll-gist | Possible types: [string], NULL, Min/max Length: 5/5 |
85
+ | jekyll-paginate | Possible types: [string], NULL, Min/max Length: 5/5 |
86
+ | jekyll-coffeescript | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
87
+ | jekyll-seo-tag | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
88
+ | jekyll-github-metadata | Possible types: [string], NULL, Min/max Length: 6/6 |
89
+ | jekyll-avatar | Possible types: [string], NULL, Min/max Length: 5/5 |
90
+ | jekyll-remote-theme | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
91
+ | jemoji | Possible types: [date, time, string], NULL, Min/max Length: 6/6 |
92
+ | jekyll-mentions | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
93
+ | jekyll-relative-links | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
94
+ | jekyll-optional-front-matter | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
95
+ | jekyll-readme-index | Possible types: [string], NULL, Min/max Length: 5/5 |
96
+ | jekyll-default-layout | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
97
+ | jekyll-titles-from-headings | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
98
+ | jekyll-swiss | Possible types: [string], NULL, Min/max Length: 5/5 |
99
+ | minima | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
100
+ | jekyll-theme-primer | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
101
+ | jekyll-theme-architect | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
102
+ | jekyll-theme-cayman | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
103
+ | jekyll-theme-dinky | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
104
+ | jekyll-theme-hacker | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
105
+ | jekyll-theme-leap-day | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
106
+ | jekyll-theme-merlot | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
107
+ | jekyll-theme-midnight | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
108
+ | jekyll-theme-minimal | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
109
+ | jekyll-theme-modernist | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
110
+ | jekyll-theme-slate | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
111
+ | jekyll-theme-tactile | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
112
+ | jekyll-theme-time-machine | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
113
+ | ruby | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
114
+ | github-pages | Possible types: [date, time, string, integer], NULL, Min/max Length: 3/3 |
115
+ | html-pipeline | Possible types: [date, time, string], NULL, Min/max Length: 6/6 |
116
+ | sass | Possible types: [date, time, string], NULL, Min/max Length: 5/5 |
117
+ | safe_yaml | Possible types: [string], NULL, Min/max Length: 5/5 |
118
+ | nokogiri | Possible types: [date, time, string], NULL, Min/max Length: 6/6 |
119
+ +------------------------------+--------------------------------------------------------------------------+
120
+ github_repo_contents
121
+ +-----------------+---------------------------------------------------------+
122
+ | [].name | Possible types: [string], NULL, Min/max Length: 2/14 |
123
+ | [].path | Possible types: [string], NULL, Min/max Length: 2/14 |
124
+ | [].sha | Possible types: [string], NULL, Min/max Length: 40/40 |
125
+ | [].size | Possible types: [integer], NULL |
126
+ | [].url | Possible types: [string], NULL, Min/max Length: 75/87 |
127
+ | [].html_url | Possible types: [string], NULL, Min/max Length: 57/69 |
128
+ | [].git_url | Possible types: [string], NULL, Min/max Length: 103/103 |
129
+ | [].download_url | Possible types: [string], NULL, Min/max Length: 72/79 |
130
+ | [].type | Possible types: [string], NULL, Min/max Length: 3/4 |
131
+ | []._links.self | Possible types: [string], NULL, Min/max Length: 75/87 |
132
+ | []._links.git | Possible types: [string], NULL, Min/max Length: 103/103 |
133
+ | []._links.html | Possible types: [string], NULL, Min/max Length: 57/69 |
134
+ +-----------------+---------------------------------------------------------+
135
135
  ```
136
136
 
137
137
  Or if you try like this
@@ -155,7 +155,7 @@ data = {
155
155
  }
156
156
 
157
157
  DatasetExplorer::Collector.instance.collect(:achievements, data)
158
- result = DatasetExplorer::Collector.explain_all(:achievements)
158
+ result = DatasetExplorer::Collector.instance.explain(:achievements).keys
159
159
 
160
160
  # result is:
161
161
 
@@ -28,4 +28,6 @@ Gem::Specification.new do |spec|
28
28
  spec.bindir = 'exe'
29
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
30
  spec.require_paths = ['lib']
31
+
32
+ spec.add_dependency 'terminal-table'
31
33
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'dataset_explorer/version'
4
+ require 'dataset_explorer/value_evaluator'
4
5
  require 'dataset_explorer/item_collector'
5
6
  require 'dataset_explorer/collector'
6
7
 
@@ -14,14 +14,20 @@ module DatasetExplorer
14
14
  collector_for(type).add(item)
15
15
  end
16
16
 
17
- def explain_all
17
+ def explain_all(format: :hash)
18
18
  @collectors.keys.map do |key|
19
- [key, explain(key)]
19
+ [key, explain(key, format: format)]
20
20
  end.to_h
21
21
  end
22
22
 
23
- def explain(type)
24
- @collectors.fetch(type).values
23
+ def explain(type, format: :hash)
24
+ explanation = @collectors.fetch(type).explain
25
+
26
+ if format == :table
27
+ explanation = to_table(explanation)
28
+ end
29
+
30
+ explanation
25
31
  end
26
32
 
27
33
  private
@@ -30,6 +36,14 @@ module DatasetExplorer
30
36
  @collectors[type] ||= ItemCollector.new
31
37
  end
32
38
 
39
+ def to_table(fields)
40
+ rows = []
41
+ fields.each do |key, description|
42
+ rows << [key, description]
43
+ end
44
+ Terminal::Table.new(rows: rows)
45
+ end
46
+
33
47
  private_class_method :new
34
48
  end
35
49
  end
@@ -3,10 +3,19 @@
3
3
  module DatasetExplorer
4
4
  class ItemCollector
5
5
  def initialize
6
- @values = []
6
+ @keys = []
7
+ @evaluators = {}
7
8
  end
8
9
 
9
- attr_reader :values
10
+ def explain
11
+ {}.tap do |explanation|
12
+ @evaluators.each do |field, evaluator|
13
+ explanation[field] = evaluator.describe
14
+ end
15
+ end
16
+ end
17
+
18
+ attr_reader :keys
10
19
 
11
20
  def add(item)
12
21
  unless item.is_a?(Array)
@@ -25,15 +34,17 @@ module DatasetExplorer
25
34
  map_keys(item[key], key, prefix)
26
35
  end.flatten.map(&:to_s).uniq
27
36
 
28
- @values << new_values
29
- @values = @values.flatten.uniq
37
+ @keys << new_values
38
+ @keys = @keys.flatten.uniq
30
39
  end
31
40
 
32
41
  # rubocop:disable Metrics/MethodLength
42
+ # rubocop:disable Metrics/AbcSize
33
43
  def map_keys(value, key = nil, prefix = nil)
34
44
  prefix = [prefix, key].compact.join('.')
35
45
 
36
46
  unless mappable?(value)
47
+ evaluator_for(prefix).evaluate(value)
37
48
  return prefix
38
49
  end
39
50
 
@@ -45,9 +56,9 @@ module DatasetExplorer
45
56
 
46
57
  if value.respond_to?(:each)
47
58
  prefix = "#{prefix}.[]"
48
- return [].tap do |values|
59
+ return [].tap do |keys|
49
60
  value.each do |item_value|
50
- values << map_keys(item_value, nil, prefix)
61
+ keys << map_keys(item_value, nil, prefix)
51
62
  end
52
63
  end
53
64
  end
@@ -55,6 +66,7 @@ module DatasetExplorer
55
66
  raise Error, 'Unforseen scenario'
56
67
  end
57
68
  # rubocop:enable Metrics/MethodLength
69
+ # rubocop:enable Metrics/AbcSize
58
70
 
59
71
  def mappable?(value)
60
72
  if behaves_like_hash?(value)
@@ -75,5 +87,9 @@ module DatasetExplorer
75
87
  def behaves_like_array?(value)
76
88
  value.respond_to?(:each)
77
89
  end
90
+
91
+ def evaluator_for(field)
92
+ @evaluators[field.to_s] ||= ValueEvaluator.new(field)
93
+ end
78
94
  end
79
95
  end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require 'time'
5
+ require 'terminal-table'
6
+
7
+ module DatasetExplorer
8
+ class ValueEvaluator
9
+ attr_reader :min_length
10
+ attr_reader :max_length
11
+
12
+ def initialize(field_name)
13
+ @field_name = field_name
14
+ @null = true
15
+ @evaluators = {
16
+ 'date' => DateEvaluator.new,
17
+ 'time' => TimeEvaluator.new,
18
+ 'string' => StringEvaluator.new,
19
+ 'float' => FloatEvaluator.new,
20
+ 'integer' => IntegerEvaluator.new,
21
+ 'boolean' => BooleanEvaluator.new
22
+ }
23
+ @min_length = nil
24
+ @max_length = nil
25
+ end
26
+
27
+ def evaluate(value)
28
+ if value.nil?
29
+ @null = true
30
+ return
31
+ end
32
+
33
+ evaluate_length(value)
34
+
35
+ @evaluators.each do |key, evaluator|
36
+ unless evaluator.accept?(value)
37
+ @evaluators.delete(key)
38
+ end
39
+ end
40
+ end
41
+
42
+ def types
43
+ @evaluators.keys
44
+ end
45
+
46
+ def describe
47
+ parts = ["Possible types: [#{types.join(', ')}]"]
48
+ if @null
49
+ parts << 'NULL'
50
+ end
51
+
52
+ if min_length
53
+ parts << "Min/max Length: #{min_length}/#{max_length}"
54
+ end
55
+
56
+ parts.join(', ')
57
+ end
58
+
59
+ def evaluate_length(value)
60
+ unless value.respond_to?(:length)
61
+ return
62
+ end
63
+
64
+ length = value.length
65
+ @min_length ||= length
66
+ @max_length ||= length
67
+
68
+ if @min_length > length
69
+ @min_length = length
70
+ end
71
+
72
+ if @max_length < length
73
+ @max_length = length
74
+ end
75
+ end
76
+
77
+ class TimeEvaluator
78
+ def accept?(value)
79
+ if value.is_a?(String)
80
+ return Time.parse(value.to_s)
81
+ end
82
+
83
+ value.is_a?(Time)
84
+ rescue ArgumentError
85
+ false
86
+ end
87
+ end
88
+
89
+ class DateEvaluator
90
+ def accept?(value)
91
+ if value.is_a?(String)
92
+ return Date.parse(value.to_s)
93
+ end
94
+
95
+ value.is_a?(Date)
96
+ rescue ArgumentError
97
+ false
98
+ end
99
+ end
100
+
101
+ class StringEvaluator
102
+ def accept?(value)
103
+ value.is_a?(String)
104
+ end
105
+ end
106
+
107
+ class FloatEvaluator
108
+ def accept?(value)
109
+ Float(value).to_s == value.to_s
110
+ rescue ArgumentError, TypeError
111
+ false
112
+ end
113
+ end
114
+
115
+ class IntegerEvaluator
116
+ def accept?(value)
117
+ Integer(value)
118
+ rescue ArgumentError, TypeError
119
+ false
120
+ end
121
+ end
122
+
123
+ class BooleanEvaluator
124
+ ACCEPT = %w[
125
+ true
126
+ false
127
+ ].freeze
128
+
129
+ def accept?(value)
130
+ ACCEPT.include?(value.to_s.downcase)
131
+ end
132
+ end
133
+ end
134
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatasetExplorer
4
- VERSION = '0.1.1'
4
+ VERSION = '1.0.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dataset_explorer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcelo Jacobus
@@ -9,7 +9,21 @@ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
11
  date: 2020-05-25 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: terminal-table
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  description: Explore and maps fields from a dataset - I.E. Api response
14
28
  email:
15
29
  - marcelo.jacobus@gmail.com
@@ -32,6 +46,7 @@ files:
32
46
  - lib/dataset_explorer.rb
33
47
  - lib/dataset_explorer/collector.rb
34
48
  - lib/dataset_explorer/item_collector.rb
49
+ - lib/dataset_explorer/value_evaluator.rb
35
50
  - lib/dataset_explorer/version.rb
36
51
  homepage: https://github.com/mjacobus/dataset_explorer
37
52
  licenses: