csv_pirate 3.1.1 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,16 @@
1
+ Version 3.3.0 2009-10-05
2
+ - Fixed ArgumentError bugs in Initializer and has_csv_pirate_ship
3
+ - Fixed typo in piratey_args
4
+ - Major enhancements to documentation
5
+ - Now complete control over filename is possible
6
+
7
+ Version 3.2.1 2009-10-04
8
+ - Fixed bug in parlay by creating method parlance
9
+
10
+ Version 3.2.0 2009-10-01
11
+ - Fixed typo in documentation
12
+ - Added land_ho method!
13
+
1
14
  Version 3.1.1 2009-10-01
2
15
  - Readme Cleanup
3
16
  - Removing broken say_your_last_words method
data/README.rdoc CHANGED
@@ -28,7 +28,7 @@ Initialize method (a.k.a new()) takes a hash of params:
28
28
  # :timestamp - each successive run will create a new file using a HHMMSS time stamp
29
29
  # :none - no iterative file naming convention, just use waggoner and aft
30
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
31
- # :clear - do not use :counter or :timestamp, and instead overwrite the file
31
+ # :clean - do not use :counter or :timestamp, and instead overwrite the file
32
32
  # :dirty - do not use :counter, or :timestamp, or :overwrite. Just keep adding on.
33
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
34
  # check the source to see if there anything else hiding in there!
@@ -52,6 +52,10 @@ Release Announcement:
52
52
 
53
53
  == Installation
54
54
 
