csv_pirate 3.4.4 → 4.0.1
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/CHANGELOG +10 -0
- data/README.rdoc +27 -8
- data/Rakefile +8 -2
- data/VERSION.yml +3 -3
- data/csv_pirate.gemspec +15 -6
- data/init.rb +1 -9
- data/lib/csv_pirate.rb +112 -58
- data/lib/ninth_bit/pirate_ship.rb +42 -10
- data/rails/init.rb +8 -1
- data/spec/csv_pirate_spec.rb +190 -2
- data/spec/pirate_ship_spec.rb +69 -0
- data/spec/spec.opts +7 -0
- data/spec/spec_helper.rb +4 -1
- data/spec/spec_helpers/glowing_gas_ball.rb +30 -0
- data/spec/spec_helpers/star.rb +29 -0
- metadata +13 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
Version 4.0.1 2010-01-15
|
2
|
+
- Improving import / export
|
3
|
+
- Updating Readme to reflect 4.0.0 API
|
4
|
+
|
5
|
+
Version 4.0.0 2010-01-14 (never released)
|
6
|
+
- CSV Imports from old CsvPirate Dumps
|
7
|
+
- Lots of refactoring
|
8
|
+
- Lots of bug reduction
|
9
|
+
- added Rspec tests!
|
10
|
+
|
1
11
|
Version 3.4.4 2009-11-10
|
2
12
|
- Fixed installation instructions to refer to gemcutter, and removed github as gemhost
|
3
13
|
|
data/README.rdoc
CHANGED
@@ -2,9 +2,11 @@
|
|
2
2
|
|
3
3
|
Easily create CSVs of any data that can be derived from your models.
|
4
4
|
|
5
|
-
CsvPirate is the easy way to create a CSV of essentially anything in
|
5
|
+
CsvPirate is the easy way to create a CSV of essentially anything in Ruby, in full pirate regalia.
|
6
6
|
It works better if you are wearing a tricorne!
|
7
7
|
|
8
|
+
Everything in the source that depended on Rails extensions of Ruby classes has been refactored to work in pure Ruby!
|
9
|
+
|
8
10
|
My goal is to have it do EVERYTHING it possibly can for me, since almost every project I do needs CSV exports.
|
9
11
|
|
10
12
|
CsvPirate only works for commissions of swag OR grub!
|
@@ -33,9 +35,9 @@ Initialize method (a.k.a new()) takes a hash of parameters:
|
|
33
35
|
# :bury_treasure should we store the csv data as it is collected in an array in Ruby form for later use (true), or just write the CSV (false)?
|
34
36
|
# :blackjack Specify how you want your CSV header
|
35
37
|
# {:join => '-'} joins the method names called to get hte data for that column with '_' underscores.
|
36
|
-
# {:humanize =>'-'} first joins as above, then humanizes the string
|
38
|
+
# {:humanize =>'-'} first joins as above, then humanizes the string (this is the default)
|
37
39
|
# {:array => ['col1',col2','col3'] Uses the column names provided. If the array's length is less than the booty array's length it reverts to :humanize =>'_'
|
38
|
-
# check the source to see if there anything else hiding in there!
|
40
|
+
# check the source to see if there anything else hiding in there! There are a few new options in the 4.0.0 release, which are as yet undocumented.
|
39
41
|
|
40
42
|
The create method has the same parameters, and actually creates the CSV.
|
41
43
|
|
@@ -110,6 +112,8 @@ What's the simplest thing that will work?
|
|
110
112
|
|
111
113
|
== Usage without ActiveRecord
|
112
114
|
|
115
|
+
[ See Spec Tests for more Examples! ]
|
116
|
+
|
113
117
|
Since the defaults assume an active record class you need to override some of them:
|
114
118
|
|
115
119
|
class Star
|
@@ -199,7 +203,7 @@ Assuming a Make (as in manufacturers of automobiles) model like this:
|
|
199
203
|
:bury_treasure => true # Boolean: Should the array of objects in :swag be stored in the CsvPirate object for later inspection?
|
200
204
|
:blackjack => {:humanize => '-'} # Hash: Specify how you want your CSV header
|
201
205
|
# {:join => '-'} joins the method names called to get hte data for that column with '_' underscores.
|
202
|
-
# {:humanize => '-'} first joins as above, then humanizes the string
|
206
|
+
# {:humanize => '-'} first joins as above, then humanizes the string (this is the default)
|
203
207
|
# {:array => ['col1',col2','col3'] Uses the column names provided in the array. If the array provided is too short defaults to :humanize =>'_'
|
204
208
|
|
205
209
|
# A customized version to create a tab delimited file for this class might look like this:
|
@@ -324,13 +328,20 @@ You have the same Make class as above, and you have a MakeController:
|
|
324
328
|
class MakeController < ApplicationController
|
325
329
|
def download_csv
|
326
330
|
csv_pirate = Make.blindfold
|
327
|
-
|
328
|
-
|
329
|
-
|
331
|
+
|
332
|
+
# maroon saves the read to the file system, by using the text of the csv stored in the CsvPirate object.
|
333
|
+
send_data csv_pirate.maroon, ...
|
334
|
+
:type => 'text/csv; charset=iso-8859-1; header=present',
|
335
|
+
:disposition => "attachment; filename=#{csv_pirate.nocturnal}"
|
336
|
+
|
337
|
+
# However if CSVs are created using multiple CsvPirate objects that all append to a single file,
|
338
|
+
# we need to read the final product from the fs.
|
339
|
+
#send_file csv_pirate.brigantine,
|
340
|
+
# :type => 'text/csv; charset=utf-8; header=present',
|
341
|
+
# :disposition => "attachment; filename=#{csv_pirate.nocturnal}"
|
330
342
|
end
|
331
343
|
end
|
332
344
|
|
333
|
-
|
334
345
|
== Advanced Example with Nested Methods
|
335
346
|
|
336
347
|
You have a VehicleModel class and the same Make class as up above:
|
@@ -399,6 +410,14 @@ This allows you to modify the csv_pirate object before creating the csv like thi
|
|
399
410
|
csv_pirate.booty -= [:id, :name]
|
400
411
|
csv_pirate.hoist_mainstay()
|
401
412
|
|
413
|
+
== Tests
|
414
|
+
|
415
|
+
The tests are run with rspec. The test suite is expanding. Currently there is ample coverage of basic functionality.
|
416
|
+
|
417
|
+
To run tests cd to where ever you have csv_pirate installed, and do:
|
418
|
+
|
419
|
+
rake spec
|
420
|
+
|
402
421
|
== BUGS (Not mine, Micrsoft's)
|
403
422
|
|
404
423
|
Microsoft Office (Excel) "SYLK Invalid Format" Error will occur if the string "ID" (without quotes)
|
data/Rakefile
CHANGED
@@ -4,8 +4,8 @@ begin
|
|
4
4
|
require 'jeweler'
|
5
5
|
Jeweler::Tasks.new do |gemspec|
|
6
6
|
gemspec.name = "csv_pirate"
|
7
|
-
gemspec.summary = "Easily create CSVs of any data that can be derived from
|
8
|
-
gemspec.description = %q{CsvPirate is the easy way to create a CSV of essentially anything in
|
7
|
+
gemspec.summary = "Easily create CSVs of any data that can be derived from instance methods on your classes."
|
8
|
+
gemspec.description = %q{CsvPirate is the easy way to create a CSV of essentially anything in Ruby, in full pirate regalia.
|
9
9
|
It works better if you are wearing a tricorne!}
|
10
10
|
gemspec.email = "peter.boling@gmail.com"
|
11
11
|
gemspec.homepage = "http://github.com/pboling/csv_pirate"
|
@@ -18,6 +18,12 @@ It works better if you are wearing a tricorne!}
|
|
18
18
|
"install.rb",
|
19
19
|
"lib/csv_pirate.rb",
|
20
20
|
"lib/ninth_bit/pirate_ship.rb",
|
21
|
+
"spec/csv_pirate_spec.rb",
|
22
|
+
"spec/pirate_ship_spec.rb",
|
23
|
+
"spec/spec.opts",
|
24
|
+
"spec/spec_helper.rb",
|
25
|
+
"spec/spec_helpers/glowing_gas_ball.rb",
|
26
|
+
"spec/spec_helpers/star.rb",
|
21
27
|
"Rakefile",
|
22
28
|
"LICENSE",
|
23
29
|
"CHANGELOG",
|
data/VERSION.yml
CHANGED
data/csv_pirate.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{csv_pirate}
|
8
|
-
s.version = "
|
8
|
+
s.version = "4.0.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Peter Boling"]
|
12
|
-
s.date = %q{
|
13
|
-
s.description = %q{CsvPirate is the easy way to create a CSV of essentially anything in
|
12
|
+
s.date = %q{2010-01-15}
|
13
|
+
s.description = %q{CsvPirate is the easy way to create a CSV of essentially anything in Ruby, in full pirate regalia.
|
14
14
|
It works better if you are wearing a tricorne!}
|
15
15
|
s.email = %q{peter.boling@gmail.com}
|
16
16
|
s.extra_rdoc_files = [
|
@@ -28,16 +28,25 @@ It works better if you are wearing a tricorne!}
|
|
28
28
|
"install.rb",
|
29
29
|
"lib/csv_pirate.rb",
|
30
30
|
"lib/ninth_bit/pirate_ship.rb",
|
31
|
-
"rails/init.rb"
|
31
|
+
"rails/init.rb",
|
32
|
+
"spec/csv_pirate_spec.rb",
|
33
|
+
"spec/pirate_ship_spec.rb",
|
34
|
+
"spec/spec.opts",
|
35
|
+
"spec/spec_helper.rb",
|
36
|
+
"spec/spec_helpers/glowing_gas_ball.rb",
|
37
|
+
"spec/spec_helpers/star.rb"
|
32
38
|
]
|
33
39
|
s.homepage = %q{http://github.com/pboling/csv_pirate}
|
34
40
|
s.rdoc_options = ["--charset=UTF-8"]
|
35
41
|
s.require_paths = ["lib"]
|
36
42
|
s.rubygems_version = %q{1.3.5}
|
37
|
-
s.summary = %q{Easily create CSVs of any data that can be derived from
|
43
|
+
s.summary = %q{Easily create CSVs of any data that can be derived from instance methods on your classes.}
|
38
44
|
s.test_files = [
|
39
45
|
"spec/csv_pirate_spec.rb",
|
40
|
-
"spec/
|
46
|
+
"spec/pirate_ship_spec.rb",
|
47
|
+
"spec/spec_helper.rb",
|
48
|
+
"spec/spec_helpers/glowing_gas_ball.rb",
|
49
|
+
"spec/spec_helpers/star.rb"
|
41
50
|
]
|
42
51
|
|
43
52
|
if s.respond_to? :specification_version then
|
data/init.rb
CHANGED
@@ -1,9 +1 @@
|
|
1
|
-
require '
|
2
|
-
require 'ninth_bit/pirate_ship'
|
3
|
-
|
4
|
-
# If you are using this on a vanilla Ruby class (no rails or active record) then extend your class like this:
|
5
|
-
# MyClass.send(:extend, NinthBit::PirateShip::ActMethods) if defined?(MyClass)
|
6
|
-
# Alternatively you can do this inside your class definition:
|
7
|
-
# class MyClass
|
8
|
-
# extend NinthBit::PirateShip::ActMethods
|
9
|
-
# end
|
1
|
+
require 'rails/init'
|
data/lib/csv_pirate.rb
CHANGED
@@ -7,12 +7,12 @@
|
|
7
7
|
#Version: 1.0
|
8
8
|
#Project owners:
|
9
9
|
# peter.boling (The Cap'n)
|
10
|
-
require 'faster_csv' unless defined?(FasterCSV)
|
11
10
|
|
12
11
|
class CsvPirate
|
13
12
|
|
14
13
|
BOOKIE = [:counter, :timestamp, :none]
|
15
14
|
MOP_HEADS = [:clean, :dirty]
|
15
|
+
BRIGANTINE = [:first, :last]
|
16
16
|
|
17
17
|
attr_accessor :waggoner # First part of filename
|
18
18
|
attr_accessor :chart # directory, default is (['log','csv'])
|
@@ -52,7 +52,11 @@ class CsvPirate
|
|
52
52
|
# {:humanize => '-'} first joins as above, then humanizes the string
|
53
53
|
# {:array => ['col1',col2','col3'] Uses the column names provided in the array. If the array provided is too short defaults to :humanize =>'_'
|
54
54
|
|
55
|
-
|
55
|
+
attr_accessor :brigantine # the complete file path
|
56
|
+
attr_accessor :pinnacle # the complete file path
|
57
|
+
class << self
|
58
|
+
attr_accessor :parlay # verbosity on a scale of 0 - 3 (0=:none, 1=:error, 2=:info, 3=:debug, 0 being no screen output, 1 is default
|
59
|
+
end
|
56
60
|
|
57
61
|
# CsvPirate only works for commissions of swag OR grub!
|
58
62
|
# :swag the ARrr collection of swag to work on (optional)
|
@@ -81,15 +85,15 @@ class CsvPirate
|
|
81
85
|
# See README for examples
|
82
86
|
|
83
87
|
def initialize(*args)
|
84
|
-
raise ArgumentError, "must provide required options" if args.
|
88
|
+
raise ArgumentError, "must provide required options" if args.nil?
|
85
89
|
|
86
90
|
@swag = args.first[:swag]
|
87
91
|
@grub = args.first[:grub]
|
88
92
|
|
89
93
|
# if they provide both
|
90
|
-
raise ArgumentError, "must provide either :swag or :grub, not both" if !self.swag.
|
94
|
+
raise ArgumentError, "must provide either :swag or :grub, not both" if !self.swag.nil? && !self.grub.nil?
|
91
95
|
# if they provide neither
|
92
|
-
raise ArgumentError, "must provide either :swag or :grub" if self.swag.
|
96
|
+
raise ArgumentError, "must provide either :swag or :grub" if self.swag.nil? && self.grub.nil?
|
93
97
|
|
94
98
|
@swab = args.first[:swab] || :counter
|
95
99
|
raise ArgumentError, ":swab is #{self.swab.inspect}, but must be one of #{CsvPirate::BOOKIE.inspect}" unless CsvPirate::BOOKIE.include?(self.swab)
|
@@ -103,16 +107,17 @@ class CsvPirate
|
|
103
107
|
@waggoner = args.first[:waggoner] || "#{self.grub || self.swag}"
|
104
108
|
raise ArgumentError, ":waggoner is #{self.waggoner.inspect}, and must be a string at least one character long" if self.waggoner.nil? || self.waggoner.length < 1
|
105
109
|
|
106
|
-
@booty = args.first[:booty] || []
|
110
|
+
@booty = args.first[:booty] || [] # would like to use Class#instance_variables for generic classes
|
107
111
|
raise ArgumentError, ":booty is #{self.booty.inspect}, and must be an array of methods to call on a class for CSV data" if self.booty.nil? || !self.booty.is_a?(Array) || self.booty.empty?
|
108
112
|
|
109
113
|
@chart = args.first[:chart] || ['log','csv']
|
110
114
|
raise ArgumentError, ":chart is #{self.chart.inspect}, and must be an array of directory names, which will become the filepath for the csv file" if self.chart.nil? || !self.chart.is_a?(Array) || self.chart.empty?
|
111
115
|
|
112
116
|
@aft = args.first[:aft] || '.csv'
|
113
|
-
@chronometer = args.first[:chronometer] == false ? false : args.first[:chronometer] || Date.today
|
117
|
+
@chronometer = args.first[:chronometer] == false ? false : (args.first[:chronometer] || Date.today)
|
118
|
+
|
119
|
+
@spyglasses = (args.first[:spyglasses] || (self.respond_to?(:all) ? [:all] : nil)) if self.grub
|
114
120
|
|
115
|
-
@spyglasses = (args.first[:spyglasses] || [:all]) if self.grub
|
116
121
|
@shrouds = args.first[:shrouds] || ',' # for tsv, tab-delimited, "\t"
|
117
122
|
raise ArgumentError, ":shrouds is #{self.shrouds.inspect}, and must be a string (e.g. ',' or '\t'), which will be used as the delimeter for the csv file" if self.shrouds.nil? || !self.shrouds.is_a?(String)
|
118
123
|
|
@@ -121,8 +126,8 @@ class CsvPirate
|
|
121
126
|
@bury_treasure = args.first[:astrolabe] || false
|
122
127
|
@buried_treasure = []
|
123
128
|
|
124
|
-
#
|
125
|
-
@blackjack = args.first[:blackjack] || {:
|
129
|
+
#does not rely on rails humanize!
|
130
|
+
@blackjack = args.first[:blackjack] || {:humanize => '_'}
|
126
131
|
|
127
132
|
#Make sure the header array is the same length as the booty columns
|
128
133
|
if self.blackjack.keys.first == :array && (self.blackjack.values.first.length != self.booty.length)
|
@@ -130,7 +135,9 @@ class CsvPirate
|
|
130
135
|
puts "Warning: :blackjack reset to {:join => '_'} because the length of the :booty is different than the length of the array provided to :blackjack" if CsvPirate.parlance(2)
|
131
136
|
end
|
132
137
|
|
133
|
-
|
138
|
+
@pinnacle = self.block_and_tackle
|
139
|
+
|
140
|
+
# Initialize doesn't write anything to a CSV,
|
134
141
|
# but does create the traverse_board and opens the waggoner for reading / writing
|
135
142
|
self.northwest_passage unless self.astrolabe
|
136
143
|
|
@@ -140,10 +147,13 @@ class CsvPirate
|
|
140
147
|
# Once the traverse_board (dir) exists, then check if the rhumb_lines (file) already exists, and set our rhumb_lines counter
|
141
148
|
@swabbie = self.insult_swabbie
|
142
149
|
|
143
|
-
@
|
150
|
+
@brigantine = self.poop_deck(args.first[:brigantine])
|
151
|
+
|
152
|
+
@nocturnal = File.basename(self.brigantine)
|
153
|
+
|
144
154
|
|
145
155
|
# Then open the rhumb_lines
|
146
|
-
self.rhumb_lines = File.open(File.expand_path(self.
|
156
|
+
self.rhumb_lines = File.open(File.expand_path(self.brigantine),self.astrolabe ? "r" : "a")
|
147
157
|
end
|
148
158
|
|
149
159
|
def self.create(*args)
|
@@ -234,7 +244,7 @@ class CsvPirate
|
|
234
244
|
def jolly_roger
|
235
245
|
if self.bury_treasure
|
236
246
|
if self.buried_treasure.is_a?(Array)
|
237
|
-
puts "Found #{self.buried_treasure.length} deniers buried here: '#{self.
|
247
|
+
puts "Found #{self.buried_treasure.length} deniers buried here: '#{self.brigantine}'" if CsvPirate.parlay && CsvPirate.parlance(1)
|
238
248
|
puts "You must weigh_anchor to review your plunder!" if CsvPirate.parlay && CsvPirate.parlance(1)
|
239
249
|
else
|
240
250
|
puts "Failed to locate treasure" if CsvPirate.parlay && CsvPirate.parlance(1)
|
@@ -252,35 +262,6 @@ class CsvPirate
|
|
252
262
|
end
|
253
263
|
end
|
254
264
|
|
255
|
-
# create the header of the CSV (column/method names)
|
256
|
-
# returns an array of strings for CSV header based on blackjack
|
257
|
-
def block_and_tackle
|
258
|
-
self.blackjack.map do |k,v|
|
259
|
-
case k
|
260
|
-
#Joining is only relevant when the booty contains a nested hash of method calls as at least one of the booty array elements
|
261
|
-
#Use the booty (methods) as the column headers
|
262
|
-
when :join then self.binnacle(v, false)
|
263
|
-
#Use the humanized booty (methods) as the column headers
|
264
|
-
when :humanize then self.binnacle(v, true)
|
265
|
-
when :array then v
|
266
|
-
end
|
267
|
-
end.first
|
268
|
-
end
|
269
|
-
|
270
|
-
#returns an array of strings for CSV header based on booty
|
271
|
-
def binnacle(join_value, humanize = true)
|
272
|
-
self.booty.map do |compass|
|
273
|
-
string = compass.is_a?(Hash) ?
|
274
|
-
self.run_through(compass, join_value) :
|
275
|
-
compass.is_a?(String) ?
|
276
|
-
compass :
|
277
|
-
compass.is_a?(Symbol) ?
|
278
|
-
compass.to_s :
|
279
|
-
compass.to_s
|
280
|
-
humanize ? string.humanize : string
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
265
|
#Takes a potentially nested hash element of a booty array and turns it into a string for a column header
|
285
266
|
# hash = {:a => {:b => {:c => {:d => {"e" => "fghi"}}}}}
|
286
267
|
# run_through(hash, '_')
|
@@ -297,30 +278,102 @@ class CsvPirate
|
|
297
278
|
end
|
298
279
|
|
299
280
|
#complete file path
|
300
|
-
def poop_deck
|
301
|
-
|
281
|
+
def poop_deck(brig)
|
282
|
+
if BRIGANTINE.include?(brig)
|
283
|
+
self.old_csv_dump(brig)
|
284
|
+
elsif brig.is_a?(String)
|
285
|
+
"#{self.analemma}#{brig}"
|
286
|
+
else
|
287
|
+
"#{self.analemma}#{self.swabbie}#{self.aft}"
|
288
|
+
end
|
302
289
|
end
|
303
290
|
|
304
|
-
# Swabs the poop_deck if the mop is clean. (!)
|
291
|
+
# Swabs the poop_deck (of the brigantine) if the mop is clean. (!)
|
305
292
|
def swab_poop_deck
|
306
|
-
self.rhumb_lines.truncate(0) if self.swab == :none && self.mop == :clean && File.size(self.
|
293
|
+
self.rhumb_lines.truncate(0) if self.swab == :none && self.mop == :clean && File.size(self.brigantine) > 0
|
307
294
|
end
|
308
295
|
|
309
296
|
# Must be done on order to rummage through the loot found by the pirate ship
|
310
297
|
def weigh_anchor
|
311
|
-
CsvPirate.rinse(self.
|
298
|
+
CsvPirate.rinse(self.brigantine)
|
312
299
|
end
|
313
300
|
|
314
301
|
# Sink your own ship! Or run a block of code on each row of the current CSV
|
315
302
|
def scuttle(&block)
|
316
303
|
return false unless block_given?
|
317
|
-
CsvPirate.broadside(self.
|
304
|
+
CsvPirate.broadside(self.brigantine) do |careen|
|
318
305
|
yield careen
|
319
306
|
end
|
320
307
|
end
|
321
308
|
|
309
|
+
def to_memory(exclude_id = true, exclude_timestamps = true)
|
310
|
+
return nil unless self.grub
|
311
|
+
begin
|
312
|
+
example = self.grub.new
|
313
|
+
rescue Exception
|
314
|
+
puts "cannot instantiate instance of #{self.grub} with #{self.grub}.new. CsvPirate#to_memory works most reliably when #{self.grub}.new works with no arguments." if CsvPirate.parlance(1)
|
315
|
+
example = nil
|
316
|
+
end
|
317
|
+
buccaneers = []
|
318
|
+
self.scuttle do |row|
|
319
|
+
#puts "#{self.pinnacle.first.inspect} #{row[self.pinnacle.first].inspect}"
|
320
|
+
buccaneers << self.grub.new(self.data_hash_from_row(row, exclude_id, exclude_timestamps, example))
|
321
|
+
end
|
322
|
+
buccaneers
|
323
|
+
end
|
324
|
+
|
325
|
+
def data_hash_from_row(row, exclude_id = true, exclude_timestamps = true, example = nil)
|
326
|
+
data_hash = {}
|
327
|
+
my_booty = self.booty.reject {|x| x.is_a?(Hash)}
|
328
|
+
my_booty = exclude_id ? my_booty.reject {|x| a = x.to_sym; [:id, :ID,:dbid, :DBID, :db_id, :DB_ID].include?(a)} : self.booty
|
329
|
+
my_booty = exclude_timestamps ? my_booty.reject {|x| a = x.to_sym; [:created_at, :updated_at, :created_on, :updated_on].include?(a)} : self.booty
|
330
|
+
my_booty = my_booty.reject {|x| !example.respond_to?("#{x}=".to_sym)} unless example.nil?
|
331
|
+
my_booty.each do |method|
|
332
|
+
#puts "#{self.pinnacle[index]}"
|
333
|
+
data_hash = data_hash.merge({method => row[self.pinnacle[self.booty.index(method)]]})
|
334
|
+
end
|
335
|
+
#puts "#{data_hash.inspect}"
|
336
|
+
data_hash
|
337
|
+
end
|
338
|
+
|
339
|
+
# Grab an old CSV dump (first or last)
|
340
|
+
def old_csv_dump(brig)
|
341
|
+
file = Dir.entries(self.traverse_board).reject {|x| x.match(/^\./)}.sort.send(brig)
|
342
|
+
"#{self.traverse_board}#{file}"
|
343
|
+
end
|
344
|
+
|
322
345
|
protected
|
323
346
|
|
347
|
+
# create the header of the CSV (column/method names)
|
348
|
+
# returns an array of strings for CSV header based on blackjack
|
349
|
+
def block_and_tackle
|
350
|
+
self.blackjack.map do |k,v|
|
351
|
+
case k
|
352
|
+
#Joining is only relevant when the booty contains a nested hash of method calls as at least one of the booty array elements
|
353
|
+
#Use the booty (methods) as the column headers
|
354
|
+
when :join then self.binnacle(v, false)
|
355
|
+
#Use the humanized booty (methods) as the column headers
|
356
|
+
when :humanize then self.binnacle(v, true)
|
357
|
+
when :array then v
|
358
|
+
end
|
359
|
+
end.first
|
360
|
+
end
|
361
|
+
|
362
|
+
#returns an array of strings for CSV header based on booty
|
363
|
+
def binnacle(join_value, humanize = true)
|
364
|
+
self.booty.map do |compass|
|
365
|
+
string = compass.is_a?(Hash) ?
|
366
|
+
self.run_through(compass, join_value) :
|
367
|
+
compass.is_a?(String) ?
|
368
|
+
compass :
|
369
|
+
compass.is_a?(Symbol) ?
|
370
|
+
compass.to_s :
|
371
|
+
compass.to_s
|
372
|
+
humanize ? string.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize : string
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
# The directory path to the csv
|
324
377
|
def traverse_board
|
325
378
|
#If we have rails environment then we use rails root, otherwise self.chart stands on its own as a relative path
|
326
379
|
"#{self.north_pole}#{self.chart.join('/')}/"
|
@@ -358,18 +411,21 @@ class CsvPirate
|
|
358
411
|
index = base.rindex('.')
|
359
412
|
tail = index.nil? ? nil : base[index+1,base.length]
|
360
413
|
# Ensure numbers
|
361
|
-
|
414
|
+
tail.nil? ? 0 : tail[/\d*/].to_i
|
362
415
|
end
|
363
|
-
|
416
|
+
|
417
|
+
# Get all the files in the dir
|
418
|
+
def axe
|
419
|
+
Dir.glob(self.lantern)
|
420
|
+
end
|
421
|
+
|
422
|
+
# File increment for next CSV to dump
|
364
423
|
def boatswain
|
365
424
|
return self.swabbie unless self.swabbie.nil?
|
366
|
-
counter = 0
|
367
|
-
bowspirit = Dir.glob(self.lantern)
|
368
425
|
highval = 0
|
369
|
-
|
426
|
+
self.axe.each do |flotsam|
|
370
427
|
counter = self.filibuster(flotsam)
|
371
428
|
highval = ((highval <=> counter) == 1) ? highval : counter
|
372
|
-
counter = 0
|
373
429
|
end
|
374
430
|
".#{highval + 1}"
|
375
431
|
end
|
@@ -409,7 +465,7 @@ class CsvPirate
|
|
409
465
|
spoils = spoils.send(east.to_sym)
|
410
466
|
unless spoils.nil?
|
411
467
|
if west.is_a?(Hash)
|
412
|
-
# Recursive
|
468
|
+
# Recursive madness is here!
|
413
469
|
spoils = CsvPirate.marlinespike(spoils, west)
|
414
470
|
else
|
415
471
|
spoils = spoils.send(west.to_sym)
|
@@ -431,9 +487,7 @@ class CsvPirate
|
|
431
487
|
# Sink other ships! Or run a block of code on each row of a CSV
|
432
488
|
def self.broadside(galley, &block)
|
433
489
|
return false unless block_given?
|
434
|
-
count = 1 if report_kills
|
435
490
|
FasterCSV.foreach(galley, {:headers => :first_row, :return_headers => false}) do |gun|
|
436
|
-
puts "Galleys sunk: #{count+=1}" if CsvPirate.parlance(1)
|
437
491
|
yield gun
|
438
492
|
end
|
439
493
|
end
|
@@ -11,15 +11,16 @@ module NinthBit
|
|
11
11
|
options[:chart] ||= ['log','csv']
|
12
12
|
options[:aft] ||= '.csv'
|
13
13
|
options[:gibbet] ||= '.export'
|
14
|
-
#Needs to be defined at runtime, doesn't make sense here
|
15
|
-
#
|
14
|
+
#Needs to be defined at runtime, doesn't make sense here unless set to false, except to be overridden at runtime
|
15
|
+
# Default is nil so that the CsvPirate default will kick-in.
|
16
|
+
options[:chronometer] ||= nil
|
16
17
|
options[:waggoner] ||= "#{self}"
|
17
18
|
options[:swag] ||= nil
|
18
19
|
options[:swab] ||= :counter
|
19
20
|
options[:mop] ||= :clean
|
20
21
|
options[:shrouds] ||= ','
|
21
22
|
options[:grub] ||= self if options[:swag].nil?
|
22
|
-
options[:spyglasses] ||= [:all]
|
23
|
+
options[:spyglasses] ||= (self.respond_to?(:all) ? [:all] : nil) if options[:grub]
|
23
24
|
# Have to protect against model definitions pre-migration, since column names will fail if
|
24
25
|
options[:booty] ||= check_booty ? self.column_names : []
|
25
26
|
options[:bury_treasure] ||= true
|
@@ -27,9 +28,9 @@ module NinthBit
|
|
27
28
|
options[:parlay] ||= 1
|
28
29
|
|
29
30
|
# if they provide both
|
30
|
-
raise ArgumentError, "must provide either :swag or :grub, not both" if !options[:swag].
|
31
|
+
raise ArgumentError, "must provide either :swag or :grub, not both" if !options[:swag].nil? && !options[:grub].nil?
|
31
32
|
# if they provide neither
|
32
|
-
raise ArgumentError, "must provide either :swag or :grub" if options[:swag].
|
33
|
+
raise ArgumentError, "must provide either :swag or :grub" if options[:swag].nil? && options[:grub].nil?
|
33
34
|
raise ArgumentError, ":swab is #{options[:swab].inspect}, but must be one of #{CsvPirate::BOOKIE.inspect}" unless CsvPirate::BOOKIE.include?(options[:swab])
|
34
35
|
raise ArgumentError, ":mop is #{options[:mop].inspect}, but must be one of #{CsvPirate::MOP_HEADS.inspect}" unless CsvPirate::MOP_HEADS.include?(options[:mop])
|
35
36
|
raise ArgumentError, ":gibbet is #{options[:gibbet].inspect}, and does not contain a '.' character, which is required when using iterative filenames (set :swab => :none to turn off iterative filenames)" if options[:swab] != :none && (options[:gibbet].nil? || !options[:gibbet].include?('.'))
|
@@ -41,6 +42,10 @@ module NinthBit
|
|
41
42
|
|
42
43
|
extend ClassMethods unless (class << self; included_modules; end).include?(ClassMethods)
|
43
44
|
|
45
|
+
class << self
|
46
|
+
attr_accessor :piratey_options
|
47
|
+
end
|
48
|
+
|
44
49
|
self.piratey_options = options
|
45
50
|
|
46
51
|
end
|
@@ -58,10 +63,6 @@ module NinthBit
|
|
58
63
|
|
59
64
|
module ClassMethods
|
60
65
|
|
61
|
-
def self.extended(base)
|
62
|
-
base.class_inheritable_accessor :piratey_options
|
63
|
-
end
|
64
|
-
|
65
66
|
# intended for use with send_data for downloading the text of the csv:
|
66
67
|
# send_data Make.say_your_last_words
|
67
68
|
# TODO: Fix say_your_last_words so it works! Use send_data args for real
|
@@ -103,6 +104,29 @@ module NinthBit
|
|
103
104
|
CsvPirate.new(self.piratey_args(args))
|
104
105
|
end
|
105
106
|
|
107
|
+
def weigh_anchor(args = {})
|
108
|
+
pargs = self.piratey_args(args)
|
109
|
+
pargs.merge!({
|
110
|
+
:gibbet => '.dump',
|
111
|
+
:chart => pargs[:chart] + ["dumps"],
|
112
|
+
})
|
113
|
+
CsvPirate.create(pargs)
|
114
|
+
end
|
115
|
+
|
116
|
+
def raise_anchor(args = {})
|
117
|
+
pargs = self.piratey_args(args)
|
118
|
+
pargs.merge!({
|
119
|
+
:chart => pargs[:chart] + ["dumps"],
|
120
|
+
:brigantine => :last
|
121
|
+
})
|
122
|
+
csv_pirate = CsvPirate.new(pargs)
|
123
|
+
|
124
|
+
csv_pirate.to_memory.map do |obj|
|
125
|
+
obj.save(false) if obj.respond_to?(:save)
|
126
|
+
obj
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
106
130
|
protected
|
107
131
|
|
108
132
|
def piratey_args(args = {})
|
@@ -110,7 +134,7 @@ module NinthBit
|
|
110
134
|
return { :chart => args[:chart] || self.piratey_options[:chart],
|
111
135
|
:aft => args[:aft] || self.piratey_options[:aft],
|
112
136
|
:gibbet => args[:gibbet] || self.piratey_options[:gibbet],
|
113
|
-
:chronometer => args[:chronometer]
|
137
|
+
:chronometer => get_chronometer(args[:chronometer]),
|
114
138
|
:waggoner => args[:waggoner] || self.piratey_options[:waggoner] || "#{self}",
|
115
139
|
:swag => args[:swag] || self.piratey_options[:swag],
|
116
140
|
:swab => args[:swab] || self.piratey_options[:swab],
|
@@ -123,6 +147,14 @@ module NinthBit
|
|
123
147
|
:bury_treasure => args[:bury_treasure] || self.piratey_options[:bury_treasure] }
|
124
148
|
end
|
125
149
|
|
150
|
+
def get_chronometer(chron)
|
151
|
+
chron == false ?
|
152
|
+
false :
|
153
|
+
(chron || (self.piratey_options[:chronometer] == false ?
|
154
|
+
false :
|
155
|
+
(self.piratey_options[:chronometer] || Date.today)))
|
156
|
+
end
|
157
|
+
|
126
158
|
end
|
127
159
|
|
128
160
|
end
|
data/rails/init.rb
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
gem 'fastercsv'
|
4
|
+
rescue LoadError
|
5
|
+
"Unable to load dependencies: rubygems or fastercsv"
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'faster_csv' unless defined?(FasterCSV)
|
2
9
|
require 'csv_pirate'
|
3
10
|
require 'ninth_bit/pirate_ship'
|
4
11
|
|
data/spec/csv_pirate_spec.rb
CHANGED
@@ -1,7 +1,195 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
3
|
describe "CsvPirate" do
|
4
|
-
|
5
|
-
|
4
|
+
describe "#initialize" do
|
5
|
+
before(:each) do
|
6
|
+
@csv_pirate = CsvPirate.new({
|
7
|
+
:grub => GlowingGasBall,
|
8
|
+
:spyglasses => [:get_stars],
|
9
|
+
:chart => ["spec","csv","GlowingGasBall"],
|
10
|
+
:booty => [:name, :distance, :spectral_type, {:name => :hash}, {:name => :next}, {:name => :upcase}, :star_vowels ],
|
11
|
+
:chronometer => false,
|
12
|
+
:gibbet => "",
|
13
|
+
:aft => ".csv",
|
14
|
+
:swab => :none,
|
15
|
+
:mop => :clean,
|
16
|
+
:waggoner => 'data'
|
17
|
+
})
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return an instance of CsvPirate" do
|
21
|
+
@csv_pirate.class.should == CsvPirate
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not export anything" do
|
25
|
+
@csv_pirate.maroon.should == ""
|
26
|
+
end
|
6
27
|
end
|
28
|
+
|
29
|
+
describe "#create" do
|
30
|
+
before(:each) do
|
31
|
+
@csv_pirate = CsvPirate.create({
|
32
|
+
:grub => GlowingGasBall,
|
33
|
+
:spyglasses => [:get_stars],
|
34
|
+
:chart => ["spec","csv","GlowingGasBall"],
|
35
|
+
:booty => [:name, :distance, :spectral_type, {:name => :hash}, {:name => :next}, {:name => :upcase}, :star_vowels ],
|
36
|
+
:chronometer => false,
|
37
|
+
:gibbet => "",
|
38
|
+
:aft => ".csv",
|
39
|
+
:swab => :none,
|
40
|
+
:mop => :clean,
|
41
|
+
:waggoner => 'data'
|
42
|
+
})
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should return an instance of CsvPirate" do
|
46
|
+
@csv_pirate.class.should == CsvPirate
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should store export in maroon instance variable" do
|
50
|
+
@csv_pirate.maroon.should == "Name,Distance,Spectral type,Name hash,Name next,Name upcase,Star vowels\nProxima Centauri,4.2 LY,M5.5Vc,-1176188012,Proxima Centaurj,PROXIMA CENTAURI,Pr*x*m* C*nt**r*\nRigil Kentaurus,4.3 LY,G2V,1916094624,Rigil Kentaurut,RIGIL KENTAURUS,R*g*l K*nt**r*s\nBarnard's Star,5.9 LY,M3.8V,1003964756,Barnard's Stas,BARNARD'S STAR,B*rn*rd's St*r\nWolf 359,7.7 LY,M5.8Vc,-1717989858,Wolf 360,WOLF 359,W*lf 359\nLalande 21185,8.26 LY,M2V,466625069,Lalande 21186,LALANDE 21185,L*l*nd* 21185\nLuyten 726-8A and B,8.73 LY,M5.5 de & M6 Ve,1260790153,Luyten 726-8A and C,LUYTEN 726-8A AND B,L*yt*n 726-8A *nd B\nSirius A and B,8.6 LY,A1Vm,1177502705,Sirius A and C,SIRIUS A AND B,S*r**s A *nd B\nRoss 154,9.693 LY,M3.5,2120976706,Ross 155,ROSS 154,R*ss 154\nRoss 248,10.32 LY,M5.5V,2129428738,Ross 249,ROSS 248,R*ss 248\nEpsilon Eridani,10.5 LY,K2V,931307088,Epsilon Eridanj,EPSILON ERIDANI,Eps*l*n Er*d*n*\n"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#hoist_mainstay" do
|
55
|
+
before(:each) do
|
56
|
+
@csv_pirate = CsvPirate.new({
|
57
|
+
:grub => GlowingGasBall,
|
58
|
+
:spyglasses => [:get_stars],
|
59
|
+
:chart => ["spec","csv","GlowingGasBall"],
|
60
|
+
:booty => [:name, :distance, :spectral_type, {:name => :hash}, {:name => :next}, {:name => :upcase}, :star_vowels ],
|
61
|
+
:chronometer => false,
|
62
|
+
:gibbet => "",
|
63
|
+
:aft => ".csv",
|
64
|
+
:swab => :none,
|
65
|
+
:mop => :clean,
|
66
|
+
:waggoner => 'data'
|
67
|
+
})
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should return an instance of String" do
|
71
|
+
@csv_pirate.hoist_mainstay.class.should == String
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should return the export as a string" do
|
75
|
+
@csv_pirate.hoist_mainstay.should == "Name,Distance,Spectral type,Name hash,Name next,Name upcase,Star vowels\nProxima Centauri,4.2 LY,M5.5Vc,-1176188012,Proxima Centaurj,PROXIMA CENTAURI,Pr*x*m* C*nt**r*\nRigil Kentaurus,4.3 LY,G2V,1916094624,Rigil Kentaurut,RIGIL KENTAURUS,R*g*l K*nt**r*s\nBarnard's Star,5.9 LY,M3.8V,1003964756,Barnard's Stas,BARNARD'S STAR,B*rn*rd's St*r\nWolf 359,7.7 LY,M5.8Vc,-1717989858,Wolf 360,WOLF 359,W*lf 359\nLalande 21185,8.26 LY,M2V,466625069,Lalande 21186,LALANDE 21185,L*l*nd* 21185\nLuyten 726-8A and B,8.73 LY,M5.5 de & M6 Ve,1260790153,Luyten 726-8A and C,LUYTEN 726-8A AND B,L*yt*n 726-8A *nd B\nSirius A and B,8.6 LY,A1Vm,1177502705,Sirius A and C,SIRIUS A AND B,S*r**s A *nd B\nRoss 154,9.693 LY,M3.5,2120976706,Ross 155,ROSS 154,R*ss 154\nRoss 248,10.32 LY,M5.5V,2129428738,Ross 249,ROSS 248,R*ss 248\nEpsilon Eridani,10.5 LY,K2V,931307088,Epsilon Eridanj,EPSILON ERIDANI,Eps*l*n Er*d*n*\n"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should store export in maroon instance variable" do
|
79
|
+
@csv_pirate.maroon.should == ""
|
80
|
+
@csv_pirate.hoist_mainstay
|
81
|
+
@csv_pirate.maroon.should == "Name,Distance,Spectral type,Name hash,Name next,Name upcase,Star vowels\nProxima Centauri,4.2 LY,M5.5Vc,-1176188012,Proxima Centaurj,PROXIMA CENTAURI,Pr*x*m* C*nt**r*\nRigil Kentaurus,4.3 LY,G2V,1916094624,Rigil Kentaurut,RIGIL KENTAURUS,R*g*l K*nt**r*s\nBarnard's Star,5.9 LY,M3.8V,1003964756,Barnard's Stas,BARNARD'S STAR,B*rn*rd's St*r\nWolf 359,7.7 LY,M5.8Vc,-1717989858,Wolf 360,WOLF 359,W*lf 359\nLalande 21185,8.26 LY,M2V,466625069,Lalande 21186,LALANDE 21185,L*l*nd* 21185\nLuyten 726-8A and B,8.73 LY,M5.5 de & M6 Ve,1260790153,Luyten 726-8A and C,LUYTEN 726-8A AND B,L*yt*n 726-8A *nd B\nSirius A and B,8.6 LY,A1Vm,1177502705,Sirius A and C,SIRIUS A AND B,S*r**s A *nd B\nRoss 154,9.693 LY,M3.5,2120976706,Ross 155,ROSS 154,R*ss 154\nRoss 248,10.32 LY,M5.5V,2129428738,Ross 249,ROSS 248,R*ss 248\nEpsilon Eridani,10.5 LY,K2V,931307088,Epsilon Eridanj,EPSILON ERIDANI,Eps*l*n Er*d*n*\n"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#old_csv_dump" do
|
86
|
+
|
87
|
+
before(:each) do
|
88
|
+
["1/1/1998","2/2/2002","1/2/2003","3/2/2001","2/1/2007"].map {|x| Date.parse(x)}.each do |date|
|
89
|
+
@csv_pirate = CsvPirate.new({
|
90
|
+
:grub => GlowingGasBall,
|
91
|
+
:spyglasses => [:get_stars],
|
92
|
+
:chart => ["spec","csv","GlowingGasBall","dumps"],
|
93
|
+
:booty => [:name, :distance, :spectral_type, {:name => :hash}, {:name => :next}, {:name => :upcase}, :star_vowels ],
|
94
|
+
:chronometer => date,
|
95
|
+
:swab => :none,
|
96
|
+
:mop => :clean
|
97
|
+
})
|
98
|
+
@csv_pirate.hoist_mainstay
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should find first (oldest) dump" do
|
103
|
+
@new_csv_pirate = CsvPirate.new({
|
104
|
+
:grub => GlowingGasBall,
|
105
|
+
:spyglasses => [:get_stars],
|
106
|
+
:chart => ["spec","csv","GlowingGasBall","dumps"],
|
107
|
+
:booty => [:name, :distance, :spectral_type, {:name => :hash}, {:name => :next}, {:name => :upcase}, :star_vowels ],
|
108
|
+
:chronometer => false,
|
109
|
+
:brigantine => :first,
|
110
|
+
:swab => :none,
|
111
|
+
:mop => :clean
|
112
|
+
})
|
113
|
+
@new_csv_pirate.brigantine.should == "spec/csv/GlowingGasBall/dumps/GlowingGasBall.19980101.export.csv"
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should find last (newest) dump" do
|
117
|
+
@new_csv_pirate = CsvPirate.new({
|
118
|
+
:grub => GlowingGasBall,
|
119
|
+
:spyglasses => [:get_stars],
|
120
|
+
:chart => ["spec","csv","GlowingGasBall","dumps"],
|
121
|
+
:booty => [:name, :distance, :spectral_type, {:name => :hash}, {:name => :next}, {:name => :upcase}, :star_vowels ],
|
122
|
+
:chronometer => false,
|
123
|
+
:brigantine => :last,
|
124
|
+
:swab => :none,
|
125
|
+
:mop => :clean
|
126
|
+
})
|
127
|
+
@new_csv_pirate.brigantine.should == "spec/csv/GlowingGasBall/dumps/GlowingGasBall.20070201.export.csv"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#to_memory" do
|
132
|
+
|
133
|
+
before(:each) do
|
134
|
+
["1/1/1998","2/2/2002","1/2/2003","3/2/2001","2/1/2007"].map {|x| Date.parse(x)}.each do |date|
|
135
|
+
@csv_pirate = CsvPirate.new({
|
136
|
+
:grub => GlowingGasBall,
|
137
|
+
:spyglasses => [:get_stars],
|
138
|
+
:chart => ["spec","csv","GlowingGasBall","dumps"],
|
139
|
+
:booty => [:name, :distance, :spectral_type, {:name => :hash}, {:name => :next}, {:name => :upcase}, :star_vowels ],
|
140
|
+
:chronometer => date,
|
141
|
+
:swab => :none,
|
142
|
+
:mop => :clean
|
143
|
+
})
|
144
|
+
@csv_pirate.hoist_mainstay
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should return an array of 10 grubs built from data in CSV" do
|
149
|
+
@new_csv_pirate = CsvPirate.new({
|
150
|
+
:grub => GlowingGasBall,
|
151
|
+
:spyglasses => [:get_stars],
|
152
|
+
:chart => ["spec","csv","GlowingGasBall","dumps"],
|
153
|
+
:booty => [:name, :distance, :spectral_type, {:name => :hash}, {:name => :next}, {:name => :upcase}, :star_vowels ],
|
154
|
+
:chronometer => false,
|
155
|
+
:brigantine => :last,
|
156
|
+
:swab => :none,
|
157
|
+
:mop => :clean
|
158
|
+
})
|
159
|
+
@new_csv_pirate.brigantine.should == "spec/csv/GlowingGasBall/dumps/GlowingGasBall.20070201.export.csv"
|
160
|
+
@new_csv_pirate.to_memory.class.should == Array
|
161
|
+
@new_csv_pirate.to_memory.length.should == 10
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe ":blackjack option" do
|
166
|
+
before(:each) do
|
167
|
+
@csv_pirate = CsvPirate.new({
|
168
|
+
:grub => GlowingGasBall,
|
169
|
+
:spyglasses => [:get_stars],
|
170
|
+
:chart => ["spec","csv","GlowingGasBall"],
|
171
|
+
:booty => [:name, :distance, :spectral_type, {:name => :hash}, {:name => :next}, {:name => :upcase}, :star_vowels ],
|
172
|
+
:chronometer => false,
|
173
|
+
:gibbet => "",
|
174
|
+
:aft => ".csv",
|
175
|
+
:swab => :none,
|
176
|
+
:mop => :clean,
|
177
|
+
:waggoner => 'data'
|
178
|
+
})
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should be {humanize => '_'} by default" do
|
182
|
+
@csv_pirate.blackjack.should == {:humanize => '_'}
|
183
|
+
@csv_pirate.hoist_mainstay
|
184
|
+
@csv_pirate.maroon.should == "Name,Distance,Spectral type,Name hash,Name next,Name upcase,Star vowels\nProxima Centauri,4.2 LY,M5.5Vc,-1176188012,Proxima Centaurj,PROXIMA CENTAURI,Pr*x*m* C*nt**r*\nRigil Kentaurus,4.3 LY,G2V,1916094624,Rigil Kentaurut,RIGIL KENTAURUS,R*g*l K*nt**r*s\nBarnard's Star,5.9 LY,M3.8V,1003964756,Barnard's Stas,BARNARD'S STAR,B*rn*rd's St*r\nWolf 359,7.7 LY,M5.8Vc,-1717989858,Wolf 360,WOLF 359,W*lf 359\nLalande 21185,8.26 LY,M2V,466625069,Lalande 21186,LALANDE 21185,L*l*nd* 21185\nLuyten 726-8A and B,8.73 LY,M5.5 de & M6 Ve,1260790153,Luyten 726-8A and C,LUYTEN 726-8A AND B,L*yt*n 726-8A *nd B\nSirius A and B,8.6 LY,A1Vm,1177502705,Sirius A and C,SIRIUS A AND B,S*r**s A *nd B\nRoss 154,9.693 LY,M3.5,2120976706,Ross 155,ROSS 154,R*ss 154\nRoss 248,10.32 LY,M5.5V,2129428738,Ross 249,ROSS 248,R*ss 248\nEpsilon Eridani,10.5 LY,K2V,931307088,Epsilon Eridanj,EPSILON ERIDANI,Eps*l*n Er*d*n*\n"
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should work as {:join => '_'}" do
|
188
|
+
@csv_pirate.blackjack = {:join => '_'}
|
189
|
+
@csv_pirate.blackjack.should == {:join => '_'}
|
190
|
+
@csv_pirate.hoist_mainstay
|
191
|
+
@csv_pirate.maroon.should == "name,distance,spectral_type,name_hash,name_next,name_upcase,star_vowels\nProxima Centauri,4.2 LY,M5.5Vc,-1176188012,Proxima Centaurj,PROXIMA CENTAURI,Pr*x*m* C*nt**r*\nRigil Kentaurus,4.3 LY,G2V,1916094624,Rigil Kentaurut,RIGIL KENTAURUS,R*g*l K*nt**r*s\nBarnard's Star,5.9 LY,M3.8V,1003964756,Barnard's Stas,BARNARD'S STAR,B*rn*rd's St*r\nWolf 359,7.7 LY,M5.8Vc,-1717989858,Wolf 360,WOLF 359,W*lf 359\nLalande 21185,8.26 LY,M2V,466625069,Lalande 21186,LALANDE 21185,L*l*nd* 21185\nLuyten 726-8A and B,8.73 LY,M5.5 de & M6 Ve,1260790153,Luyten 726-8A and C,LUYTEN 726-8A AND B,L*yt*n 726-8A *nd B\nSirius A and B,8.6 LY,A1Vm,1177502705,Sirius A and C,SIRIUS A AND B,S*r**s A *nd B\nRoss 154,9.693 LY,M3.5,2120976706,Ross 155,ROSS 154,R*ss 154\nRoss 248,10.32 LY,M5.5V,2129428738,Ross 249,ROSS 248,R*ss 248\nEpsilon Eridani,10.5 LY,K2V,931307088,Epsilon Eridanj,EPSILON ERIDANI,Eps*l*n Er*d*n*\n"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
7
195
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "PirateShip" do
|
4
|
+
describe "#walk_the_plank" do
|
5
|
+
before(:each) do
|
6
|
+
@csv_pirate = Star.walk_the_plank
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return a string" do
|
10
|
+
@csv_pirate.class.should == String
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#blindfold" do
|
15
|
+
before(:each) do
|
16
|
+
@csv_pirate = Star.blindfold
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return an instance of CsvPirate" do
|
20
|
+
@csv_pirate.class.should == CsvPirate
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#land_ho" do
|
25
|
+
before(:each) do
|
26
|
+
@csv_pirate = Star.land_ho
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return an instance of CsvPirate" do
|
30
|
+
@csv_pirate.class.should == CsvPirate
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#land_ho" do
|
35
|
+
before(:each) do
|
36
|
+
@csv_pirate = Star.land_ho
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return an instance of CsvPirate" do
|
40
|
+
@csv_pirate.class.should == CsvPirate
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#weigh_anchor" do
|
45
|
+
before(:each) do
|
46
|
+
@csv_pirate = Star.weigh_anchor({:chronometer => Date.parse("2/1/2007")})
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return an instance of CsvPirate" do
|
50
|
+
@csv_pirate.class.should == CsvPirate
|
51
|
+
@csv_pirate.chart.should == ["spec","csv","Star","dumps"]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#raise_anchor" do
|
56
|
+
before(:each) do
|
57
|
+
@csv_pirate = Star.weigh_anchor({:chronometer => Date.parse("3/29/2002")})
|
58
|
+
@csv_pirate = Star.weigh_anchor({:chronometer => Date.parse("6/14/2004")})
|
59
|
+
@csv_pirate = Star.weigh_anchor({:chronometer => Date.parse("12/25/1962")})
|
60
|
+
@csv_pirate = Star.raise_anchor()
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return an array of 10 grubs built from data in CSV" do
|
64
|
+
@csv_pirate.class.should == Array
|
65
|
+
@csv_pirate.length.should == 10
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
CHANGED
@@ -2,8 +2,11 @@ require 'spec'
|
|
2
2
|
|
3
3
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
4
|
|
5
|
-
require '
|
5
|
+
require 'init'
|
6
6
|
|
7
7
|
Spec::Runner.configure do |config|
|
8
8
|
|
9
9
|
end
|
10
|
+
|
11
|
+
# require all files inside spec_helpers
|
12
|
+
Dir[File.join(File.dirname(__FILE__), "spec_helpers/*.rb")].each { |file| require file }
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class GlowingGasBall
|
2
|
+
|
3
|
+
attr_accessor :name, :distance, :spectral_type
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
@name = args.first[:name]
|
7
|
+
@distance = args.first[:distance]
|
8
|
+
@spectral_type = args.first[:spectral_type]
|
9
|
+
end
|
10
|
+
|
11
|
+
def star_vowels
|
12
|
+
self.name.tr('aeiou', '*')
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.get_stars
|
16
|
+
[
|
17
|
+
GlowingGasBall.new(:name => "Proxima Centauri", :distance => "4.2 LY", :spectral_type => "M5.5Vc"),
|
18
|
+
GlowingGasBall.new(:name => "Rigil Kentaurus", :distance => "4.3 LY", :spectral_type => "G2V"),
|
19
|
+
GlowingGasBall.new(:name => "Barnard's Star", :distance => "5.9 LY", :spectral_type => "M3.8V"),
|
20
|
+
GlowingGasBall.new(:name => "Wolf 359", :distance => "7.7 LY", :spectral_type => "M5.8Vc"),
|
21
|
+
GlowingGasBall.new(:name => "Lalande 21185", :distance => "8.26 LY", :spectral_type => "M2V"),
|
22
|
+
GlowingGasBall.new(:name => "Luyten 726-8A and B", :distance => "8.73 LY", :spectral_type => "M5.5 de & M6 Ve"),
|
23
|
+
GlowingGasBall.new(:name => "Sirius A and B", :distance => "8.6 LY", :spectral_type => "A1Vm"),
|
24
|
+
GlowingGasBall.new(:name => "Ross 154", :distance => "9.693 LY", :spectral_type => "M3.5"),
|
25
|
+
GlowingGasBall.new(:name => "Ross 248", :distance => "10.32 LY", :spectral_type => "M5.5V"),
|
26
|
+
GlowingGasBall.new(:name => "Epsilon Eridani", :distance => "10.5 LY", :spectral_type => "K2V")
|
27
|
+
]
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Star < GlowingGasBall
|
2
|
+
|
3
|
+
extend NinthBit::PirateShip::ActMethods
|
4
|
+
has_csv_pirate_ship :booty => [ :name, :distance, :spectral_type, {:name => :hash}, {:name => :next}, {:name => :upcase}, :star_vowels ],
|
5
|
+
:spyglasses => [:get_stars],
|
6
|
+
:chart => ["spec","csv","Star"],
|
7
|
+
:chronometer => false,
|
8
|
+
:gibbet => "",
|
9
|
+
:aft => ".csv",
|
10
|
+
:swab => :none,
|
11
|
+
:mop => :clean,
|
12
|
+
:waggoner => 'data'
|
13
|
+
|
14
|
+
def self.get_stars
|
15
|
+
[
|
16
|
+
Star.new(:name => "Proxima Centauri", :distance => "4.2 LY", :spectral_type => "M5.5Vc"),
|
17
|
+
Star.new(:name => "Rigil Kentaurus", :distance => "4.3 LY", :spectral_type => "G2V"),
|
18
|
+
Star.new(:name => "Barnard's Star", :distance => "5.9 LY", :spectral_type => "M3.8V"),
|
19
|
+
Star.new(:name => "Wolf 359", :distance => "7.7 LY", :spectral_type => "M5.8Vc"),
|
20
|
+
Star.new(:name => "Lalande 21185", :distance => "8.26 LY", :spectral_type => "M2V"),
|
21
|
+
Star.new(:name => "Luyten 726-8A and B", :distance => "8.73 LY", :spectral_type => "M5.5 de & M6 Ve"),
|
22
|
+
Star.new(:name => "Sirius A and B", :distance => "8.6 LY", :spectral_type => "A1Vm"),
|
23
|
+
Star.new(:name => "Ross 154", :distance => "9.693 LY", :spectral_type => "M3.5"),
|
24
|
+
Star.new(:name => "Ross 248", :distance => "10.32 LY", :spectral_type => "M5.5V"),
|
25
|
+
Star.new(:name => "Epsilon Eridani", :distance => "10.5 LY", :spectral_type => "K2V")
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csv_pirate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Boling
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-15 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -23,7 +23,7 @@ dependencies:
|
|
23
23
|
version: "0"
|
24
24
|
version:
|
25
25
|
description: |-
|
26
|
-
CsvPirate is the easy way to create a CSV of essentially anything in
|
26
|
+
CsvPirate is the easy way to create a CSV of essentially anything in Ruby, in full pirate regalia.
|
27
27
|
It works better if you are wearing a tricorne!
|
28
28
|
email: peter.boling@gmail.com
|
29
29
|
executables: []
|
@@ -45,6 +45,12 @@ files:
|
|
45
45
|
- lib/csv_pirate.rb
|
46
46
|
- lib/ninth_bit/pirate_ship.rb
|
47
47
|
- rails/init.rb
|
48
|
+
- spec/csv_pirate_spec.rb
|
49
|
+
- spec/pirate_ship_spec.rb
|
50
|
+
- spec/spec.opts
|
51
|
+
- spec/spec_helper.rb
|
52
|
+
- spec/spec_helpers/glowing_gas_ball.rb
|
53
|
+
- spec/spec_helpers/star.rb
|
48
54
|
has_rdoc: true
|
49
55
|
homepage: http://github.com/pboling/csv_pirate
|
50
56
|
licenses: []
|
@@ -72,7 +78,10 @@ rubyforge_project:
|
|
72
78
|
rubygems_version: 1.3.5
|
73
79
|
signing_key:
|
74
80
|
specification_version: 3
|
75
|
-
summary: Easily create CSVs of any data that can be derived from
|
81
|
+
summary: Easily create CSVs of any data that can be derived from instance methods on your classes.
|
76
82
|
test_files:
|
77
83
|
- spec/csv_pirate_spec.rb
|
84
|
+
- spec/pirate_ship_spec.rb
|
78
85
|
- spec/spec_helper.rb
|
86
|
+
- spec/spec_helpers/glowing_gas_ball.rb
|
87
|
+
- spec/spec_helpers/star.rb
|