goldmine 0.0.3 → 0.0.4

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.
Files changed (3) hide show
  1. data/README.md +336 -129
  2. data/lib/goldmine.rb +8 -9
  3. metadata +2 -2
data/README.md CHANGED
@@ -1,180 +1,387 @@
1
1
  # Goldmine
2
2
 
3
- ## Data mining made easy... the Ruby way.
4
- ### Turn any list into a treasure trove.
3
+ ## Pivot tables for the Rubyist
5
4
 
6
- Goldmine allows you to apply pivot table logic to any list for powerful data mining capabilities.
5
+ ### Pivot any list into a wealth of information.
7
6
 
8
- In the nomenclature of Goldmine, we call this digging for data. So we've added a `dig` method to `Array`.
7
+ Goldmine allows you to apply pivot table logic to any list for powerful data mining capabilities.
9
8
 
10
- #### More reasons to love it
9
+ ### Reasons to love it
11
10
 
12
11
  * Provides ETL like functionality... but simple and elegant
12
+ * Easily build OLAP cubes using Ruby
13
13
  * Supports method chaining for deep data mining
14
14
  * Handles values that are lists themselves
15
- * Allows you to name your pivots
16
15
 
17
- What does this all mean for you? Lets have a look.
16
+ [Why use it?](#putting-it-all-together)
17
+
18
+ ## Quick start
19
+
20
+ Install
21
+
22
+ ```
23
+ $gem install goldmine
24
+ ```
25
+
26
+ Use
27
+
28
+ ```ruby
29
+ [1,2,3,4,5,6,7,8,9].pivot { |i| i < 5 }
30
+ ```
31
+
32
+ ### Usage examples
33
+
34
+ * [Pivot a list](#pivot-a-list-of-numbers-based-on-whether-or-not-they-are-less-than-5)
35
+ * [Create a named pivot](#explicitly-name-a-pivot)
36
+ * [Pivot values that are lists themselves](#pivot-values-that-are-lists-themselves)
37
+ * [Chain pivots](#chain-pivots-together)
38
+ * [Chain pivots conditionally](#conditionally-chain-pivots-together)
39
+ * [Dig deep and extract meaningful data](#deep-cuts)
18
40
 
19
41
  ## The Basics
20
42
 
21
- #### Pivot a simple list of numbers based on whether or not they are less than 5
43
+ ### Pivot a list of numbers based on whether or not they are less than 5
22
44
 
23
45
  ```ruby
46
+ # operation
24
47
  list = [1,2,3,4,5,6,7,8,9]
25
- data = list.dig { |i| i < 5 }
48
+ data = list.pivot { |i| i < 5 }
26
49
 
27
- # {
28
- # true => [1, 2, 3, 4],
29
- # false => [5, 6, 7, 8, 9]
30
- # }
50
+ # resulting data
51
+ {
52
+ true => [1, 2, 3, 4],
53
+ false => [5, 6, 7, 8, 9]
54
+ }
31
55
  ```
32
56
 
33
- #### The same pivot as above but explicitly named
57
+ ### Explicitly name a pivot
34
58
 
35
59
  ```ruby
60
+ # operation
36
61
  list = [1,2,3,4,5,6,7,8,9]
37
- data = list.dig("less than 5") { |i| i < 5 }
62
+ data = list.pivot("less than 5") { |i| i < 5 }
38
63
 
39
- # {
40
- # "less than 5: true" => [1, 2, 3, 4],
41
- # "less than 5: false" => [5, 6, 7, 8, 9]
42
- # }
64
+ # resulting data
65
+ {
66
+ { "less than 5" => true } => [1, 2, 3, 4],
67
+ { "less than 5" => false } => [5, 6, 7, 8, 9]
68
+ }
43
69
  ```
44
70
 
45
71
  ## Next Steps
46
72
 
47
- #### Chain pivots together
73
+ ### Pivot values that are lists themselves
48
74
 
49
75
  ```ruby
76
+ # operation
77
+ list = [
78
+ { :name => "one", :list => [1] },
79
+ { :name => "two", :list => [1, 2] },
80
+ { :name => "three", :list => [1, 2, 3] },
81
+ { :name => "four", :list => [1, 2, 3, 4] },
82
+ ]
83
+ data = list.pivot { |record| record[:list] }
84
+
85
+ # resulting data
86
+ {
87
+ 1 => [ { :name => "one", :list => [1] },
88
+ { :name => "two", :list => [1, 2] },
89
+ { :name => "three", :list => [1, 2, 3] },
90
+ { :name => "four", :list => [1, 2, 3, 4] } ],
91
+ 2 => [ { :name => "two", :list => [1, 2] },
92
+ { :name => "three", :list => [1, 2, 3] },
93
+ { :name => "four", :list => [1, 2, 3, 4] } ],
94
+ 3 => [ { :name => "three", :list => [1, 2, 3] },
95
+ { :name => "four", :list => [1, 2, 3, 4] } ],
96
+ 4 => [ { :name => "four", :list => [1, 2, 3, 4] } ]
97
+ }
98
+ ```
99
+
100
+ ### Chain pivots together
101
+
102
+ ```ruby
103
+ # operation
50
104
  list = [1,2,3,4,5,6,7,8,9]
51
- data = list.dig { |i| i < 5 }.dig { |i| i % 2 == 0 }
52
-
53
- # {
54
- # [true, false] => [1, 3],
55
- # [true, true] => [2, 4],
56
- # [false, false] => [5, 7, 9],
57
- # [false, true] => [6, 8]
58
- # }
105
+ data = list.pivot { |i| i < 5 }.pivot { |i| i % 2 == 0 }
106
+
107
+ # resulting data
108
+ {
109
+ [true, false] => [1, 3],
110
+ [true, true] => [2, 4],
111
+ [false, false] => [5, 7, 9],
112
+ [false, true] => [6, 8]
113
+ }
59
114
  ```
60
115
 
61
- #### The same pivot as above but explicitly named
116
+ ### Conditionally chain pivots together
62
117
 
63
118
  ```ruby
119
+ # operation
120
+ params = { :divisible_by_two => false, :next_greater_than_five => true }
64
121
  list = [1,2,3,4,5,6,7,8,9]
65
- data = list.dig("less than 5") { |i| i < 5 }.dig("divisible by 2") { |i| i % 2 == 0 }
66
-
67
- # {
68
- # ["less than 5: true", "divisible by 2: false"] => [1, 3],
69
- # ["less than 5: true", "divisible by 2: true"] => [2, 4],
70
- # ["less than 5: false", "divisible by 2: false"] => [5, 7, 9],
71
- # ["less than 5: false", "divisible by 2: true"] => [6, 8]
72
- # }
122
+ data = list.pivot("less than 5") { |i| i < 5 }
123
+ data = data.pivot("divisible by 2") { |i| i % 2 == 0 } if params[:divisible_by_two]
124
+ data = data.pivot("next greater than 5") { |i| i.next > 5 } if params[:next_greater_than_five]
125
+
126
+ # resulting data
127
+ {
128
+ { "less than 5" => true, "next greater than 5" => false } => [1, 2, 3, 4],
129
+ { "less than 5" => false, "next greater than 5" => true } => [5, 6, 7, 8, 9]
130
+ }
73
131
  ```
74
132
 
75
133
  ## Deep Cuts
76
134
 
77
- #### Pivot a list of users based on a value that is itself a list
135
+ ### Build a moderately complex dataset of Cities
78
136
 
79
137
  ```ruby
80
- list = [
81
- { :name => "Nathan", :projects => [:a, :b] },
82
- { :name => "Eric", :projects => [:a, :d, :g] },
83
- { :name => "Brian", :projects => [:b, :c, :e, :f] },
84
- { :name => "Mark", :projects => [:g] },
85
- { :name => "Josh", :projects => [:a, :c] },
86
- { :name => "Matthew", :projects => [:b, :c, :d] }
138
+ cities = [
139
+ { :name => "San Francisco",
140
+ :state => "CA",
141
+ :population => 805235,
142
+ :airlines => [ "Delta", "United", "SouthWest" ]
143
+ },
144
+ {
145
+ :name => "Mountain View",
146
+ :state => "CA",
147
+ :population => 74066,
148
+ :airlines => [ "SkyWest", "United", "SouthWest" ]
149
+ },
150
+ {
151
+ :name => "Manhattan",
152
+ :state => "NY",
153
+ :population => 1586698,
154
+ :airlines => [ "Delta", "JetBlue", "United" ]
155
+ },
156
+ {
157
+ :name => "Brooklyn",
158
+ :state => "NY",
159
+ :population => 2504700,
160
+ :airlines => [ "Delta", "American", "US Airways" ]
161
+ },
162
+ {
163
+ :name => "Boston",
164
+ :state => "MA",
165
+ :population => 617594,
166
+ :airlines => [ "Delta", "JetBlue", "American" ]
167
+ },
168
+ {
169
+ :name => "Atlanta",
170
+ :state => "GA",
171
+ :population => 420003,
172
+ :airlines => [ "Delta", "United", "SouthWest" ]
173
+ },
174
+ {
175
+ :name => "Dallas",
176
+ :state => "TX",
177
+ :population => 1197816,
178
+ :airlines => [ "Delta", "SouthWest", "Frontier" ]
179
+ }
87
180
  ]
88
- data = list.dig { |record| record[:projects] }
89
-
90
- # {
91
- # :a => [ { :name => "Nathan", :projects => [:a, :b] },
92
- # { :name => "Eric", :projects => [:a, :d, :g] },
93
- # { :name => "Josh", :projects => [:a, :c] } ],
94
- # :b => [ { :name => "Nathan", :projects => [:a, :b] },
95
- # { :name => "Brian", :projects => [:b, :c, :e, :f] },
96
- # { :name => "Matthew", :projects => [:b, :c, :d] } ],
97
- # :d => [ { :name => "Eric", :projects => [:a, :d, :g] },
98
- # { :name => "Matthew", :projects => [:b, :c, :d] } ],
99
- # :g => [ { :name => "Eric", :projects => [:a, :d, :g] },
100
- # { :name => "Mark", :projects => [:g] } ],
101
- # :c => [ { :name => "Brian", :projects => [:b, :c, :e, :f] },
102
- # { :name => "Josh", :projects => [:a, :c] },
103
- # { :name => "Matthew", :projects => [:b, :c, :d] } ],
104
- # :e => [ { :name => "Brian", :projects => [:b, :c, :e, :f] } ],
105
- # :f => [ { :name => "Brian", :projects => [:b, :c, :e, :f] } ]
106
- # }
107
-
108
181
  ```
109
182
 
110
- #### Pivot a list of users based on lang and number of projects owned
183
+ ### Pivot cities by state for population over 750k
111
184
 
112
185
  ```ruby
113
- list = [
114
- { :name => "Nathan", :langs => [:ruby, :javascript], :projects => [:a, :b] },
115
- { :name => "Eric", :langs => [:ruby, :javascript, :groovy], :projects => [:a, :d, :g] },
116
- { :name => "Brian", :langs => [:ruby, :javascript, :c, :go], :projects => [:b, :c, :e, :f] },
117
- { :name => "Mark", :langs => [:ruby, :java, :scala], :projects => [:g] },
118
- { :name => "Josh", :langs => [:ruby, :lisp, :clojure], :projects => [:a, :c] },
119
- { :name => "Matthew", :langs => [:ruby, :c, :clojure], :projects => [:b, :c, :d] }
120
- ]
121
- data = list
122
- .dig("lang") { |rec| rec[:langs] }
123
- .dig("project count") { |rec| rec[:projects].length }
124
-
125
- # {
126
- # ["lang: ruby", "project count: 2"] => [ { :name => "Nathan", ... }, { :name => "Josh", ... } ],
127
- # ["lang: ruby", "project count: 3"] => [ { :name => "Eric", ... }, { :name => "Matthew", ... } ],
128
- # ["lang: ruby", "project count: 4"] => [ { :name => "Brian", ... } ],
129
- # ["lang: ruby", "project count: 1"] => [ { :name => "Mark", ... } ],
130
- # ["lang: javascript", "project count: 2"] => [ { :name => "Nathan", ... } ],
131
- # ["lang: javascript", "project count: 3"] => [ { :name => "Eric", ... } ],
132
- # ["lang: javascript", "project count: 4"] => [ { :name => "Brian", ... } ],
133
- # ["lang: groovy", "project count: 3"] => [ { :name => "Eric", ... } ],
134
- # ["lang: c", "project count: 4"] => [ { :name => "Brian", ... } ],
135
- # ["lang: c", "project count: 3"] => [ { :name => "Matthew", ... } ],
136
- # ["lang: go", "project count: 4"] => [ { :name => "Brian", ... } ],
137
- # ["lang: java", "project count: 1"] => [ { :name => "Mark", ... } ],
138
- # ["lang: scala", "project count: 1"] => [ { :name => "Mark", ... } ],
139
- # ["lang: lisp", "project count: 2"] => [ { :name => "Josh", ... } ],
140
- # ["lang: clojure", "project count: 2"] => [ { :name => "Josh", ... } ],
141
- # ["lang: clojure", "project count: 3"] => [ { :name => "Matthew", ... } ]
142
- # }
186
+ # operation
187
+ data = cities
188
+ .pivot("state") { |city| city[:state] }
189
+ .pivot("population >= 750k") { |city| city[:population] >= 750000 }
190
+
191
+ # resulting data
192
+ {
193
+ { "state" => "CA", "population >= 750k" => true } => [ { :name => "San Francisco", ... } ],
194
+ { "state" => "CA", "population >= 750k" => false } => [ { :name => "Mountain View", ... } ],
195
+ { "state" => "NY", "population >= 750k" => true } => [ { :name => "Manhattan", ... }, { :name => "Brooklyn", ... } ],
196
+ { "state" => "MA", "population >= 750k" => false } => [ { :name => "Boston", ... } ],
197
+ { "state" => "GA", "population >= 750k" => false } => [ { :name => "Atlanta", ... } ],
198
+ { "state" => "TX", "population >= 750k" => true } => [ { :name => "Dallas", ... } ]
199
+ }
143
200
  ```
144
201
 
145
- #### Pivot a list of users based on whether or not they know javascript, what other languages they know, and whether or not their name contains the letter 'a'
146
-
147
- *Pretty contrived example here, but hopefully illustrates the type of power thats available.*
202
+ ### Putting it all together
203
+
204
+ **The end goal of all this is to support the creation of aggregate reports.**
205
+
206
+ *You can think of these reports as individual data cubes.*
207
+
208
+ Here is a table view of the pivoted city data from above.
209
+
210
+ <table>
211
+ <thead>
212
+ <tr>
213
+ <th>state</th>
214
+ <th>population >= 750k</th>
215
+ <th>cities</th>
216
+ </tr>
217
+ </thead>
218
+ <tbody>
219
+ <tr>
220
+ <td>CA</td>
221
+ <td>true</td>
222
+ <td>1</td>
223
+ </tr>
224
+ <tr>
225
+ <td>CA</td>
226
+ <td>false</td>
227
+ <td>1</td>
228
+ </tr>
229
+ <tr>
230
+ <td>NY</td>
231
+ <td>true</td>
232
+ <td>2</td>
233
+ </tr>
234
+ <tr>
235
+ <td>MA</td>
236
+ <td>false</td>
237
+ <td>1</td>
238
+ </tr>
239
+ <tr>
240
+ <td>GA</td>
241
+ <td>false</td>
242
+ <td>1</td>
243
+ </tr>
244
+ <tr>
245
+ <td>TX</td>
246
+ <td>true</td>
247
+ <td>1</td>
248
+ </tr>
249
+ </tbody>
250
+ </table>
251
+
252
+ Lets try another one.
253
+
254
+ ### Determine which airlines service cities with fewer than 750k people
148
255
 
149
256
  ```ruby
150
- list = [
151
- { :name => "Nathan", :langs => [:ruby, :javascript], :projects => [:a, :b] },
152
- { :name => "Eric", :langs => [:ruby, :javascript, :groovy], :projects => [:a, :d, :g] },
153
- { :name => "Brian", :langs => [:ruby, :javascript, :c, :go], :projects => [:b, :c, :e, :f] },
154
- { :name => "Mark", :langs => [:ruby, :java, :scala], :projects => [:g] },
155
- { :name => "Josh", :langs => [:ruby, :lisp, :clojure], :projects => [:a, :c] },
156
- { :name => "Matthew", :langs => [:ruby, :c, :clojure], :projects => [:b, :c, :d] }
157
- ]
158
- data = list
159
- .dig("knows javascript") { |rec| rec[:langs].include?(:javascript) }
160
- .dig("lang") { |rec| rec[:langs] }
161
- .dig("name includes 'a'") { |rec| rec[:name].include?("a") }
162
-
163
- # {
164
- # ["knows javascript: true", "lang: ruby", "name includes 'a': true"] => [ { :name => "Nathan", ... }, { :name => "Brian", ... } ],
165
- # ["knows javascript: true", "lang: ruby", "name includes 'a': false"] => [ { :name => "Eric", ... } ],
166
- # ["knows javascript: true", "lang: javascript", "name includes 'a': true"] => [ { :name => "Nathan", ... }, { :name => "Brian", ... } ],
167
- # ["knows javascript: true", "lang: javascript", "name includes 'a': false"] => [ { :name => "Eric", ... } ],
168
- # ["knows javascript: true", "lang: groovy", "name includes 'a': false"] => [ { :name => "Eric", ... } ],
169
- # ["knows javascript: true", "lang: c", "name includes 'a': true"] => [ { :name => "Brian", ... } ],
170
- # ["knows javascript: true", "lang: go", "name includes 'a': true"] => [ { :name => "Brian", ... } ],
171
- # ["knows javascript: false", "lang: ruby", "name includes 'a': true"] => [ { :name => "Mark", ... }, { :name => "Matthew", ... } ],
172
- # ["knows javascript: false", "lang: ruby", "name includes 'a': false"] => [ { :name => "Josh", ... } ],
173
- # ["knows javascript: false", "lang: java", "name includes 'a': true"] => [ { :name => "Mark", ... } ],
174
- # ["knows javascript: false", "lang: scala", "name includes 'a': true"] => [ { :name => "Mark", ... } ],
175
- # ["knows javascript: false", "lang: lisp", "name includes 'a': false"] => [ { :name => "Josh", ... } ],
176
- # ["knows javascript: false", "lang: clojure", "name includes 'a': false"] => [ { :name => "Josh", ... } ],
177
- # ["knows javascript: false", "lang: clojure", "name includes 'a': true"] => [ { :name => "Matthew", ... } ],
178
- # ["knows javascript: false", "lang: c", "name includes 'a': true"] => [ { :name => "Matthew", ... } ]
179
- # }
257
+ # operation
258
+ data = cities
259
+ .pivot("airline") { |city| city[:airlines] }
260
+ .pivot("population < 750k") { |city| city[:population] < 750000 }
261
+
262
+ # resulting data
263
+ {
264
+ { "airline" => "Delta", "population < 750k" => false } => [
265
+ { :name => "San Francisco", ... },
266
+ { :name => "Manhattan", ... },
267
+ { :name => "Brooklyn", ... },
268
+ { :name => "Dallas", ... }],
269
+ { "airline" => "Delta", "population < 750k" => true } => [
270
+ { :name => "Boston", ... },
271
+ { :name => "Atlanta", ... }],
272
+ { "airline" => "United", "population < 750k" => false } => [
273
+ { :name => "San Francisco", ... },
274
+ { :name => "Manhattan", ... }],
275
+ { "airline" => "United", "population < 750k" => true } => [
276
+ { :name => "Mountain View", ... },
277
+ { :name => "Atlanta", ... }],
278
+ { "airline" => "SouthWest", "population < 750k" => false } => [
279
+ { :name => "San Francisco", ... },
280
+ { :name => "Dallas", ... }],
281
+ { "airline" => "SouthWest", "population < 750k" => true } => [
282
+ { :name => "Mountain View", ... },
283
+ { :name => "Atlanta", ... }],
284
+ { "airline" => "SkyWest", "population < 750k" => true } => [
285
+ { :name => "Mountain View", ... }],
286
+ { "airline" => "JetBlue", "population < 750k" => false } => [
287
+ { :name => "Manhattan", ... }],
288
+ { "airline" => "JetBlue", "population < 750k" => true } => [
289
+ { :name => "Boston", ... }],
290
+ { "airline" => "American", "population < 750k" => false } => [
291
+ { :name => "Brooklyn", ... }],
292
+ { "airline" => "American", "population < 750k" => true } => [
293
+ { :name => "Boston", ... }],
294
+ { "airline" => "US Airways", "population < 750k" => false } => [
295
+ { :name => "Brooklyn", ... }],
296
+ { "airline" => "Frontier", "population < 750k" => false } => [
297
+ { :name => "Dallas", ... }]
298
+ }
180
299
  ```
300
+
301
+ Here is the corresponding table view for the above dataset.
302
+
303
+ <table>
304
+ <thead>
305
+ <tr>
306
+ <th>airline</th>
307
+ <th>population &lt; 750k</th>
308
+ <th>cities</th>
309
+ </tr>
310
+ </thead>
311
+ <tbody>
312
+ <tr>
313
+ <td>Delta</td>
314
+ <td>false</td>
315
+ <td>4</td>
316
+ </tr>
317
+ <tr>
318
+ <td>Delta</td>
319
+ <td>true</td>
320
+ <td>2</td>
321
+ </tr>
322
+ <tr>
323
+ <td>United</td>
324
+ <td>false</td>
325
+ <td>2</td>
326
+ </tr>
327
+ <tr>
328
+ <td>United</td>
329
+ <td>true</td>
330
+ <td>2</td>
331
+ </tr>
332
+ <tr>
333
+ <td>SouthWest</td>
334
+ <td>false</td>
335
+ <td>2</td>
336
+ </tr>
337
+ <tr>
338
+ <td>SouthWest</td>
339
+ <td>true</td>
340
+ <td>2</td>
341
+ </tr>
342
+ <tr>
343
+ <td>SkyWest</td>
344
+ <td>true</td>
345
+ <td>1</td>
346
+ </tr>
347
+ <tr>
348
+ <td>JetBlue</td>
349
+ <td>false</td>
350
+ <td>1</td>
351
+ </tr>
352
+ <tr>
353
+ <td>JetBlue</td>
354
+ <td>true</td>
355
+ <td>1</td>
356
+ </tr>
357
+ <tr>
358
+ <td>American</td>
359
+ <td>false</td>
360
+ <td>1</td>
361
+ </tr>
362
+ <tr>
363
+ <td>American</td>
364
+ <td>true</td>
365
+ <td>1</td>
366
+ </tr>
367
+ <tr>
368
+ <td>US Airways</td>
369
+ <td>false</td>
370
+ <td>1</td>
371
+ </tr>
372
+ <tr>
373
+ <td>Frontier</td>
374
+ <td>false</td>
375
+ <td>1</td>
376
+ </tr>
377
+ </tbody>
378
+ </table>
379
+
380
+ Hopefully you can see the potential even though the above examples are somewhat contrived.
381
+
382
+ ## Special thanks
383
+
384
+ * One on One Marketing - for sponsoring the development of Goldmine
385
+ * Eric Berry - for constructive feedback
386
+ * Josh Bowles - for early adoption and feedback
387
+ * Brett Beers - for early adoption and feedback
data/lib/goldmine.rb CHANGED
@@ -2,7 +2,7 @@ require "rubygems"
2
2
 
3
3
  module Goldmine
4
4
  module ArrayMiner
5
- def dig(name=nil, &block)
5
+ def pivot(name=nil, &block)
6
6
  reduce({}) do |memo, item|
7
7
  value = yield(item)
8
8
 
@@ -24,19 +24,18 @@ module Goldmine
24
24
 
25
25
  module HashMiner
26
26
  attr_accessor :goldmine
27
- def dig(name=nil, &block)
27
+ def pivot(name=nil, &block)
28
28
  return self unless goldmine
29
29
  reduce({}) do |memo, item|
30
30
  key = item.first
31
31
  value = item.last
32
- value.dig(name, &block).each do |k, v|
33
- new_key = []
34
- if key.is_a? Array
35
- new_key = new_key + key
32
+ value.pivot(name, &block).each do |k, v|
33
+ if key.is_a? Hash
34
+ k = { block.to_s => k } unless k.is_a?(Hash)
35
+ new_key = key.merge(k)
36
36
  else
37
- new_key << key
37
+ new_key = [key, k]
38
38
  end
39
- new_key << k
40
39
  memo[new_key] = v
41
40
  end
42
41
  memo.goldmine = true
@@ -51,7 +50,7 @@ module Goldmine
51
50
  end
52
51
 
53
52
  def goldmine_key(name, key)
54
- mine_key = "#{name}: #{key}" if name
53
+ mine_key = { name => key } if name
55
54
  mine_key ||= key
56
55
  end
57
56
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: goldmine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -50,5 +50,5 @@ rubyforge_project:
50
50
  rubygems_version: 1.8.10
51
51
  signing_key:
52
52
  specification_version: 3
53
- summary: Data mining made easy... the Ruby way.
53
+ summary: Pivot tables for the Rubyist
54
54
  test_files: []