55
+ Gem from Gemcutter (after setting up your machine to use the gemcutter repo, see http://gemcutter.org):
56
+
57
+ sudo gem install csv_pirate
58
+
55
59
  Gem Using Git building from source:
56
60
 
57
61
  mkdir -p ~/src
@@ -59,7 +63,7 @@ Gem Using Git building from source:
59
63
  git clone git://github.com/pboling/csv_pirate.git
60
64
  cd csv_pirate
61
65
  gem build csv_pirate.gemspec
62
- sudo gem install csv_pirate-2.0.1.gem # (Or whatever version gets built)
66
+ sudo gem install csv_pirate-3.3.0.gem # (Or whatever version gets built)
63
67
 
64
68
  Then cd to your rails app to optionally freeze the gem into your app:
65
69
 
@@ -73,6 +77,7 @@ Plugin using Git:
73
77
 
74
78
  ruby script/plugin install git://github.com/pboling/csv_pirate.git
75
79
 
80
+ If installed as a gem load it with config.gem 'csv_pirate' # or 'pboling-csv_pirate' if from github
76
81
 
77
82
  == Upgrading
78
83
 
@@ -81,7 +86,73 @@ Plugin using Git:
81
86
  ['log','csv','pirates','model_name']
82
87
  CsvPirate ensures that whatever you choose as your chart exists in the filesystem, and creates the directories if need be.
83
88
 
84
- == Example & Usage
89
+ == Usage with ActiveRecord
90
+
91
+ What's the simplest thing that'll work?
92
+
93
+ class MyClass < ActiveRecord::Base
94
+ has_csv_pirate_ship # defaults to csv of all columns of all records
95
+ end
96
+
97
+ MyClass.blindfold # creates the csv, and returns the CsvPirate instance
98
+ MyClass.walk_the_plank # creates the csv, and returns contents of the exported data (that was written into the csv) (as a string)
99
+ MyClass.land_ho # Does Not create the csv, sets up the CsvPirate instance. You can manipulate it and then call .hoist_mainstay on it to create the csv
100
+
101
+ == Usage without ActiveRecord
102
+
103
+ Since the defaults assume an active record class you need to override some of them:
104
+
105
+ class Star
106
+ extend NinthBit::PirateShip::ActMethods
107
+ has_csv_pirate_ship :booty => [:name, :distance, :spectral_type, {:name => :hash}, {:name => :next}, {:name => :upcase}, :star_vowels],
108
+ :spyglasses => [:get_stars]
109
+
110
+ attr_accessor :name, :distance, :spectral_type
111
+
112
+ def initialize(*args)
113
+ @name = args.first[:name]
114
+ @distance = args.first[:distance]
115
+ @spectral_type = args.first[:spectral_type]
116
+ end
117
+
118
+ def star_vowels
119
+ self.name.tr('aeiou', '*')
120
+ end
121
+
122
+ def self.get_stars
123
+ [
124
+ Star.new(:name => "Proxima Centauri", :distance => "4.2 LY", :spectral_type => "M5.5Vc"),
125
+ Star.new(:name => "Rigil Kentaurus", :distance => "4.3 LY", :spectral_type => "G2V"),
126
+ Star.new(:name => "Barnard's Star", :distance => "5.9 LY", :spectral_type => "M3.8V"),
127
+ Star.new(:name => "Wolf 359", :distance => "7.7 LY", :spectral_type => "M5.8Vc"),
128
+ Star.new(:name => "Lalande 21185", :distance => "8.26 LY", :spectral_type => "M2V"),
129
+ Star.new(:name => "Luyten 726-8A and B", :distance => "8.73 LY", :spectral_type => "M5.5 de & M6 Ve"),
130
+ Star.new(:name => "Sirius A and B", :distance => "8.6 LY", :spectral_type => "A1Vm"),
131
+ Star.new(:name => "Ross 154", :distance => "9.693 LY", :spectral_type => "M3.5"),
132
+ Star.new(:name => "Ross 248", :distance => "10.32 LY", :spectral_type => "M5.5V"),
133
+ Star.new(:name => "Epsilon Eridani", :distance => "10.5 LY", :spectral_type => "K2V")
134
+ ]
135
+ end
136
+ end
137
+
138
+
139
+ rails development >a = Star.blindfold
140
+ => #<CsvPirate:0x2209098 @buried_treasure=[], @mop=:clean, @spyglasses=[:get_stars], @swabbie=".3", @booty=[:name, :distance, :spectral_type, {:name=>:hash}, {:name=>:next}, {:name=>:upcase}, :star_vowels], @bury_treasure=false, @swab=:counter, @chronometer=Sun, 04 Oct 2009, @maroon="name,distance,spectral_type,namehash,namenext,nameupcase,star_vowels\nProxima Centauri,4.2 LY,M5.5Vc,971295636,Proxima Centaurj,PROXIMA CENTAURI,Pr*x*m* C*nt**r*\nRigil Kentaurus,4.3 LY,G2V,-231389024,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,429493790,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,-886693495,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,-969980943,Sirius A and C,SIRIUS A AND B,S*r**s A *nd B\nRoss 154,9.693 LY,M3.5,-26506942,Ross 155,ROSS 154,R*ss 154\nRoss 248,10.32 LY,M5.5V,-18054910,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", @waggoner="Star", @astrolabe=false, @grub=Star, @rhumb_lines=#<File:/Users/pboling/RubymineProjects/empty_csv_pirate_app/log/csv/Star.20091004.export.3.csv (closed)>, @nocturnal="Star.20091004.export.3.csv", @aft=".csv", @gibbet=".export", @shrouds=",", @swag=[#<Star:0x2202db0 @spectral_type="M5.5Vc", @distance="4.2 LY", @name="Proxima Centauri">, #<Star:0x2202d10 @spectral_type="G2V", @distance="4.3 LY", @name="Rigil Kentaurus">, #<Star:0x2202c98 @spectral_type="M3.8V", @distance="5.9 LY", @name="Barnard's Star">, #<Star:0x2202c20 @spectral_type="M5.8Vc", @distance="7.7 LY", @name="Wolf 359">, #<Star:0x2202ba8 @spectral_type="M2V", @distance="8.26 LY", @name="Lalande 21185">, #<Star:0x2202b30 @spectral_type="M5.5 de & M6 Ve", @distance="8.73 LY", @name="Luyten 726-8A and B">, #<Star:0x2202ab8 @spectral_type="A1Vm", @distance="8.6 LY", @name="Sirius A and B">, #<Star:0x2202a40 @spectral_type="M3.5", @distance="9.693 LY", @name="Ross 154">, #<Star:0x22029c8 @spectral_type="M5.5V", @distance="10.32 LY", @name="Ross 248">, #<Star:0x2202950 @spectral_type="K2V", @distance="10.5 LY", @name="Epsilon Eridani">], @chart=["log", "csv"]>
141
+ rails development >a.weigh_anchor
142
+ name,distance,spectral_type,namehash,namenext,nameupcase,star_vowels
143
+ Proxima Centauri,4.2 LY,M5.5Vc,971295636,Proxima Centaurj,PROXIMA CENTAURI,Pr*x*m* C*nt**r*
144
+ Rigil Kentaurus,4.3 LY,G2V,-231389024,Rigil Kentaurut,RIGIL KENTAURUS,R*g*l K*nt**r*s
145
+ Barnard's Star,5.9 LY,M3.8V,1003964756,Barnard's Stas,BARNARD'S STAR,B*rn*rd's St*r
146
+ Wolf 359,7.7 LY,M5.8Vc,429493790,Wolf 360,WOLF 359,W*lf 359
147
+ Lalande 21185,8.26 LY,M2V,466625069,Lalande 21186,LALANDE 21185,L*l*nd* 21185
148
+ Luyten 726-8A and B,8.73 LY,M5.5 de & M6 Ve,-886693495,Luyten 726-8A and C,LUYTEN 726-8A AND B,L*yt*n 726-8A *nd B
149
+ Sirius A and B,8.6 LY,A1Vm,-969980943,Sirius A and C,SIRIUS A AND B,S*r**s A *nd B
150
+ Ross 154,9.693 LY,M3.5,-26506942,Ross 155,ROSS 154,R*ss 154
151
+ Ross 248,10.32 LY,M5.5V,-18054910,Ross 249,ROSS 248,R*ss 248
152
+ Epsilon Eridani,10.5 LY,K2V,931307088,Epsilon Eridanj,EPSILON ERIDANI,Eps*l*n Er*d*n*
153
+ => #<File:/Users/pboling/RubymineProjects/empty_csv_pirate_app/log/csv/Star.20091004.export.3.csv (closed)>
154
+
155
+ == Advanced Usage & Examples
85
156
 
86
157
  Assuming a Make (as in manufacturers of automobiles) model like this:
87
158
 
@@ -99,8 +170,29 @@ Assuming a Make (as in manufacturers of automobiles) model like this:
99
170
  has_many :vehicle_models
100
171
  named_scope :factory_in_germany, :conditions => ["factory = ?", "Germany"]
101
172
 
102
- has_csv_pirate_ship :spyglasses => [:factory_in_germany],
103
- :booty => [:id, :name]
173
+ # Showing all available options with their default values
174
+ has_csv_pirate_ship :chart => ['log','csv'] # Array of Strings: directory where csv will be created (Yes, it creates all of them if they do not already exist)
175
+ :aft => '.csv' # String: filename extension, usually this would be '.csv', but can be whatever you want.
176
+ :gibbet => '.export' # String: Middle part of the filename {the '.' is required for iterative filenames, set :swab => :none to turn off iterative filenames}
177
+ # Comes after waggoner and chronometer, before swabbie and aft
178
+ :waggoner => "#{Make}" # String: First part of filename
179
+
180
+ # Must provide :swag or :grub (not both)
181
+ :swag => nil # Array of objects: to use to create the CSV (i.e. you've already done the query and have the results you want a CSV of)
182
+ :grub => Make # Class: on which to call the method chain in :spyglasses that will return the array of objects to be placed in :swag by CsvPirate (See description of swag above).
183
+ :spyglasses => [:all] # Array of symbols/strings: Methods that will be chained together and called on :grub in order to get the :swag records which will become the rows of the CSV.
184
+ :booty => Make.column_names # Array of symbols/strings or nested hashes of symbols/strings: Methods to call on each object in :swag. These become the columns of the CSV. The method names become the CSV column headings. Methods can be chained to dig deep (e.g. traverse several ActiveRecord associations) to get at a value for the CSV.
185
+
186
+ :swab => :counter # Symbol: What kind of file counter to use to avoid overwtiting the CSV file, :counter is Integer, :timestamp is HHMMSS, :none is no file counter, increasing the liklihood of duplicate filenames on successive csv exports.
187
+ :mop => :clean # Symbol: If we DO end up writing to a preexisting file (by design or accident) should we overwrite (:clean) or append (:dirty)?
188
+ :shrouds => ',' # String: Delimiter for CSV. '\t' will create a tab delimited file (tsv), '|' will create a pipe delimited file.
189
+ :bury_treasure => true # Boolean: Should the array of objects in :swag be stored in the CsvPirate object for later inspection?
190
+
191
+ # A customized version to create a tab delimited file for this class might look like this:
192
+ # has_csv_pirate_ship :spyglasses => [:factory_in_germany],
193
+ # :booty => [:id, :name],
194
+ # :shrouds => '\t'
195
+ # # kepping the rest of the options at the default values, so they don't need to be defined.
104
196
  end
105
197
 
106
198
  To create a csv of the names and ids of makes with factories in germany and return the text of the export:
@@ -113,15 +205,28 @@ The name of the csv that comes out will be (by defualt located in log directory)
113
205
 
114
206
  Where Make is the class, 20090930 is today's date, .export is the gibbet, and 13 is the iterative file counter, meaning I've run this export 13 times today.
115
207
 
116
- All of those filename parts are customizable to a degree.
208
+ All of those filename parts are customizable to a degree. For example if you want to have the date NOT be today's date you can supply your own date:
209
+
210
+ Make.walk_the_plank({:chronometer => Date.parse("December 21, 2012") })
211
+ # Filename would be: Make.20121221.export.13.csv
212
+
213
+ Make.walk_the_plank({:chronometer => false })
214
+ # Filename would be: Make.export.13.csv
215
+
216
+ What if you want the file name to be always the same and to always append to the end of it?
217
+ #Example: I want the file to be named "data", with no extension, both of the following accomplish that:
218
+ Make.walk_the_plank({:chronometer => false, :gibbet => "", :aft => "", :swab => :none, :waggoner => 'data'})
219
+ Make.blindfold(:chronometer => false, :gibbet => "", :aft => "", :swab => :none, :waggoner => 'data')
220
+
221
+ All of the options to has_csv_pirate_ship are available to walk_the_plank, land_ho, and blindfold, as well as to the raw class methods CsvPirate.new and CsvPirate.create, but not neccessarily the other way around.
117
222
 
118
- You can also customize the CSV, for example if you want to add a column to the csv:
223
+ You can also customize the CSV, for example if you want to customize which columns are in the csv:
119
224
 
120
225
  Make.walk_the_plank({:booty => [:id, :name, :sales]})
121
226
 
122
- Youw want a timestamp file counter instead of the integer default:
227
+ You want a timestamp file counter instead of the integer default:
123
228
 
124
- Make.walk_the_plank({:booty => [:id, :name, :sales], :spyglasses => [:all], :swab => :timestamp})
229
+ Make.walk_the_plank({:booty => [:id, :name, :sales], :swab => :timestamp})
125
230
 
126
231
  If you want to append each export to the end of the same file (on a per day basis):
127
232
 
@@ -270,6 +375,23 @@ Then check the output from the console:
270
375
 
271
376
  Joy to recursive code everywhere!
272
377
 
378
+ If you wanted to create the CsvPirate object and then modify it before creating the csv you can do that too.
379
+ Does not actually create the csv, so you need to do this in your code:
380
+
381
+ csv_pirate = VehicleModel.land_ho({:booty => [:id, :name, :year, :horsepower, :price]})
382
+
383
+ This allows you to modify the csv_pirate object before creating the csv like this:
384
+
385
+ csv_pirate.booty -= [:id, :name]
386
+ csv_pirate.hoist_mainstay()
387
+
388
+ == Thanks
389
+
390
+ Thanks go to
391
+ 9thBit LLC (http://www.9thBit.net)
392
+ Sagebit LLC (http://www.sagebit.com) - Sagebit has been very supportive of my open source efforts, thanks Ben!
393
+ TimePerks LLC (http://www.timeperks.com) - Many useful enhancements were requested and paid for by TimePerks
394
+
273
395
  ----------------------------------------------------------------------------------
274
396
  Author: Peter Boling, peter.boling at gmail dot com
275
397
  Copyright (c) 2009 Peter H. Boling of 9thBit LLC, released under the MIT license. See LICENSE for details.
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 1
2
+ :patch: 0
3
3
  :major: 3
4
- :minor: 1
4
+ :minor: 3
data/csv_pirate.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{csv_pirate}
8
- s.version = "3.1.1"
8
+ s.version = "3.3.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"]
12
- s.date = %q{2009-10-01}
12
+ s.date = %q{2009-10-05}
13
13
  s.description = %q{CsvPirate is the easy way to create a CSV of essentially anything in Rails, in full pirate regalia.
14
14
  It works better if you are wearing a tricorne!}
15
15
  s.email = %q{peter.boling@gmail.com}
data/lib/csv_pirate.rb CHANGED
@@ -14,15 +14,15 @@ class CsvPirate
14
14
  BOOKIE = [:counter, :timestamp, :none]
15
15
  MOP_HEADS = [:clean, :dirty]
16
16
 
17
- attr_accessor :waggoner #filename
18
- attr_accessor :chart #directory, default is (['log','csv'])
19
- attr_accessor :aft #extension, default is ('.csv')
20
- attr_accessor :gibbet #part of the filename after waggoner and date, before swabbie and aft
21
- attr_accessor :chronometer
17
+ attr_accessor :waggoner # First part of filename
18
+ attr_accessor :chart # directory, default is (['log','csv'])
19
+ attr_accessor :aft # extension, default is ('.csv')
20
+ attr_accessor :gibbet # part of the filename after waggoner and date, before swabbie and aft
21
+ attr_accessor :chronometer # Date object or false
22
22
 
23
23
  # Must provide swag or grub (not both)
24
- attr_accessor :swag # ARrr array of objects
25
- attr_accessor :grub # ARrr class
24
+ attr_accessor :swag # Array of objects
25
+ attr_accessor :grub # Class
26
26
  # spyglasses is only used with grub, not swag
27
27
  attr_accessor :spyglasses # named_scopes
28
28
 
@@ -60,14 +60,14 @@ class CsvPirate
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"
63
- # :chronometer keeps track of when you hunt for treasure
63
+ # :chronometer keeps track of when you hunt for treasure, can be false if you don't want to keep track.
64
64
  # :gibbet filename spacer after the date, and before the iterative counter/timestamp. MuST contain a '.'
65
65
  # :swab can be :counter, :timestamp, or :none
66
66
  # :counter - default, each successive run will create a new file using a counter
67
67
  # :timestamp - each successive run will create a new file using a HHMMSS time stamp
68
- # :none - no iterative file naming convention, just use waggoner and aft
68
+ # :none - no iterative file naming convention, just use waggoner, aft and gibbet
69
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
70
- # :clear - do not use :counter or :timestamp, and instead overwrite the file
70
+ # :clean - do not use :counter or :timestamp, and instead overwrite the file
71
71
  # :dirty - do not use :counter, or :timestamp, or :overwrite. Just keep adding on.
72
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)?
73
73
  # See README for examples
@@ -79,33 +79,34 @@ class CsvPirate
79
79
  @grub = args.first[:grub]
80
80
 
81
81
  # if they provide both
82
- raise ArgumentError, "must provide either :swag or :grub" if !args.first[:swag].blank? && !args.first[:grub].blank?
82
+ raise ArgumentError, "must provide either :swag or :grub, not both" if !self.swag.blank? && !self.grub.blank?
83
83
  # if they provide neither
84
- raise ArgumentError, "must provide either :swag or :grub, not both" if args.first[:swag].blank? && args.first[:grub].blank?
84
+ raise ArgumentError, "must provide either :swag or :grub" if self.swag.blank? && self.grub.blank?
85
85
 
86
86
  @swab = args.first[:swab] || :counter
87
- raise ArgumentError, ":swab is #{args.first[:swab].inspect}, but must be one of #{CsvPirate::BOOKIE.inspect}" unless CsvPirate::BOOKIE.include?(args.first[:swab])
87
+ raise ArgumentError, ":swab is #{self.swab.inspect}, but must be one of #{CsvPirate::BOOKIE.inspect}" unless CsvPirate::BOOKIE.include?(self.swab)
88
88
 
89
89
  @mop = args.first[:mop] || :clean
90
- raise ArgumentError, ":mop is #{args.first[:mop].inspect}, but must be one of #{CsvPirate::MOP_HEADS.inspect}" unless CsvPirate::MOP_HEADS.include?(args.first[:mop])
90
+ raise ArgumentError, ":mop is #{self.mop.inspect}, but must be one of #{CsvPirate::MOP_HEADS.inspect}" unless CsvPirate::MOP_HEADS.include?(self.mop)
91
91
 
92
92
  @gibbet = args.first[:gibbet] || '.export'
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?('.')
93
+ raise ArgumentError, ":gibbet is #{self.gibbet.inspect}, and does not contain a '.' character, which is required when using iterative filenames (set :swab => :none to turn off iterative filenames)" if self.swab != :none && (self.gibbet.nil? || !self.gibbet.include?('.'))
94
94
 
95
95
  @waggoner = args.first[:waggoner] || "#{self.grub || self.swag}"
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
96
+ 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
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].is_a?(Array) || args.first[:booty].empty?
99
+ 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?
100
100
 
101
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?
102
+ 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?
103
103
 
104
104
  @aft = args.first[:aft] || '.csv'
105
- @chronometer = args.first[:chronometer] || Date.today
105
+ @chronometer = args.first[:chronometer] == false ? false : args.first[:chronometer] || Date.today
106
106
 
107
107
  @spyglasses = (args.first[:spyglasses] || [:all]) if self.grub
108
108
  @shrouds = args.first[:shrouds] || ',' # for tsv, tab-delimited, "\t"
109
+ 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)
109
110
 
