goldmine 0.9.2 → 1.0.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 657692c39740a0cf3b3c14851f886387616aa417
4
+ data.tar.gz: 8a611460c2a55d95d8e2d406dca9b1e72ab50682
5
+ SHA512:
6
+ metadata.gz: c4821192a956bedf128bf1f9013712f12d11ff1b69e7b7decd14655998243bdc449775ae2ec0485f49f39cf7c1701134f46430c8b1e1ddc80e0f89848e6fff51
7
+ data.tar.gz: 987848b18ed99c765401567937b8ffcc80411248f1e07ccb1d649a8c5a2ccce41b0139168c4f9133a1553475dee1b69b2c434f01e2b7c7c2936dc4b8995afd50
@@ -1,30 +1,34 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- goldmine (0.9.2)
4
+ goldmine (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- ansi (1.4.3)
10
9
  coderay (1.0.9)
11
- method_source (0.8.1)
12
- minitest (4.7.2)
13
- pry (0.9.12)
10
+ method_source (0.8.2)
11
+ micro_test (0.4.0)
12
+ os
13
+ multi_json (1.8.2)
14
+ os (0.9.6)
15
+ pry (0.9.12.2)
14
16
  coderay (~> 1.0.5)
15
17
  method_source (~> 0.8)
16
18
  slop (~> 3.4)
17
- rake (10.0.4)
18
- slop (3.4.4)
19
- turn (0.9.6)
20
- ansi
19
+ rake (10.1.0)
20
+ simplecov (0.7.1)
21
+ multi_json (~> 1.0)
22
+ simplecov-html (~> 0.7.1)
23
+ simplecov-html (0.7.1)
24
+ slop (3.4.6)
21
25
 
22
26
  PLATFORMS
23
27
  ruby
24
28
 
25
29
  DEPENDENCIES
26
30
  goldmine!
27
- minitest
31
+ micro_test
28
32
  pry
29
33
  rake
30
- turn
34
+ simplecov
data/README.md CHANGED
@@ -4,113 +4,46 @@
4
4
  [![Dependency Status](https://gemnasium.com/hopsoft/goldmine.png)](https://gemnasium.com/hopsoft/goldmine)
5
5
  [![Code Climate](https://codeclimate.com/github/hopsoft/goldmine.png)](https://codeclimate.com/github/hopsoft/goldmine)
6
6
 
7
- ## Pivot tables for the Rubyist
7
+ ### Extract a wealth of information from Arrays & Hashes
8
8
 
9
- ![Goldmine GEM](http://hopsoft.github.com/goldmine/images/gold.jpg)
9
+ Think of it as an enhanced `Enumerable#group_by`.
10
10
 
11
- ### Pivot any list into a wealth of information
11
+ ## Uses
12
12
 
13
- Goldmine allows you to apply pivot table logic to any list for powerful data mining capabilities.
13
+ - Data mining
14
+ - Data transformation
15
+ - CSV report generation
16
+ - Prep for data visualization
17
+ - Fact table creation
14
18
 
15
- ### Reasons to love it
19
+ The [demo project](http://hopsoft.github.io/goldmine/) demonstrates some of Goldmine's uses.
16
20
 
17
- * Provides ETL like functionality... but simple and elegant
18
- * Easily build OLAP cubes using Ruby
19
- * Supports method chaining for deep data mining
20
- * Handles values that are lists themselves
21
+ ## Quick Start
21
22
 
22
- [Why use it?](#putting-it-all-together)
23
-
24
- ## Quick start
25
-
26
- Install
27
-
28
- ```bash
29
- $gem install goldmine
30
23
  ```
31
-
32
- Use
33
-
34
- ```ruby
35
- require "goldmine"
36
- [1,2,3,4,5,6,7,8,9].pivot { |i| i < 5 }
24
+ gem install goldmine
25
+ irb
37
26
  ```
38
27
 
39
- ### Usage examples
40
-
41
- * [Pivot a list](#pivot-a-list-of-numbers-based-on-whether-or-not-they-are-less-than-5)
42
- * [Create a named pivot](#explicitly-name-a-pivot)
43
- * [Pivot values that are lists themselves](#pivot-values-that-are-lists-themselves)
44
- * [Chain pivots](#chain-pivots-together)
45
- * [Dig deep and extract meaningful data](#deep-cuts)
46
-
47
- ## The Basics
48
-
49
- ### Pivot a list of numbers based on whether or not they are less than 5
50
-
51
28
  ```ruby
52
- # operation
29
+ require "goldmine"
53
30
  list = [1,2,3,4,5,6,7,8,9]
54
- data = list.pivot { |i| i < 5 }
55
-
56
- # resulting data
31
+ list = Goldmine::ArrayMiner.new(list)
32
+ list.pivot { |i| i < 5 }
33
+ # result:
57
34
  {
58
35
  true => [1, 2, 3, 4],
59
36
  false => [5, 6, 7, 8, 9]
60
37
  }
61
38
  ```
62
39
 
63
- ### Explicitly name a pivot
64
-
65
- ```ruby
66
- # operation
67
- list = [1,2,3,4,5,6,7,8,9]
68
- data = list.pivot("less than 5") { |i| i < 5 }
69
-
70
- # resulting data
71
- {
72
- { "less than 5" => true } => [1, 2, 3, 4],
73
- { "less than 5" => false } => [5, 6, 7, 8, 9]
74
- }
75
- ```
76
-
77
- ## Next Steps
78
-
79
- ### Pivot values that are lists themselves
80
-
81
- ```ruby
82
- # operation
83
- list = [
84
- { :name => "one", :list => [1] },
85
- { :name => "two", :list => [1, 2] },
86
- { :name => "three", :list => [1, 2, 3] },
87
- { :name => "four", :list => [1, 2, 3, 4] },
88
- ]
89
- data = list.pivot { |record| record[:list] }
90
-
91
- # resulting data
92
- {
93
- 1 => [ { :name => "one", :list => [1] },
94
- { :name => "two", :list => [1, 2] },
95
- { :name => "three", :list => [1, 2, 3] },
96
- { :name => "four", :list => [1, 2, 3, 4] } ],
97
- 2 => [ { :name => "two", :list => [1, 2] },
98
- { :name => "three", :list => [1, 2, 3] },
99
- { :name => "four", :list => [1, 2, 3, 4] } ],
100
- 3 => [ { :name => "three", :list => [1, 2, 3] },
101
- { :name => "four", :list => [1, 2, 3, 4] } ],
102
- 4 => [ { :name => "four", :list => [1, 2, 3, 4] } ]
103
- }
104
- ```
105
-
106
- ### Chain pivots together
40
+ ## Chained Pivots
107
41
 
108
42
  ```ruby
109
- # operation
110
43
  list = [1,2,3,4,5,6,7,8,9]
111
- data = list.pivot { |i| i < 5 }.pivot { |i| i % 2 == 0 }
112
-
113
- # resulting data
44
+ list = Goldmine::ArrayMiner.new(list)
45
+ list.pivot { |i| i < 5 }.pivot { |i| i % 2 == 0 }
46
+ # result:
114
47
  {
115
48
  [true, false] => [1, 3],
116
49
  [true, true] => [2, 4],
@@ -119,261 +52,87 @@ data = list.pivot { |i| i < 5 }.pivot { |i| i % 2 == 0 }
119
52
  }
120
53
  ```
121
54
 
122
- ## Deep Cuts
123
-
124
- ### Build a moderately complex dataset of Cities
55
+ ## Named Pivots
125
56
 
126
57
  ```ruby
127
- cities = [
128
- { :name => "San Francisco",
129
- :state => "CA",
130
- :population => 805235,
131
- :airlines => [ "Delta", "United", "SouthWest" ]
132
- },
133
- {
134
- :name => "Mountain View",
135
- :state => "CA",
136
- :population => 74066,
137
- :airlines => [ "SkyWest", "United", "SouthWest" ]
138
- },
139
- {
140
- :name => "Manhattan",
141
- :state => "NY",
142
- :population => 1586698,
143
- :airlines => [ "Delta", "JetBlue", "United" ]
144
- },
145
- {
146
- :name => "Brooklyn",
147
- :state => "NY",
148
- :population => 2504700,
149
- :airlines => [ "Delta", "American", "US Airways" ]
150
- },
151
- {
152
- :name => "Boston",
153
- :state => "MA",
154
- :population => 617594,
155
- :airlines => [ "Delta", "JetBlue", "American" ]
156
- },
157
- {
158
- :name => "Atlanta",
159
- :state => "GA",
160
- :population => 420003,
161
- :airlines => [ "Delta", "United", "SouthWest" ]
162
- },
163
- {
164
- :name => "Dallas",
165
- :state => "TX",
166
- :population => 1197816,
167
- :airlines => [ "Delta", "SouthWest", "Frontier" ]
168
- }
169
- ]
58
+ list = [1,2,3,4,5,6,7,8,9]
59
+ list = Goldmine::ArrayMiner.new(list)
60
+ list.pivot(:less_than_5) { |i| i < 5 }
61
+ # result:
62
+ {
63
+ { :less_than_5 => true } => [1, 2, 3, 4],
64
+ { :less_than_5 => false } => [5, 6, 7, 8, 9]
65
+ }
170
66
  ```
171
67
 
172
- ### Pivot cities by state for population over 750k
68
+ ## Value Pivots
173
69
 
174
70
  ```ruby
175
- # operation
176
- data = cities
177
- .pivot("state") { |city| city[:state] }
178
- .pivot("population >= 750k") { |city| city[:population] >= 750000 }
179
-
180
- # resulting data
71
+ list = [
72
+ { :name => "Sally", :favorite_colors => [:blue] },
73
+ { :name => "John", :favorite_colors => [:blue, :green] },
74
+ { :name => "Stephen", :favorite_colors => [:red, :pink, :purple] },
75
+ { :name => "Emily", :favorite_colors => [:orange, :green] },
76
+ { :name => "Joe", :favorite_colors => [:red] }
77
+ ]
78
+ list = Goldmine::ArrayMiner.new(list)
79
+ list.pivot { |record| record[:favorite_colors] }
80
+ # result:
181
81
  {
182
- { "state" => "CA", "population >= 750k" => true } => [ { :name => "San Francisco", ... } ],
183
- { "state" => "CA", "population >= 750k" => false } => [ { :name => "Mountain View", ... } ],
184
- { "state" => "NY", "population >= 750k" => true } => [ { :name => "Manhattan", ... }, { :name => "Brooklyn", ... } ],
185
- { "state" => "MA", "population >= 750k" => false } => [ { :name => "Boston", ... } ],
186
- { "state" => "GA", "population >= 750k" => false } => [ { :name => "Atlanta", ... } ],
187
- { "state" => "TX", "population >= 750k" => true } => [ { :name => "Dallas", ... } ]
82
+ :blue => [
83
+ { :name => "Sally", :favorite_colors => [:blue] },
84
+ { :name => "John", :favorite_colors => [:blue, :green] }
85
+ ],
86
+ :green => [
87
+ { :name => "John", :favorite_colors => [:blue, :green] },
88
+ { :name => "Emily", :favorite_colors => [:orange, :green] }
89
+ ],
90
+ :red => [
91
+ { :name => "Stephen", :favorite_colors => [:red, :pink, :purple] },
92
+ { :name => "Joe", :favorite_colors => [:red] }
93
+ ],
94
+ :pink => [
95
+ { :name => "Stephen", :favorite_colors => [:red, :pink, :purple] }
96
+ ],
97
+ :purple => [
98
+ { :name => "Stephen", :favorite_colors => [:red, :pink, :purple] }
99
+ ],
100
+ :orange => [
101
+ { :name => "Emily", :favorite_colors => [:orange, :green] }
102
+ ]
188
103
  }
189
104
  ```
190
105
 
191
- ### Putting it all together
192
-
193
- **The end goal of all this is to support the creation of aggregate reports.**
194
-
195
- *You can think of these reports as individual data cubes.*
196
-
197
- Here is a table view of the pivoted city data from above.
198
-
199
- <table class="table table-bordered table-striped">
200
- <thead>
201
- <tr>
202
- <th>state</th>
203
- <th>population >= 750k</th>
204
- <th>cities</th>
205
- </tr>
206
- </thead>
207
- <tbody>
208
- <tr>
209
- <td>CA</td>
210
- <td>true</td>
211
- <td>1</td>
212
- </tr>
213
- <tr>
214
- <td>CA</td>
215
- <td>false</td>
216
- <td>1</td>
217
- </tr>
218
- <tr>
219
- <td>NY</td>
220
- <td>true</td>
221
- <td>2</td>
222
- </tr>
223
- <tr>
224
- <td>MA</td>
225
- <td>false</td>
226
- <td>1</td>
227
- </tr>
228
- <tr>
229
- <td>GA</td>
230
- <td>false</td>
231
- <td>1</td>
232
- </tr>
233
- <tr>
234
- <td>TX</td>
235
- <td>true</td>
236
- <td>1</td>
237
- </tr>
238
- </tbody>
239
- </table>
240
-
241
- Lets try another one.
242
-
243
- ### Determine which airlines service cities with fewer than 750k people
106
+ # Stacked pivots
244
107
 
245
108
  ```ruby
246
- # operation
247
- data = cities
248
- .pivot("airline") { |city| city[:airlines] }
249
- .pivot("population < 750k") { |city| city[:population] < 750000 }
250
-
251
- # resulting data
109
+ list = [
110
+ { :name => "Sally", :age => 21 },
111
+ { :name => "John", :age => 28 },
112
+ { :name => "Stephen", :age => 37 },
113
+ { :name => "Emily", :age => 32 },
114
+ { :name => "Joe", :age => 18 }
115
+ ]
116
+ list = Goldmine::ArrayMiner.new(list)
117
+ mined = list.pivot("Name has an 'e'") do |record|
118
+ !!record[:name].match(/e/i)
119
+ end
120
+ mined = mined.pivot(">= 21 years old") do |record|
121
+ record[:age] >= 21
122
+ end
123
+ # result:
252
124
  {
253
- { "airline" => "Delta", "population < 750k" => false } => [
254
- { :name => "San Francisco", ... },
255
- { :name => "Manhattan", ... },
256
- { :name => "Brooklyn", ... },
257
- { :name => "Dallas", ... }],
258
- { "airline" => "Delta", "population < 750k" => true } => [
259
- { :name => "Boston", ... },
260
- { :name => "Atlanta", ... }],
261
- { "airline" => "United", "population < 750k" => false } => [
262
- { :name => "San Francisco", ... },
263
- { :name => "Manhattan", ... }],
264
- { "airline" => "United", "population < 750k" => true } => [
265
- { :name => "Mountain View", ... },
266
- { :name => "Atlanta", ... }],
267
- { "airline" => "SouthWest", "population < 750k" => false } => [
268
- { :name => "San Francisco", ... },
269
- { :name => "Dallas", ... }],
270
- { "airline" => "SouthWest", "population < 750k" => true } => [
271
- { :name => "Mountain View", ... },
272
- { :name => "Atlanta", ... }],
273
- { "airline" => "SkyWest", "population < 750k" => true } => [
274
- { :name => "Mountain View", ... }],
275
- { "airline" => "JetBlue", "population < 750k" => false } => [
276
- { :name => "Manhattan", ... }],
277
- { "airline" => "JetBlue", "population < 750k" => true } => [
278
- { :name => "Boston", ... }],
279
- { "airline" => "American", "population < 750k" => false } => [
280
- { :name => "Brooklyn", ... }],
281
- { "airline" => "American", "population < 750k" => true } => [
282
- { :name => "Boston", ... }],
283
- { "airline" => "US Airways", "population < 750k" => false } => [
284
- { :name => "Brooklyn", ... }],
285
- { "airline" => "Frontier", "population < 750k" => false } => [
286
- { :name => "Dallas", ... }]
125
+ { "Name has an 'e'" => false, ">= 21 years old" => true } => [
126
+ { :name => "Sally", :age => 21 },
127
+ { :name => "John", :age => 28 }
128
+ ],
129
+ { "Name has an 'e'" => true, ">= 21 years old" => true } => [
130
+ { :name => "Stephen", :age => 37 },
131
+ { :name => "Emily", :age => 32 }
132
+ ],
133
+ { "Name has an 'e'" => true, ">= 21 years old" => false } => [
134
+ { :name => "Joe", :age => 18 }
135
+ ]
287
136
  }
288
137
  ```
289
138
 
290
- Here is the corresponding table view for the above dataset.
291
-
292
- <table class="table table-bordered table-striped">
293
- <thead>
294
- <tr>
295
- <th>airline</th>
296
- <th>population &lt; 750k</th>
297
- <th>cities</th>
298
- </tr>
299
- </thead>
300
- <tbody>
301
- <tr>
302
- <td>Delta</td>
303
- <td>false</td>
304
- <td>4</td>
305
- </tr>
306
- <tr>
307
- <td>Delta</td>
308
- <td>true</td>
309
- <td>2</td>
310
- </tr>
311
- <tr>
312
- <td>United</td>
313
- <td>false</td>
314
- <td>2</td>
315
- </tr>
316
- <tr>
317
- <td>United</td>
318
- <td>true</td>
319
- <td>2</td>
320
- </tr>
321
- <tr>
322
- <td>SouthWest</td>
323
- <td>false</td>
324
- <td>2</td>
325
- </tr>
326
- <tr>
327
- <td>SouthWest</td>
328
- <td>true</td>
329
- <td>2</td>
330
- </tr>
331
- <tr>
332
- <td>SkyWest</td>
333
- <td>true</td>
334
- <td>1</td>
335
- </tr>
336
- <tr>
337
- <td>JetBlue</td>
338
- <td>false</td>
339
- <td>1</td>
340
- </tr>
341
- <tr>
342
- <td>JetBlue</td>
343
- <td>true</td>
344
- <td>1</td>
345
- </tr>
346
- <tr>
347
- <td>American</td>
348
- <td>false</td>
349
- <td>1</td>
350
- </tr>
351
- <tr>
352
- <td>American</td>
353
- <td>true</td>
354
- <td>1</td>
355
- </tr>
356
- <tr>
357
- <td>US Airways</td>
358
- <td>false</td>
359
- <td>1</td>
360
- </tr>
361
- <tr>
362
- <td>Frontier</td>
363
- <td>false</td>
364
- <td>1</td>
365
- </tr>
366
- </tbody>
367
- </table>
368
-
369
- Hopefully you can see the potential even though the above examples are somewhat contrived.
370
-
371
- ## Special thanks
372
-
373
- * [One on One Marketing](http://www.1on1.com/) - for sponsoring the development of Goldmine
374
- * [Eric Berry](https://github.com/cavneb/) - for constructive feedback
375
- * [Spencer Roan](https://github.com/spencerroan) - for constructive feedback
376
- * [Brian Johnson](https://github.com/whap/) - for bringing some sanity to the recursion
377
- * [Josh Bowles](https://github.com/jbowles/) - for early adoption and feedback
378
- * [Brett Beers](https://github.com/beersbr/) - for early adoption and feedback
379
-
data/Rakefile CHANGED
@@ -1,10 +1,7 @@
1
- require "rake"
2
- require "rake/testtask"
3
1
  require "bundler/gem_tasks"
4
2
 
5
3
  task :default => [:test]
6
4
 
7
- Rake::TestTask.new(:test) do |t|
8
- t.test_files = Dir["test/test_*.rb"]
5
+ task :test do
6
+ exec "bundle exec mt"
9
7
  end
10
-
@@ -2,5 +2,10 @@ $:.unshift File.join(File.dirname(__FILE__), "goldmine")
2
2
  require "array_miner"
3
3
  require "hash_miner"
4
4
 
5
- ::Array.send(:include, Goldmine::ArrayMiner)
6
- ::Hash.send(:include, Goldmine::HashMiner)
5
+ module Goldmine
6
+ def self.miner(object)
7
+ return ArrayMiner.new(object) if object.is_a?(Array)
8
+ return HashMiner.new(object) if object.is_a?(Hash)
9
+ nil
10
+ end
11
+ end
@@ -1,7 +1,11 @@
1
+ require "delegate"
2
+
1
3
  module Goldmine
4
+ class ArrayMiner < SimpleDelegator
2
5
 
3
- # Extends Array with a pivot method.
4
- module ArrayMiner
6
+ def initialize(array=[])
7
+ super array
8
+ end
5
9
 
6
10
  # Pivots the Array into a Hash of mined data.
7
11
  # Think of it as creating a pivot table or perhaps an OLAP cube.
@@ -42,7 +46,7 @@ module Goldmine
42
46
  # @yield [Object] Yields once for each item in the Array
43
47
  # @return [Hash] The pivoted Hash of data.
44
48
  def pivot(name=nil, &block)
45
- reduce({}) do |memo, item|
49
+ reduce(HashMiner.new) do |memo, item|
46
50
  value = yield(item)
47
51
 
48
52
  if value.is_a?(Array)
@@ -1,7 +1,12 @@
1
+ require "delegate"
2
+ require "hash_miner"
3
+
1
4
  module Goldmine
5
+ class HashMiner < SimpleDelegator
2
6
 
3
- # Extends Hash with a pivot method.
4
- module HashMiner
7
+ def initialize(hash={})
8
+ super hash
9
+ end
5
10
 
6
11
  attr_accessor :goldmine
7
12
 
@@ -28,9 +33,9 @@ module Goldmine
28
33
  def pivot(name=nil, &block)
29
34
  return self unless goldmine
30
35
 
31
- reduce({}) do |memo, item|
36
+ reduce(HashMiner.new) do |memo, item|
32
37
  key = item.first
33
- value = item.last
38
+ value = Goldmine.miner(item.last)
34
39
  value.pivot(name, &block).each do |k, v|
35
40
  if key.is_a? Hash
36
41
  k = { block.to_s => k } unless k.is_a?(Hash)
@@ -1,3 +1,3 @@
1
1
  module Goldmine
2
- VERSION = "0.9.2"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,13 +1,26 @@
1
+ require "micro_test"
1
2
  require "simplecov"
3
+ SimpleCov.command_name "MicroTest"
2
4
  SimpleCov.start
3
- require "test/unit"
4
- require "turn"
5
- require File.join(File.dirname(__FILE__), "..", "lib", "goldmine")
5
+ require File.expand_path("../../lib/goldmine", __FILE__)
6
6
 
7
- class TestGoldmine < MiniTest::Unit::TestCase
7
+ class TestGoldmine < MicroTest::Test
8
8
 
9
- def test_simple_pivot
9
+ test "miner from array" do
10
+ assert Goldmine.miner([]).is_a?(Goldmine::ArrayMiner)
11
+ end
12
+
13
+ test "miner from hash" do
14
+ assert Goldmine.miner({}).is_a?(Goldmine::HashMiner)
15
+ end
16
+
17
+ test "miner from usupported object" do
18
+ assert Goldmine.miner(Object.new).nil?
19
+ end
20
+
21
+ test "simple pivot" do
10
22
  list = [1,2,3,4,5,6,7,8,9]
23
+ list = Goldmine::ArrayMiner.new(list)
11
24
  data = list.pivot { |i| i < 5 }
12
25
 
13
26
  expected = {
@@ -15,11 +28,12 @@ class TestGoldmine < MiniTest::Unit::TestCase
15
28
  false => [5, 6, 7, 8, 9]
16
29
  }
17
30
 
18
- assert_equal expected, data
31
+ assert data == expected
19
32
  end
20
33
 
21
- def test_named_pivot
34
+ test "named pivot" do
22
35
  list = [1,2,3,4,5,6,7,8,9]
36
+ list = Goldmine::ArrayMiner.new(list)
23
37
  data = list.pivot("less than 5") { |i| i < 5 }
24
38
 
25
39
  expected = {
@@ -27,16 +41,17 @@ class TestGoldmine < MiniTest::Unit::TestCase
27
41
  { "less than 5" => false } => [5, 6, 7, 8, 9]
28
42
  }
29
43
 
30
- assert_equal expected, data
44
+ assert data == expected
31
45
  end
32
46
 
33
- def test_pivot_of_list_values
47
+ test "pivot of list values" do
34
48
  list = [
35
49
  { :name => "one", :list => [1] },
36
50
  { :name => "two", :list => [1, 2] },
37
51
  { :name => "three", :list => [1, 2, 3] },
38
52
  { :name => "four", :list => [1, 2, 3, 4] },
39
53
  ]
54
+ list = Goldmine::ArrayMiner.new(list)
40
55
  data = list.pivot { |record| record[:list] }
41
56
 
42
57
  expected = {
@@ -52,11 +67,40 @@ class TestGoldmine < MiniTest::Unit::TestCase
52
67
  4 => [ { :name => "four", :list => [1, 2, 3, 4] } ]
53
68
  }
54
69
 
55
- assert_equal expected, data
70
+ assert data == expected
56
71
  end
57
72
 
58
- def test_chained_pivots
73
+ test "pivot of list values with empty list" do
74
+ list = [
75
+ { :name => "empty", :list => [] },
76
+ { :name => "one", :list => [1] },
77
+ { :name => "two", :list => [1, 2] },
78
+ { :name => "three", :list => [1, 2, 3] },
79
+ { :name => "four", :list => [1, 2, 3, 4] },
80
+ ]
81
+ list = Goldmine::ArrayMiner.new(list)
82
+ data = list.pivot { |record| record[:list] }
83
+
84
+ expected = {
85
+ nil => [ {:name => "empty", :list => [] } ],
86
+ 1 => [ { :name => "one", :list => [1] },
87
+ { :name => "two", :list => [1, 2] },
88
+ { :name => "three", :list => [1, 2, 3] },
89
+ { :name => "four", :list => [1, 2, 3, 4] } ],
90
+ 2 => [ { :name => "two", :list => [1, 2] },
91
+ { :name => "three", :list => [1, 2, 3] },
92
+ { :name => "four", :list => [1, 2, 3, 4] } ],
93
+ 3 => [ { :name => "three", :list => [1, 2, 3] },
94
+ { :name => "four", :list => [1, 2, 3, 4] } ],
95
+ 4 => [ { :name => "four", :list => [1, 2, 3, 4] } ]
96
+ }
97
+
98
+ assert data == expected
99
+ end
100
+
101
+ test "chained pivots" do
59
102
  list = [1,2,3,4,5,6,7,8,9]
103
+ list = Goldmine::ArrayMiner.new(list)
60
104
  data = list.pivot { |i| i < 5 }.pivot { |i| i % 2 == 0 }
61
105
 
62
106
  expected = {
@@ -66,12 +110,12 @@ class TestGoldmine < MiniTest::Unit::TestCase
66
110
  [false, true] => [6, 8]
67
111
  }
68
112
 
69
- assert_equal expected, data
113
+ assert data == expected
70
114
  end
71
115
 
72
- def test_deep_chained_pivots
116
+ test "deep chained pivots" do
73
117
  list = [1,2,3,4,5,6,7,8,9]
74
- # list = [2,5,9]
118
+ list = Goldmine::ArrayMiner.new(list)
75
119
  data = list
76
120
  .pivot { |i| i < 3 }
77
121
  .pivot { |i| i < 6 }
@@ -91,11 +135,12 @@ class TestGoldmine < MiniTest::Unit::TestCase
91
135
  [false, false, false, false, true] => [9]
92
136
  }
93
137
 
94
- assert_equal expected, data
138
+ assert data == expected
95
139
  end
96
140
 
97
- def test_named_deep_chained_pivots
141
+ test "named deep chained pivots" do
98
142
  list = [1,2,3,4,5,6,7,8,9]
143
+ list = Goldmine::ArrayMiner.new(list)
99
144
  data = list.pivot("a") { |i| i < 3 }.pivot("b") { |i| i < 6 }.pivot("c") { |i| i < 9 }.pivot("d") { |i| i % 2 == 0 }.pivot("e") { |i| i % 3 == 0 }
100
145
 
101
146
  expected = {
@@ -110,11 +155,12 @@ class TestGoldmine < MiniTest::Unit::TestCase
110
155
  {"a"=>false, "b"=>false, "c"=>false, "d"=>false, "e"=>true} => [9]
111
156
  }
112
157
 
113
- assert_equal expected, data
158
+ assert data == expected
114
159
  end
115
160
 
116
- def test_named_chained_pivots
161
+ test "named chained pivots" do
117
162
  list = [1,2,3,4,5,6,7,8,9]
163
+ list = Goldmine::ArrayMiner.new(list)
118
164
  data = list.pivot("less than 5") { |i| i < 5 }.pivot("divisible by 2") { |i| i % 2 == 0 }
119
165
 
120
166
  expected = {
@@ -124,9 +170,7 @@ class TestGoldmine < MiniTest::Unit::TestCase
124
170
  { "less than 5" => false, "divisible by 2" => true} => [6, 8]
125
171
  }
126
172
 
127
- assert_equal expected, data
173
+ assert data == expected
128
174
  end
129
175
 
130
-
131
-
132
176
  end
metadata CHANGED
@@ -1,97 +1,72 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: goldmine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Nathan Hopkins
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-04-19 00:00:00.000000000 Z
11
+ date: 2013-10-16 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
- name: minitest
28
+ name: micro_test
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: simplecov
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- - !ruby/object:Gem::Dependency
63
- name: turn
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
70
- type: :development
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
52
+ - - '>='
76
53
  - !ruby/object:Gem::Version
77
54
  version: '0'
78
55
  - !ruby/object:Gem::Dependency
79
56
  name: pry
80
57
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
58
  requirements:
83
- - - ! '>='
59
+ - - '>='
84
60
  - !ruby/object:Gem::Version
85
61
  version: '0'
86
62
  type: :development
87
63
  prerelease: false
88
64
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
65
  requirements:
91
- - - ! '>='
66
+ - - '>='
92
67
  - !ruby/object:Gem::Version
93
68
  version: '0'
94
- description: Pivot tables for the Rubyist.
69
+ description: Extract a wealth of information from Arrays & Hashes
95
70
  email:
96
71
  - natehop@gmail.com
97
72
  executables: []
@@ -110,28 +85,27 @@ files:
110
85
  homepage: https://github.com/hopsoft/goldmine
111
86
  licenses:
112
87
  - MIT
88
+ metadata: {}
113
89
  post_install_message:
114
90
  rdoc_options: []
115
91
  require_paths:
116
92
  - lib
117
93
  required_ruby_version: !ruby/object:Gem::Requirement
118
- none: false
119
94
  requirements:
120
- - - ! '>='
95
+ - - '>='
121
96
  - !ruby/object:Gem::Version
122
97
  version: '0'
123
98
  required_rubygems_version: !ruby/object:Gem::Requirement
124
- none: false
125
99
  requirements:
126
- - - ! '>='
100
+ - - '>='
127
101
  - !ruby/object:Gem::Version
128
102
  version: '0'
129
103
  requirements: []
130
104
  rubyforge_project:
131
- rubygems_version: 1.8.23
105
+ rubygems_version: 2.0.3
132
106
  signing_key:
133
- specification_version: 3
134
- summary: Pivot tables for the Rubyist.
107
+ specification_version: 4
108
+ summary: Extract a wealth of information from Arrays & Hashes
135
109
  test_files:
136
110
  - test/test_goldmine.rb
137
111
  has_rdoc: