csv_pirate 2.4.4 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ Version 2.5.1 2009-10-01
2
+ - Fixed bug with handling of Rails.root & RAILS_ROOT
3
+
4
+ Version 2.5.0 2009-10-01
5
+ - Added northwest_passage to create all the directories in :chart
6
+
1
7
  Version 2.4.1 2009-10-01
2
8
  - Fixed critical typo
3
9
 
data/README.rdoc CHANGED
@@ -5,30 +5,33 @@ Easily create CSVs of any data that can be derived from your models.
5
5
  CsvPirate is the easy way to create a CSV of essentially anything in Rails, in full pirate regalia.
6
6
  It works better if you are wearing a tricorne!
7
7
 
8
+ My goal is to have it do EVERYTHING it possibly can for me, since almost every project I do needs CSV exports.
9
+
8
10
  CsvPirate only works for commissions of swag OR grub!
9
11
 
10
12
  Initialize method (a.k.a new()) takes a hash of params:
11
13
 
12
14
  # 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
15
+ # :swag the ARrr collection of swag to work on (optional)
16
+ # :grub the ARrr class that the spyglasses will be used on (optional)
17
+ # :spyglasses named scopes in your model that will refine the rows in the CSV according to conditions of the spyglasses,
18
+ # and order them according to the order of the spyglasses (optional)
19
+ # :booty booty (columns/methods) on your model that you want printed in the CSV, also used to create the figurehead (CSV header)
20
+ # :chart array of directory names (relative to rails root if using rails) which will be the filepath where you want to hide your loot
21
+ # :wagonner name of document where you will give detailed descriptions of the loot
22
+ # :aft filename extention ('.csv')
23
+ # :shrouds CSV column separator, default is ','. For tsv, tab-delimited, "\t"
24
+ # :chronometer keeps track of when you hunt for treasure
25
+ # :gibbet filename spacer after the date, and before the iterative counter/timestamp. MuST contain a '.'
26
+ # :swab can be :counter, :timestamp, or :none
25
27
  # :counter - default, each successive run will create a new file using a counter
26
28
  # :timestamp - each successive run will create a new file using a HHMMSS time stamp
27
29
  # :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
30
+ # :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
31
  # :clear - do not use :counter or :timestamp, and instead overwrite the file
30
32
  # :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!
33
+ # :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
+ # check the source to see if there anything else hiding in there!
32
35
 
33
36
  The create method has the same parameters, and actually creates the CSV.
34
37
 
@@ -71,6 +74,13 @@ Plugin using Git:
71
74
  ruby script/plugin install git://github.com/pboling/csv_pirate.git
72
75
 
73
76
 
77
+ == Upgrading
78
+
79
+ In older versions :chart was a string which indicated where you wanted to hide the loot (write the csv file)
80
+ Now it must be an array of directory names. So if you want your loot in "log/csv/pirates/model_name", then chart is:
81
+ ['log','csv','pirates','model_name']
82
+ CsvPirate ensures that whatever you choose as your chart exists in the filesystem, and creates the directories if need be.
83
+
74
84
  == Example & Usage
75
85
 
76
86
  Assuming a Make (as in manufacturers of automobiles) model like this:
@@ -152,7 +162,7 @@ The following two sets of code are identical:
152
162
  :spyglasses => [:active,:logged_in],
153
163
  :waggoner => 'active_users_logged_in',
154
164
  :booty => ["id","number","login","created_at"],
155
- :chart => 'log/csv/'
165
+ :chart => ['log','csv']
156
166
  })
157
167
  csv_pirate.hoist_mainstay() # creates CSV file and writes out the rows
158
168
 
@@ -161,7 +171,7 @@ The following two sets of code are identical:
161
171
  :spyglasses => [:active,:logged_in],
162
172
  :waggoner => 'active_users_logged_in',
163
173
  :booty => ["id","number","login","created_at"],
164
- :chart => 'log/csv/'
174
+ :chart => ['log','csv']
165
175
  })# creates CSV file and writes out the rows
166
176
 
167
177
  Another example using swag instead of grub:
@@ -171,7 +181,7 @@ Another example using swag instead of grub:
171
181
  :swag => users,
172
182
  :waggoner => 'inactive_users_not_logged_in',