110
111
  @astrolabe = args.first[:astrolabe] || false
111
112
 
@@ -198,7 +199,7 @@ class CsvPirate
198
199
 
199
200
  self.rhumb_lines.close
200
201
 
201
- self.jolly_roger if CsvPirate.parlay > 1
202
+ self.jolly_roger if CsvPirate.parlay && CsvPirate.parlance(1)
202
203
 
203
204
  # returns the text of this CSV export
204
205
  return self.maroon
@@ -215,10 +216,10 @@ class CsvPirate
215
216
  def jolly_roger
216
217
  if self.bury_treasure
217
218
  if self.buried_treasure.is_a?(Array)
218
- puts "Found #{self.buried_treasure.length} deniers buried here: '#{self.poop_deck}'" if CsvPirate.parlay > 1
219
- puts "You must weigh_anchor to review your plunder!" if CsvPirate.parlay > 1
219
+ puts "Found #{self.buried_treasure.length} deniers buried here: '#{self.poop_deck}'" if CsvPirate.parlay && CsvPirate.parlance(1)
220
+ puts "You must weigh_anchor to review your plunder!" if CsvPirate.parlay && CsvPirate.parlance(1)
220
221
  else
221
- puts "Failed to locate treasure" if CsvPirate.parlay > 1
222
+ puts "Failed to locate treasure" if CsvPirate.parlay && CsvPirate.parlance(1)
222
223
  end
223
224
  end
224
225
  end
@@ -371,7 +372,7 @@ class CsvPirate
371
372
  return false unless block_given?
372
373
  count = 1 if report_kills
373
374
  FasterCSV.foreach(galley, {:headers => :first_row, :return_headers => false}) do |gun|
374
- puts "Galleys sunk: #{count+=1}" if CsvPirate.parlay > 1
375
+ puts "Galleys sunk: #{count+=1}" if CsvPirate.parlance(1)
375
376
  yield gun
376
377
  end
377
378
  end
@@ -421,13 +422,13 @@ class CsvPirate
421
422
  cutthroat.figurehead
422
423
 
423
424
  carrack.scuttle do |cutlass|
424
- puts "CUTLASS: #{cutlass.inspect}" if CsvPirate.parlay > 2
425
- puts "CARRACK.SWAG: #{carrack.swag.inspect}" if CsvPirate.parlay > 2
425
+ puts "CUTLASS: #{cutlass.inspect}" if CsvPirate.parlance(2)
426
+ puts "CARRACK.SWAG: #{carrack.swag.inspect}" if CsvPirate.parlance(2)
426
427
  backstaff = cutlass[carrack.swag] || cutlass["#{carrack.spyglasses}"]
427
- puts "BACKSTAFF: #{backstaff}" if CsvPirate.parlay > 2
428
- puts "CARRACK.SPYGLASSES: #{carrack.spyglasses.inspect}" if CsvPirate.parlay > 2
428
+ puts "BACKSTAFF: #{backstaff}" if CsvPirate.parlance(2)
429
+ puts "CARRACK.SPYGLASSES: #{carrack.spyglasses.inspect}" if CsvPirate.parlance(2)
429
430
  gully = carrack.grub.send("find_by_#{carrack.spyglasses}".to_sym, backstaff)
