csv_pirate 2.1.2 → 2.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +16 -0
- data/README.rdoc +72 -39
- data/VERSION.yml +2 -2
- data/csv_pirate.gemspec +1 -1
- data/lib/csv_pirate.rb +88 -57
- data/lib/ninth_bit/pirate_ship.rb +40 -9
- metadata +1 -1
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
Version 2.4.1 2009-10-01
|
|
2
|
+
- Fixed critical typo
|
|
3
|
+
|
|
4
|
+
Version 2.4.0 2009-10-01
|
|
5
|
+
- Added blindfold to pirate_ship
|
|
6
|
+
- Added say_your_last_words to pirate_ship which is hash for send_data
|
|
7
|
+
|
|
8
|
+
Version 2.3.0 2009-10-01
|
|
9
|
+
- No longer requires rails at all
|
|
10
|
+
- hoise_mainstay now returns the exported text
|
|
11
|
+
- Better documentation in Readme and source
|
|
12
|
+
|
|
13
|
+
Version 2.2.0 2009-10-01
|
|
14
|
+
- Use FasterCSV for all backend work
|
|
15
|
+
- Added shrouds for creating tsv and psv files
|
|
16
|
+
|
|
1
17
|
Version 2.1.0 2009-10-01
|
|
2
18
|
- Added handling of nested methods!
|
|
3
19
|
|
data/README.rdoc
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
== CsvPirate
|
|
1
|
+
== CsvPirate
|
|
2
2
|
|
|
3
3
|
Easily create CSVs of any data that can be derived from your models.
|
|
4
4
|
|
|
@@ -9,22 +9,26 @@ CsvPirate only works for commissions of swag OR grub!
|
|
|
9
9
|
|
|
10
10
|
Initialize method (a.k.a new()) takes a hash of params:
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
12
|
+
# CsvPirate only works for commissions of swag OR grub!
|
|
13
|
+
# :swag the ARrr collection of swag to work on (optional)
|
|
14
|
+
# :grub the ARrr class that the spyglasses will be used on (optional)
|
|
15
|
+
# :spyglasses named scopes in your model that will refine the rows in the CSV according to conditions of the spyglasses,
|
|
16
|
+
# and order them according to the order of the spyglasses (optional)
|
|
17
|
+
# :booty booty (columns/methods) on your model that you want printed in the CSV, also used to create the figurehead (CSV header)
|
|
18
|
+
# :chart name of directory where you want to hide your loot
|
|
19
|
+
# :wagonner name of document where you will give detailed descriptions of the loot
|
|
20
|
+
# :aft filename extention ('.csv')
|
|
21
|
+
# :shrouds CSV column separator, default is ','. For tsv, tab-delimited, "\t"
|
|
22
|
+
# :chronometer keeps track of when you hunt for treasure
|
|
23
|
+
# :gibbet filename spacer after the date, and before the iterative counter/timestamp. MuST contain a '.'
|
|
24
|
+
# :swab can be :counter, :timestamp, or :none
|
|
25
|
+
# :counter - default, each successive run will create a new file using a counter
|
|
26
|
+
# :timestamp - each successive run will create a new file using a HHMMSS time stamp
|
|
27
|
+
# :none - no iterative file naming convention, just use waggoner and aft
|
|
28
|
+
# :mop can be :clean or :dirty (:overwrite or :append) (only has an effect if :swab is :none) since overwriting is irrelevant for a new file
|
|
29
|
+
# :clear - do not use :counter or :timestamp, and instead overwrite the file
|
|
30
|
+
# :dirty - do not use :counter, or :timestamp, or :overwrite. Just keep adding on.
|
|
31
|
+
# There are others too, check the source for a complete picture!
|
|
28
32
|
|
|
29
33
|
The create method has the same parameters, and actually creates the CSV.
|
|
30
34
|
|
|
@@ -89,7 +93,7 @@ Assuming a Make (as in manufacturers of automobiles) model like this:
|
|
|
89
93
|
:booty => [:id, :name]
|
|
90
94
|
end
|
|
91
95
|
|
|
92
|
-
To create a csv of the names and ids of makes with factories in germany:
|
|
96
|
+
To create a csv of the names and ids of makes with factories in germany and return the text of the export:
|
|
93
97
|
|
|
94
98
|
Make.walk_the_plank # Get it? HA! If you can't believe I wrote this whole thing JUST to be able to make jokes like that... check ma sources :)
|
|
95
99
|
|
|
@@ -104,9 +108,24 @@ All of those filename parts are customizable to a degree.
|
|
|
104
108
|
You can also customize the CSV, for example if you want to add a column to the csv:
|
|
105
109
|
|
|
106
110
|
Make.walk_the_plank({:booty => [:id, :name, :sales]})
|
|
111
|
+
|
|
112
|
+
Youw want a timestamp file counter instead of the integer default:
|
|
113
|
+
|
|
107
114
|
Make.walk_the_plank({:booty => [:id, :name, :sales], :spyglasses => [:all], :swab => :timestamp})
|
|
115
|
+
|
|
116
|
+
If you want to append each export to the end of the same file (on a per day basis):
|
|
117
|
+
|
|
108
118
|
Make.walk_the_plank({:booty => [:id, :name, :sales], :spyglasses => [:all], :swab => :none, :mop => :dirty})
|
|
109
119
|
|
|
120
|
+
If you want to restrict the csv to a particular set of named scopes:
|
|
121
|
+
|
|
122
|
+
Make.walk_the_plank({:booty => [:id, :name, :sales], :spyglasses => [:with_abs, :with_esc, :with_heated_seats]})
|
|
123
|
+
|
|
124
|
+
If you want to create a tsv (tab-delimited) or psv (pipe-delimited) instead of a csv:
|
|
125
|
+
|
|
126
|
+
Make.walk_the_plank({:booty => [:id, :name, :sales], :shrouds => '\t'})
|
|
127
|
+
Make.walk_the_plank({:booty => [:id, :name, :sales], :shrouds => '|'})
|
|
128
|
+
|
|
110
129
|
If you have a method in the Make class like this:
|
|
111
130
|
|
|
112
131
|
def to_slug
|
|
@@ -117,29 +136,14 @@ getting it in the CSV is easy peasy:
|
|
|
117
136
|
|
|
118
137
|
Make.walk_the_plank({:booty => [:id, :name, :to_slug]})
|
|
119
138
|
|
|
120
|
-
|
|
139
|
+
If you want to traverse Active Record Associations, or call a method on the return value of another method (unlimited nesting):
|
|
121
140
|
|
|
122
|
-
|
|
123
|
-
|
|
141
|
+
Make.walk_the_plank({:booty => [:id, :name, :to_slug, {:to_slug => :hash}]}) #will call .hash on the result of make.to_slug
|
|
142
|
+
Make.walk_the_plank({:booty => [:id, :name, :to_slug, {:to_slug => {:hash => :abs}}]}) #returns make.to_slug.hash.abs
|
|
124
143
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
# :spyglasses named scopes in your model that will refine the rows in the CSV according to conditions of the spyglasses,
|
|
129
|
-
# and order them according to the order of the spyglasses (optional)
|
|
130
|
-
# :booty booty (columns/methods) on your model that you want printed in the CSV, also used to create the figurehead (CSV header)
|
|
131
|
-
# :chart name of directory where you want to hide your loot
|
|
132
|
-
# :wagonner name of document where you will give detailed descriptions of the loot
|
|
133
|
-
# :aft filename extention ('.csv')
|
|
134
|
-
# :chronometer keeps track of when you hunt for treasure
|
|
135
|
-
# :gibbet filename spacer after the date, and before the iterative counter/timestamp. MuST contain a '.'
|
|
136
|
-
# :swab can be :counter, :timestamp, or :none
|
|
137
|
-
# :counter - default, each successive run will create a new file using a counter
|
|
138
|
-
# :timestamp - each successive run will create a new file using a HHMMSS time stamp
|
|
139
|
-
# :none - no iterative file naming convention, just use waggoner and aft
|
|
140
|
-
# :mop can be :clean or :dirty (:overwrite or :append) (only has an effect if :swab is :none) since overwriting is irrelevant for a new file
|
|
141
|
-
# :clear - do not use :counter or :timestamp, and instead overwrite the file
|
|
142
|
-
# :dirty - do not use :counter, or :timestamp, or :overwrite. Just keep adding on.
|
|
144
|
+
Add whatever methods you want to the :booty array. Write new methods, and add them! Make lots of glorious CSVs full of data to impress the pointy ones in the office.
|
|
145
|
+
|
|
146
|
+
You can also use the raw CsvPirate class itself directly wherever you want.
|
|
143
147
|
|
|
144
148
|
The following two sets of code are identical:
|
|
145
149
|
|
|
@@ -183,6 +187,35 @@ OR
|
|
|
183
187
|
|
|
184
188
|
csv_pirate = CsvPirate.new({:swag => users,:waggoner => 'inactive_users_not_logged_in',:booty => ["id","number","login","created_at"],:chart => 'log/csv/'})
|
|
185
189
|
|
|
190
|
+
|
|
191
|
+
== Downloading the CSV
|
|
192
|
+
|
|
193
|
+
You have the same Make class as above, and you have a MakeController:
|
|
194
|
+
|
|
195
|
+
class MakeController < ApplicationController
|
|
196
|
+
|
|
197
|
+
def download_csv
|
|
198
|
+
send_data Make.say_your_last_words # "utf-8" is default, and uses options from has_csv_pirate_ship
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# OR you can customize it just like walk_the_plank
|
|
202
|
+
|
|
203
|
+
def download_csv
|
|
204
|
+
send_data Make.say_your_last_words("iso-8859-1", {:booty => [:id, :name]})
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
Too easy? I wrote this for two reasons... pirate jokes and to make my life easier. If you need more flexibility then:
|
|
210
|
+
|
|
211
|
+
def download_csv
|
|
212
|
+
csv_pirate = Make.blindfold
|
|
213
|
+
send_data csv_pirate.maroon,
|
|
214
|
+
:type => 'text/csv; charset=iso-8859-1; header=present',
|
|
215
|
+
:disposition => "attachment; filename=#{csv_pirate.nocturnal}"
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
|
|
186
219
|
== Advanced Example with Nested Methods
|
|
187
220
|
|
|
188
221
|
You have a VehicleModel class and the same Make class as up above:
|
data/VERSION.yml
CHANGED
data/csv_pirate.gemspec
CHANGED
data/lib/csv_pirate.rb
CHANGED
|
@@ -32,7 +32,7 @@ class CsvPirate
|
|
|
32
32
|
attr_accessor :booty # methods / columns
|
|
33
33
|
|
|
34
34
|
attr_accessor :bury_treasure # should we store the csv data in an array for later inspection, or just write the CSV?
|
|
35
|
-
# default is
|
|
35
|
+
# default is false
|
|
36
36
|
# The array that gets built as we write the CSV... could be useful?
|
|
37
37
|
attr_accessor :buried_treasure # info array
|
|
38
38
|
|
|
@@ -40,41 +40,48 @@ class CsvPirate
|
|
|
40
40
|
|
|
41
41
|
attr_accessor :astrolabe # when true then read only CsvPirate instance for loading of CSVs
|
|
42
42
|
|
|
43
|
+
attr_accessor :shrouds # CSV column separator
|
|
44
|
+
|
|
43
45
|
attr_accessor :swab # default is :counter
|
|
44
46
|
attr_accessor :mop # default is :clean (only has an effect if :swab is :none) since overwriting is irrelevant for a new file
|
|
45
47
|
attr_accessor :swabbie # value of the counter / timestamp
|
|
48
|
+
attr_accessor :maroon # text of csv
|
|
49
|
+
attr_accessor :nocturnal # basename of the filepath (i.e. filename)
|
|
46
50
|
|
|
47
51
|
cattr_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
|
|
48
52
|
|
|
49
53
|
# CsvPirate only works for commissions of swag OR grub!
|
|
50
|
-
# :swag
|
|
51
|
-
# :grub
|
|
52
|
-
# :spyglasses
|
|
53
|
-
#
|
|
54
|
-
# :booty
|
|
55
|
-
# :chart
|
|
56
|
-
# :wagonner
|
|
57
|
-
# :aft
|
|
58
|
-
# :
|
|
59
|
-
# :
|
|
60
|
-
# :
|
|
54
|
+
# :swag the ARrr collection of swag to work on (optional)
|
|
55
|
+
# :grub the ARrr class that the spyglasses will be used on (optional)
|
|
56
|
+
# :spyglasses named scopes in your model that will refine the rows in the CSV according to conditions of the spyglasses,
|
|
57
|
+
# and order them according to the order of the spyglasses (optional)
|
|
58
|
+
# :booty booty (columns/methods) on your model that you want printed in the CSV, also used to create the figurehead (CSV header)
|
|
59
|
+
# :chart name of directory where you want to hide your loot
|
|
60
|
+
# :wagonner name of document where you will give detailed descriptions of the loot
|
|
61
|
+
# :aft filename extention ('.csv')
|
|
62
|
+
# :shrouds CSV column separator, default is ','. For tsv, tab-delimited, "\t"
|
|
63
|
+
# :chronometer keeps track of when you hunt for treasure
|
|
64
|
+
# :gibbet filename spacer after the date, and before the iterative counter/timestamp. MuST contain a '.'
|
|
65
|
+
# :swab can be :counter, :timestamp, or :none
|
|
61
66
|
# :counter - default, each successive run will create a new file using a counter
|
|
62
67
|
# :timestamp - each successive run will create a new file using a HHMMSS time stamp
|
|
63
68
|
# :none - no iterative file naming convention, just use waggoner and aft
|
|
64
|
-
# :mop
|
|
69
|
+
# :mop can be :clean or :dirty (:overwrite or :append) (only has an effect if :swab is :none) since overwriting is irrelevant for a new file
|
|
65
70
|
# :clear - do not use :counter or :timestamp, and instead overwrite the file
|
|
66
71
|
# :dirty - do not use :counter, or :timestamp, or :overwrite. Just keep adding on.
|
|
72
|
+
# :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)?
|
|
67
73
|
# See README for examples
|
|
68
74
|
|
|
69
75
|
def initialize(*args)
|
|
76
|
+
raise ArgumentError, "must provide required options" if args.blank?
|
|
70
77
|
|
|
71
78
|
@swag = args.first[:swag]
|
|
72
79
|
@grub = args.first[:grub]
|
|
73
80
|
|
|
74
81
|
# if they provide both
|
|
75
|
-
raise ArgumentError, "must provide either
|
|
82
|
+
raise ArgumentError, "must provide either :swag or :grub" if !args.first[:swag].blank? && !args.first[:grub].blank?
|
|
76
83
|
# if they provide neither
|
|
77
|
-
raise ArgumentError, "must provide either
|
|
84
|
+
raise ArgumentError, "must provide either :swag or :grub, not both" if args.first[:swag].blank? && args.first[:grub].blank?
|
|
78
85
|
|
|
79
86
|
@swab = args.first[:swab] || :counter
|
|
80
87
|
raise ArgumentError, ":swab is #{args.first[:swab].inspect}, but must be one of #{CsvPirate::BOOKIE.inspect}" unless CsvPirate::BOOKIE.include?(args.first[:swab])
|
|
@@ -96,19 +103,25 @@ class CsvPirate
|
|
|
96
103
|
@chronometer = args.first[:chronometer] || Date.today
|
|
97
104
|
|
|
98
105
|
@spyglasses = (args.first[:spyglasses] || [:all]) if self.grub
|
|
99
|
-
|
|
106
|
+
@shrouds = args.first[:shrouds] || ',' # for tsv, tab-delimited, "\t"
|
|
100
107
|
|
|
101
108
|
@astrolabe = args.first[:astrolabe] || false
|
|
102
109
|
|
|
103
|
-
@bury_treasure = args.first[:astrolabe] ||
|
|
110
|
+
@bury_treasure = args.first[:astrolabe] || false
|
|
104
111
|
@buried_treasure = []
|
|
105
112
|
|
|
106
113
|
# Initialize doesn't write anything to a CSV,
|
|
107
114
|
# but does create the traverse_board and opens the waggoner for reading / writing
|
|
108
115
|
Dir.mkdir(self.traverse_board) if !self.astrolabe && Dir.glob(self.traverse_board).empty?
|
|
109
116
|
|
|
117
|
+
# This will contain the text of the csv from this particular execution
|
|
118
|
+
@maroon = ""
|
|
119
|
+
|
|
110
120
|
# Once the traverse_board (dir) exists, then check if the rhumb_lines (file) already exists, and set our rhumb_lines counter
|
|
111
121
|
@swabbie = self.insult_swabbie
|
|
122
|
+
|
|
123
|
+
@nocturnal = File.basename(self.poop_deck)
|
|
124
|
+
|
|
112
125
|
# Then open the rhumb_lines
|
|
113
126
|
self.rhumb_lines = File.open(File.expand_path(self.poop_deck),self.astrolabe ? "r" : "a")
|
|
114
127
|
end
|
|
@@ -122,6 +135,7 @@ class CsvPirate
|
|
|
122
135
|
:waggoner => args.first[:waggoner],
|
|
123
136
|
:swag => args.first[:swag],
|
|
124
137
|
:swab => args.first[:swab],
|
|
138
|
+
:shrouds => args.first[:shrouds],
|
|
125
139
|
:mop => args.first[:mop],
|
|
126
140
|
:grub => args.first[:grub],
|
|
127
141
|
:spyglasses => args.first[:spyglasses],
|
|
@@ -178,40 +192,49 @@ class CsvPirate
|
|
|
178
192
|
|
|
179
193
|
self.swab_poop_deck
|
|
180
194
|
|
|
181
|
-
self.
|
|
182
|
-
|
|
183
|
-
self.bury_treasure ? self.buried_treasure = self.dead_mans_chest : self.dead_mans_chest
|
|
195
|
+
self.dead_mans_chest
|
|
184
196
|
|
|
185
197
|
self.rhumb_lines.close
|
|
186
198
|
|
|
187
199
|
self.jolly_roger if CsvPirate.parlay > 1
|
|
188
200
|
|
|
189
|
-
# returns the
|
|
190
|
-
return self.
|
|
201
|
+
# returns the text of this CSV export
|
|
202
|
+
return self.maroon
|
|
191
203
|
end
|
|
192
204
|
|
|
193
205
|
def dead_mans_chest
|
|
194
|
-
self.
|
|
195
|
-
self.
|
|
206
|
+
self.maroon = FasterCSV.generate(:col_sep => self.shrouds) do |csv|
|
|
207
|
+
self.sounding(csv)
|
|
196
208
|
end
|
|
209
|
+
self.scrivener(self.maroon)
|
|
210
|
+
self.maroon
|
|
197
211
|
end
|
|
198
212
|
|
|
199
213
|
def jolly_roger
|
|
200
|
-
if self.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
214
|
+
if self.bury_treasure
|
|
215
|
+
if self.buried_treasure.is_a?(Array)
|
|
216
|
+
puts "Found #{self.buried_treasure.length} deniers buried here: '#{self.poop_deck}'" if CsvPirate.parlay > 1
|
|
217
|
+
puts "You must weigh_anchor to review your plunder!" if CsvPirate.parlay > 1
|
|
218
|
+
else
|
|
219
|
+
puts "Failed to locate treasure" if CsvPirate.parlay > 1
|
|
220
|
+
end
|
|
205
221
|
end
|
|
206
222
|
end
|
|
207
223
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
self.
|
|
224
|
+
def sounding(csv)
|
|
225
|
+
# create the header of the CSV (column/method names)
|
|
226
|
+
csv << self.booty
|
|
227
|
+
# create the data for the csv
|
|
228
|
+
self.dig_for_treasure do |treasure|
|
|
229
|
+
moidore = treasure.map {|x| "#{x}"}
|
|
230
|
+
csv << moidore # |x| marks the spot!
|
|
231
|
+
self.buried_treasure << moidore if self.bury_treasure
|
|
232
|
+
end
|
|
211
233
|
end
|
|
212
|
-
|
|
234
|
+
|
|
213
235
|
def traverse_board
|
|
214
|
-
|
|
236
|
+
#If we have rails environment then we use rails root, otherwise self.chart stands on its own as a relative path
|
|
237
|
+
"#{defined?(Rails) ? Rails.root + '/' : defined?(RAILS_ROOT) ? RAILS_ROOT + '/' : ''}#{self.chart}"
|
|
215
238
|
end
|
|
216
239
|
|
|
217
240
|
def sand_glass
|
|
@@ -223,14 +246,38 @@ class CsvPirate
|
|
|
223
246
|
"#{self.analemma}#{self.swabbie}#{self.aft}"
|
|
224
247
|
end
|
|
225
248
|
|
|
249
|
+
def merchantman
|
|
250
|
+
"#{self.waggoner}#{self.sand_glass}#{self.gibbet}"
|
|
251
|
+
end
|
|
252
|
+
|
|
226
253
|
def analemma
|
|
227
|
-
"#{self.traverse_board}#{self.
|
|
254
|
+
"#{self.traverse_board}#{self.merchantman}"
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Swabs the poop_deck if the mop is clean. (!)
|
|
258
|
+
def swab_poop_deck
|
|
259
|
+
self.rhumb_lines.truncate(0) if self.swab == :none && self.mop == :clean && File.size(self.poop_deck) > 0
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# Must be done on order to rummage through the loot found by the pirate ship
|
|
263
|
+
def weigh_anchor
|
|
264
|
+
CsvPirate.rinse(self.poop_deck)
|
|
228
265
|
end
|
|
229
266
|
|
|
267
|
+
# Sink your own ship! Or run a block of code on each row of the current CSV
|
|
268
|
+
def scuttle(&block)
|
|
269
|
+
return false unless block_given?
|
|
270
|
+
CsvPirate.broadside(self.poop_deck) do |careen|
|
|
271
|
+
yield careen
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
protected
|
|
276
|
+
|
|
230
277
|
def lantern
|
|
231
278
|
"#{self.analemma}.*"
|
|
232
279
|
end
|
|
233
|
-
|
|
280
|
+
|
|
234
281
|
def filibuster(flotsam)
|
|
235
282
|
base = File.basename(flotsam, self.aft)
|
|
236
283
|
index = base.rindex('.')
|
|
@@ -238,7 +285,7 @@ class CsvPirate
|
|
|
238
285
|
# Ensure numbers
|
|
239
286
|
counter = tail.nil? ? 0 : tail[/\d*/].to_i
|
|
240
287
|
end
|
|
241
|
-
|
|
288
|
+
|
|
242
289
|
def boatswain
|
|
243
290
|
return self.swabbie unless self.swabbie.nil?
|
|
244
291
|
counter = 0
|
|
@@ -249,17 +296,12 @@ class CsvPirate
|
|
|
249
296
|
highval = ((highval <=> counter) == 1) ? highval : counter
|
|
250
297
|
counter = 0
|
|
251
298
|
end
|
|
252
|
-
|
|
299
|
+
".#{highval + 1}"
|
|
253
300
|
end
|
|
254
301
|
|
|
255
302
|
def coxswain
|
|
256
303
|
return self.swabbie unless self.swabbie.nil?
|
|
257
|
-
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
# Swabs the poop_deck if the mop is clean. (!)
|
|
261
|
-
def swab_poop_deck
|
|
262
|
-
self.rhumb_lines.truncate(0) if self.swab == :none && self.mop == :clean && File.size(self.poop_deck) > 0
|
|
304
|
+
".#{Time.now.strftime("%I%M%S")}"
|
|
263
305
|
end
|
|
264
306
|
|
|
265
307
|
# Sets the swabby file counter
|
|
@@ -270,22 +312,11 @@ class CsvPirate
|
|
|
270
312
|
when :timestamp
|
|
271
313
|
self.coxswain
|
|
272
314
|
else
|
|
273
|
-
|
|
315
|
+
""
|
|
274
316
|
end
|
|
275
317
|
end
|
|
276
318
|
|
|
277
|
-
|
|
278
|
-
def weigh_anchor
|
|
279
|
-
CsvPirate.rinse(self.poop_deck)
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
# Sink your own ship! Or run a block of code on each row of the current CSV
|
|
283
|
-
def scuttle(&block)
|
|
284
|
-
return false unless block_given?
|
|
285
|
-
CsvPirate.broadside(self.poop_deck) do |careen|
|
|
286
|
-
yield careen
|
|
287
|
-
end
|
|
288
|
-
end
|
|
319
|
+
public
|
|
289
320
|
|
|
290
321
|
########################################
|
|
291
322
|
############ CLASS METHODS #############
|
|
@@ -4,9 +4,8 @@ module NinthBit
|
|
|
4
4
|
module ActMethods
|
|
5
5
|
#coding tyle is adopted from attachment_fu
|
|
6
6
|
def has_csv_pirate_ship(options = {})
|
|
7
|
-
if options.blank?
|
|
8
|
-
|
|
9
|
-
end
|
|
7
|
+
raise ArgumentError, "must provide required options" if options.blank?
|
|
8
|
+
|
|
10
9
|
options[:chart] ||= 'log/'
|
|
11
10
|
options[:aft] ||= '.csv'
|
|
12
11
|
options[:gibbet] ||= '.export'
|
|
@@ -16,6 +15,7 @@ module NinthBit
|
|
|
16
15
|
options[:swag] ||= nil
|
|
17
16
|
options[:swab] ||= :counter
|
|
18
17
|
options[:mop] ||= :clean
|
|
18
|
+
options[:shrouds] ||= ','
|
|
19
19
|
options[:grub] ||= self if options[:swag].nil?
|
|
20
20
|
options[:spyglasses] ||= [:all]
|
|
21
21
|
options[:booty] ||= self.column_names
|
|
@@ -23,9 +23,9 @@ module NinthBit
|
|
|
23
23
|
options[:parlay] ||= 1
|
|
24
24
|
|
|
25
25
|
# if they provide both
|
|
26
|
-
raise ArgumentError, "must provide either
|
|
26
|
+
raise ArgumentError, "must provide either :swag or :grub" if !options[:swag].blank? && !options[:grub].blank?
|
|
27
27
|
# if they provide neither
|
|
28
|
-
raise ArgumentError, "must provide either
|
|
28
|
+
raise ArgumentError, "must provide either :swag or :grub, not both" if options[:swag].blank? && options[:grub].blank?
|
|
29
29
|
raise ArgumentError, ":swab is #{options[:swab].inspect}, but must be one of #{CsvPirate::BOOKIE.inspect}" unless CsvPirate::BOOKIE.include?(options[:swab])
|
|
30
30
|
raise ArgumentError, ":mop is #{options[:mop].inspect}, but must be one of #{CsvPirate::MOP_HEADS.inspect}" unless CsvPirate::MOP_HEADS.include?(options[:mop])
|
|
31
31
|
raise ArgumentError, ":gibbet is #{options[:gibbet].inspect}, and does not contain a '.' character, which is required for iterative filenames" if options[:gibbet].nil? || !options[:gibbet].include?('.')
|
|
@@ -45,10 +45,41 @@ module NinthBit
|
|
|
45
45
|
base.class_inheritable_accessor :piratey_options
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
# intended for use with send_data for downloading the text of the csv:
|
|
49
|
+
# send_data Make.say_your_last_words
|
|
50
|
+
def say_your_last_words(charset = 'utf-8', args = {})
|
|
51
|
+
csv_pirate = self.blindfold(args)
|
|
52
|
+
return [ csv_pirate.maroon,
|
|
53
|
+
{:type => "text/csv; charset=#{charset}; header=present"},
|
|
54
|
+
{:disposition => "attachment; filename=#{csv_pirate.nocturnal}"} ]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
#returns the text of the csv export (not the file - this is important if you are appending)
|
|
58
|
+
# warning if using from console: if you are exporting a large csv this will all print in your console.
|
|
59
|
+
# intended for use with send_data for downloading the text of the csv:
|
|
60
|
+
# send_data Make.walk_the_plank,
|
|
61
|
+
# :type => 'text/csv; charset=iso-8859-1; header=present',
|
|
62
|
+
# :disposition => "attachment; filename=Data.csv"
|
|
48
63
|
def walk_the_plank(args = {})
|
|
64
|
+
csv_pirate = CsvPirate.new(self.piratey_args(args))
|
|
65
|
+
csv_pirate.hoist_mainstay()
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
#returns the csv_pirate object so you have access to everything
|
|
69
|
+
# If using in a download action it might look like this:
|
|
70
|
+
# csv_pirate = Make.blindfold
|
|
71
|
+
# send_data csv_pirate.maroon,
|
|
72
|
+
# :type => 'text/csv; charset=iso-8859-1; header=present',
|
|
73
|
+
# :disposition => "attachment; filename=#{csv_pirate.nocturnal}"
|
|
74
|
+
def blindfold(args = {})
|
|
49
75
|
CsvPirate.parlay = args[:parlay] || self.piratey_options[:parlay]
|
|
50
|
-
CsvPirate.create(
|
|
51
|
-
|
|
76
|
+
CsvPirate.create(self.piratey_args(args))
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
protected
|
|
80
|
+
|
|
81
|
+
def piratey_args(args = {})
|
|
82
|
+
{ :chart => args[:chart] || self.piratey_options[:chart],
|
|
52
83
|
:aft => args[:aft] || self.piratey_options[:aft],
|
|
53
84
|
:gibbet => args[:gibbet] || self.piratey_options[:gibbet],
|
|
54
85
|
:chronometer => args[:chronometer] || Date.today,
|
|
@@ -56,11 +87,11 @@ module NinthBit
|
|
|
56
87
|
:swag => args[:swag] || self.piratey_options[:swag],
|
|
57
88
|
:swab => args[:swab] || self.piratey_options[:swab],
|
|
58
89
|
:mop => args[:mop] || self.piratey_options[:mop],
|
|
90
|
+
:shrouds => args[:swab] || self.piratey_options[:shrouds],
|
|
59
91
|
:grub => args[:grub] || self.piratey_options[:grub],
|
|
60
92
|
:spyglasses => args[:spyglasses] || self.piratey_options[:spyglasses],
|
|
61
93
|
:booty => args[:booty] || self.piratey_options[:booty],
|
|
62
|
-
:bury_treasure => args[:bury_treasure] || self.piratey_options[:bury_treasure]
|
|
63
|
-
})
|
|
94
|
+
:bury_treasure => args[:bury_treasure] || self.piratey_options[:bury_treasure] }
|
|
64
95
|
end
|
|
65
96
|
|
|
66
97
|
end
|