173
183
  :booty => ["id","number","login","created_at"],
174
- :chart => 'log/csv/'
184
+ :chart => ['log','csv']
175
185
  })
176
186
  csv_pirate.hoist_mainstay()
177
187
 
@@ -181,11 +191,11 @@ Then if you want to get your hands on the loot immediately:
181
191
 
182
192
  For those who can't help but copy/paste into console and then edit:
183
193
 
184
- csv_pirate = CsvPirate.new({:grub => User,:spyglasses => [:active,:logged_in],:waggoner => 'active_users_logged_in',:booty => ["id","number","login","created_at"],:chart => 'log/csv/'})
194
+ csv_pirate = CsvPirate.new({:grub => User,:spyglasses => [:active,:logged_in],:waggoner => 'active_users_logged_in',:booty => ["id","number","login","created_at"],:chart => ['log','csv']})
185
195
 
186
196
  OR
187
197
 
188
- csv_pirate = CsvPirate.new({:swag => users,:waggoner => 'inactive_users_not_logged_in',:booty => ["id","number","login","created_at"],:chart => 'log/csv/'})
198
+ csv_pirate = CsvPirate.new({:swag => users,:waggoner => 'inactive_users_not_logged_in',:booty => ["id","number","login","created_at"],:chart => ['log','csv']})
189
199
 
190
200
 
191
201
  == Downloading the CSV
@@ -257,7 +267,7 @@ You have a VehicleModel class and the same Make class as up above:
257
267
 
258
268
  Then to create the CSV:
259
269
 
260
- a = VehicleModel.walk_the_plank
270
+ a = VehicleModel.blindfold
261
271
 
262
272
  Then check the output from the console:
263
273
 
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 4
3
- :major: 2
4
- :minor: 4
2
+ :patch: 0
3
+ :major: 3
4
+ :minor: 1
data/csv_pirate.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{csv_pirate}
8
- s.version = "2.4.4"
8
+ s.version = "3.1.0"
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"]
data/lib/csv_pirate.rb CHANGED
@@ -15,7 +15,7 @@ class CsvPirate
15
15
  MOP_HEADS = [:clean, :dirty]
16
16
 
17
17
  attr_accessor :waggoner #filename
18
- attr_accessor :chart #directory, default is ('log/')
18
+ attr_accessor :chart #directory, default is (['log','csv'])
19
19
  attr_accessor :aft #extension, default is ('.csv')
20
20
  attr_accessor :gibbet #part of the filename after waggoner and date, before swabbie and aft
21
21
  attr_accessor :chronometer
@@ -56,7 +56,7 @@ class CsvPirate
56
56
  # :spyglasses named scopes in your model that will refine the rows in the CSV according to conditions of the spyglasses,
57
57
  # and order them according to the order of the spyglasses (optional)
58
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
59
+ # :chart array of directory names (relative to rails root if using rails) which will be the filepath where you want to hide your loot
60
60
  # :wagonner name of document where you will give detailed descriptions of the loot
61
61
  # :aft filename extention ('.csv')
62
62
  # :shrouds CSV column separator, default is ','. For tsv, tab-delimited, "\t"
@@ -92,13 +92,15 @@ class CsvPirate
92
92
  @gibbet = args.first[:gibbet] || '.export'
93
93
  raise ArgumentError, ":gibbet is #{args.first[:gibbet].inspect}, and does not contain a '.' character, which is required for iterative filenames" if args.first[:gibbet].nil? || !args.first[:gibbet].include?('.')
94
94
 
95
- @waggoner = args.first[:waggoner] || "#{self.grub}"
95
+ @waggoner = args.first[:waggoner] || "#{self.grub || self.swag}"
96
96
  raise ArgumentError, ":waggoner is #{args.first[:waggoner].inspect}, and must be a string at least one character long" if args.first[:waggoner].nil? || args.first[:waggoner].length < 1
97
97
 
98
98
  @booty = args.first[:booty] || []
99
- raise ArgumentError, ":booty is #{args.first[:booty].inspect}, and must be an array of methods to call on a class for CSV data" if args.first[:booty].nil? || args.first[:booty].empty?
99
+ raise ArgumentError, ":booty is #{args.first[:booty].inspect}, and must be an array of methods to call on a class for CSV data" if args.first[:booty].nil? || !args.first[:booty].is_a?(Array) || args.first[:booty].empty?
100
+
101
+ @chart = args.first[:chart] || ['log','csv']
102
+ raise ArgumentError, ":chart is #{args.first[:chart].inspect}, and must be an array of directory names, which will become the filepath for the csv file" if args.first[:chart].nil? || !args.first[:chart].is_a?(Array) || args.first[:booty].empty?
100
103
 
101
- @chart = args.first[:chart] || 'log/'
102
104
  @aft = args.first[:aft] || '.csv'
103
105
  @chronometer = args.first[:chronometer] || Date.today
104
106
 
@@ -112,7 +114,7 @@ class CsvPirate
112
114
 
113
115
  # Initialize doesn't write anything to a CSV,
114
116
  # but does create the traverse_board and opens the waggoner for reading / writing
115
- Dir.mkdir(self.traverse_board) if !self.astrolabe && Dir.glob(self.traverse_board).empty?
117
+ self.northwest_passage unless self.astrolabe
116
118
 
117
119
  # This will contain the text of the csv from this particular execution
118
120
  @maroon = ""
@@ -232,28 +234,11 @@ class CsvPirate
232
234
  end
233
235
  end
234
236
 
235
- def traverse_board
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}"
238
- end
239
-
240
- def sand_glass
241
- "#{self.chronometer.respond_to?(:strftime) ? '.' + self.chronometer.strftime("%Y%m%d") : ''}"
242
- end
243
-
244
237
  #complete file path
245
238
  def poop_deck
246
239
  "#{self.analemma}#{self.swabbie}#{self.aft}"
247
240
  end
248
241
 
249
- def merchantman
250
- "#{self.waggoner}#{self.sand_glass}#{self.gibbet}"
251
- end
252
-
253
- def analemma
254
- "#{self.traverse_board}#{self.merchantman}"
255
- end
256
-
257
242
  # Swabs the poop_deck if the mop is clean. (!)
258
243
  def swab_poop_deck
259
244
  self.rhumb_lines.truncate(0) if self.swab == :none && self.mop == :clean && File.size(self.poop_deck) > 0
@@ -274,6 +259,34 @@ class CsvPirate
274
259
 
275
260
  protected
276
261
 
262
+ def traverse_board
263
+ #If we have rails environment then we use rails root, otherwise self.chart stands on its own as a relative path
264
+ "#{self.north_pole}#{self.chart.join('/')}/"
265
+ end
266
+
267
+ def sand_glass
268
+ "#{self.chronometer.respond_to?(:strftime) ? '.' + self.chronometer.strftime("%Y%m%d") : ''}"
269
+ end
270
+
271
+ def merchantman
272
+ "#{self.waggoner}#{self.sand_glass}#{self.gibbet}"
273
+ end
274
+
275
+ def analemma
276
+ "#{self.traverse_board}#{self.merchantman}"
277
+ end
278
+
279
+ def north_pole
280
+ "#{defined?(Rails) ? "#{Rails.root}/" : defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/" : ''}"
281
+ end
282
+
283
+ def northwest_passage
284
+ self.chart.length.times do |i|
285
+ north_star = self.north_pole + self.chart[0..i].join('/')
286
+ Dir.mkdir(north_star) if Dir.glob(north_star).empty?
287
+ end
288
+ end
289
+
277
290
  def lantern
278
291
  "#{self.analemma}.*"
279
292
  end
@@ -372,7 +385,7 @@ class CsvPirate
372
385
  # :spyglasses => is the column to load ("find_by_#{booty}") the ARrr object for each row on the first CSV
373
386
  # (swag OR spyglasses can be specified, but code defers to swag if provided)
374
387
  # :waggoner => where the capn's loot was stashed (filename)
375
- # :chart => directory where capn's waggoner is located
388
+ # :chart => array of directory names where capn's waggoner is located
376
389
  # :astrolabe => true (file is opened at top of file in read only mode when true)
377
390
  # The first_mate hash is:
378
391
  # :grub => is the class on which to make booty [method] calls, or