430
- puts "GULLY: #{gully.inspect}" if CsvPirate.parlay > 2
431
+ puts "GULLY: #{gully.inspect}" if CsvPirate.parlance(2)
431
432
  if gully
432
433
  flotsam = cutthroat.grub.is_a?(String) ?
433
434
  gully.send(cutthroat.grub.to_sym) :
@@ -438,16 +439,16 @@ class CsvPirate
438
439
  cutthroat.grub.class == Class ?
439
440
  cutthroat.grub.send("find_by_#{cutthroat.swag}", gully.send(cutthroat.spyglasses)) :
440
441
  nil
441
- puts "FLOTSAM: #{flotsam.inspect}" if CsvPirate.parlay > 2
442
+ puts "FLOTSAM: #{flotsam.inspect}" if CsvPirate.parlance(2)
442
443
  if flotsam
443
444
  plunder = cutthroat.prize(flotsam)
444
445
  cutthroat.buried_treasure << plunder
445
446
  cutthroat.scrivener(plunder.map {|bulkhead| "#{bulkhead}"}.join(','))
446
447
  else
447
- puts "Unable to locate: #{cutthroat.grub} related to #{carrack.grub}.#{carrack.spyglasses} '#{gully.send(carrack.spyglasses)}'" if CsvPirate.parlay > 1
448
+ puts "Unable to locate: #{cutthroat.grub} related to #{carrack.grub}.#{carrack.spyglasses} '#{gully.send(carrack.spyglasses)}'" if CsvPirate.parlance(1)
448
449
  end
