csv_pirate 3.4.4 → 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|