@@ -382,23 +395,23 @@ class CsvPirate
382
395
  # :spyglasses => is the column to load ("find_by_#{booty}") the ARrr object for each row on the second CSV (if grub is a class)
383
396
  # :booty => is the methods to call on the ARrr object for each row on the second CSV
384
397
  # :waggoner => where to stash the first mate's loot (filename)
385
- # :chart => directory where first mate's waggoner is located
398
+ # :chart => array of directory names where first mate's waggoner is located
386
399
  # :astrolabe => false (false is the default for astrolabe, so we could leave it off the first_mate)
387
400
  #
388
401
  # Example:
389
- # capn = {:grub => User,:spyglasses => [:inactive],:booty => ['id','login','status'],:waggoner => 'orig',:chart => 'log/csv/',:astrolabe => false}
402
+ # capn = {:grub => User,:spyglasses => [:inactive],:booty => ['id','login','status'],:waggoner => 'orig',:chart => ['log','csv'],:astrolabe => false}
390
403
  # make_orig = CsvPirate.new(capn)
391
404
  # make_orig.hoist_mainstay
392
405
  # make_orig.weigh_anchor
393
406
  #
394
- # first_mate = {:grub => 'account',:booty => ["id","number","name","created_at"],:waggoner => 'fake',:chart => 'log/csv/'}
407
+ # first_mate = {:grub => 'account',:booty => ["id","number","name","created_at"],:waggoner => 'fake',:chart => ['log','csv']}
395
408
  # OR
396
409
  # # for same class, we re-use the object loaded from first CSV and make the booty [method] calls on it
397
- # first_mate = {:grub => User,:booty => ["id","login","visits_count"],:waggoner => 'fake',:chart => 'log/csv/'}
410
+ # first_mate = {:grub => User,:booty => ["id","login","visits_count"],:waggoner => 'fake',:chart => ['log','csv']}
398
411
  # OR
399
- # first_mate = {:grub => Account,:spyglasses => 'id',:swag=>'user_id',:booty => ["id","name","number"],:waggoner => 'fake',:chart => 'log/csv/'}
412
+ # first_mate = {:grub => Account,:spyglasses => 'id',:swag=>'user_id',:booty => ["id","name","number"],:waggoner => 'fake',:chart => ['log','csv']}
400
413
  # AND
401
- # capn = {:grub => User,:spyglasses => 'login',:swag => 1,:waggoner => 'orig',:chart => 'log/csv/',:astrolabe => true}
414
+ # capn = {:grub => User,:spyglasses => 'login',:swag => 1,:waggoner => 'orig',:chart => ['log','csv'],:astrolabe => true}
402
415
  # after_mutiny = CsvPirate.mutiny(capn, first_mate)
403
416
  #
404
417
  def self.mutiny(capn, first_mate)
@@ -6,7 +6,7 @@ module NinthBit
6
6
  def has_csv_pirate_ship(options = {})
7
7
  raise ArgumentError, "must provide required options" if options.blank?
8
8
 
9
- options[:chart] ||= 'log/'
9
+ options[:chart] ||= ['log','csv']
10
10
  options[:aft] ||= '.csv'
11
11
  options[:gibbet] ||= '.export'
12
12
  #Needs to be defined at runtime, doesn't make sense here
@@ -30,7 +30,8 @@ module NinthBit
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?('.')
32
32
  raise ArgumentError, ":waggoner is #{options[:waggoner].inspect}, and must be a string at least one character long" if options[:waggoner].nil? || options[:waggoner].length < 1
33
- raise ArgumentError, ":booty is #{options[:booty].inspect}, and must be an array of methods to call on a class for CSV data" if options[:booty].nil? || options[:booty].empty?
33
+ raise ArgumentError, ":booty is #{options[:booty].inspect}, and must be an array of methods to call on a class for CSV data" if options[:booty].nil? || !options[:booty].is_a?(Array) || options[:booty].empty?
34
+ raise ArgumentError, ":chart is #{options[:chart].inspect}, and must be an array of directory names, which will become the filepath for the csv file" if options[:chart].nil? || !options[:chart].is_a?(Array) || options[:chart].empty?
34
35
 
35
36
  extend ClassMethods unless (class << self; included_modules; end).include?(ClassMethods)
36
37
 
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: 2.4.4
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Boling