449
450
  else
450
- puts "Unable to locate: #{carrack.grub}.#{carrack.spyglasses} '#{gully.send(carrack.spyglasses)}'" if CsvPirate.parlay > 1
451
+ puts "Unable to locate: #{carrack.grub}.#{carrack.spyglasses} '#{gully.send(carrack.spyglasses)}'" if CsvPirate.parlance(1)
451
452
  end
452
453
  end
453
454
 
@@ -460,4 +461,9 @@ class CsvPirate
460
461
  return cutthroat
461
462
  end
462
463
 
464
+ # verbosity on a scale of 0 - 3 (0=:none, 1=:error, 2=:info, 3=:debug, 0 being no screen output, 1 is default
465
+ def self.parlance(level = 1)
466
+ self.parlay.is_a?(Numeric) && self.parlay >= level
467
+ end
468
+
463
469
  end
@@ -23,15 +23,16 @@ module NinthBit
23
23
  options[:parlay] ||= 1
24
24
 
25
25
  # if they provide both
26
- raise ArgumentError, "must provide either :swag or :grub" if !options[:swag].blank? && !options[:grub].blank?
26
+ raise ArgumentError, "must provide either :swag or :grub, not both" if !options[:swag].blank? && !options[:grub].blank?
27
27
  # if they provide neither
28
- raise ArgumentError, "must provide either :swag or :grub, not both" if options[:swag].blank? && options[:grub].blank?
28
+ raise ArgumentError, "must provide either :swag or :grub" 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
- 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?('.')
31
+ 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?('.'))
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
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
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?
35
+ raise ArgumentError, ":shrouds is #{options[:shrouds].inspect}, and must be a string (e.g. ',' or '\t'), which will be used as the delimeter for the csv file" if options[:shrouds].nil? || !options[:shrouds].is_a?(String)
35
36
 
36
37
  extend ClassMethods unless (class << self; included_modules; end).include?(ClassMethods)
37
38
 
@@ -48,48 +49,58 @@ module NinthBit
48
49
 
49
50
  # intended for use with send_data for downloading the text of the csv:
50
51
  # send_data Make.say_your_last_words
51
- # TODO: Fix say_yourr_last_words so it works! Use send_data args
52
+ # TODO: Fix say_yourr_last_words so it works! Use send_data args for real
52
53
  #def say_your_last_words(charset = 'utf-8', args = {})
53
54
  # csv_pirate = self.blindfold(args)
54
55
  # return [ csv_pirate.maroon,
55
56
  # {:type => "text/csv; charset=#{charset}; header=present"},
56
57
  # {:disposition => "attachment; filename=#{csv_pirate.nocturnal}"} ]
57
58
  #end
58
-
59
- #returns the text of the csv export (not the file - this is important if you are appending)
59
+
60
+ # returns the text of the csv export (not the file - this is important if you are appending)
60
61
  # warning if using from console: if you are exporting a large csv this will all print in your console.
61
62
  # intended for use with send_data for downloading the text of the csv:
62
63
  # send_data Make.walk_the_plank,
63
64
  # :type => 'text/csv; charset=iso-8859-1; header=present',
64
65
  # :disposition => "attachment; filename=Data.csv"
65
66
  def walk_the_plank(args = {})
66
- csv_pirate = CsvPirate.new(self.piratey_args(args))
67
- csv_pirate.hoist_mainstay()
67
+ self.land_ho(args).hoist_mainstay()
68
68
  end
69
69
 
70
- #returns the csv_pirate object so you have access to everything
70
+ # returns the csv_pirate object so you have access to everything
71
+ # warning if using from console: if you are exporting a large csv this will all print in your console.
71
72
  # If using in a download action it might look like this:
72
73
  # csv_pirate = Make.blindfold
73
74
  # send_data csv_pirate.maroon,
74
75
  # :type => 'text/csv; charset=iso-8859-1; header=present',
75
76
  # :disposition => "attachment; filename=#{csv_pirate.nocturnal}"
76
77
  def blindfold(args = {})
77
- CsvPirate.parlay = args[:parlay] || self.piratey_options[:parlay]
78
78
  CsvPirate.create(self.piratey_args(args))
79
79
  end
80
80
 
81
+ # returns the csv_pirate object so you have access to everything
82
+ # Does not actually create the csv, so you need to do this in your code:
83
+ # csv_pirate = Klass.land_ho({:booty => [:id, :name, :dragons, :created_at]})
84
+ # This allows you to modify the csv_pirate object before creating the csv like this:
85
+ # csv_pirate.booty -= [:id, :name]
86
+ # csv_pirate.hoist_mainstay()
87
+ def land_ho(args = {})
88
+ CsvPirate.new(self.piratey_args(args))
89
+ end
90
+
81
91
  protected
82
92
 
83
93
  def piratey_args(args = {})
84
- { :chart => args[:chart] || self.piratey_options[:chart],
94
+ CsvPirate.parlay = args[:parlay] || self.piratey_options[:parlay]
95
+ return { :chart => args[:chart] || self.piratey_options[:chart],
85
96
  :aft => args[:aft] || self.piratey_options[:aft],
86
97
  :gibbet => args[:gibbet] || self.piratey_options[:gibbet],
87
- :chronometer => args[:chronometer] || Date.today,
98
+ :chronometer => args[:chronometer] == false ? false : args[:chronometer] || Date.today,
88
99
  :waggoner => args[:waggoner] || self.piratey_options[:waggoner] || "#{self}",
89
100
  :swag => args[:swag] || self.piratey_options[:swag],
90
101
  :swab => args[:swab] || self.piratey_options[:swab],
91
102
  :mop => args[:mop] || self.piratey_options[:mop],
92
- :shrouds => args[:swab] || self.piratey_options[:shrouds],
103
+ :shrouds => args[:shrouds] || self.piratey_options[:shrouds],
93
104
  :grub => args[:grub] || self.piratey_options[:grub],
94
105
  :spyglasses => args[:spyglasses] || self.piratey_options[:spyglasses],
95
106
  :booty => args[:booty] || self.piratey_options[:booty],
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: 3.1.1
4
+ version: 3.3.0
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: 2009-10-01 00:00:00 -04:00
12
+ date: 2009-10-05 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15