lib/csv_pirate.rb in csv_pirate-2.1.2 vs lib/csv_pirate.rb in csv_pirate-2.4.4

- old
+ new

@@ -30,53 +30,60 @@ # Should be methods/columns on the swag # also used to create the figurehead (CSV header) attr_accessor :booty # methods / columns attr_accessor :bury_treasure # should we store the csv data in an array for later inspection, or just write the CSV? - # default is true + # default is false # The array that gets built as we write the CSV... could be useful? attr_accessor :buried_treasure # info array attr_accessor :rhumb_lines # the file object to write the CSV lines to attr_accessor :astrolabe # when true then read only CsvPirate instance for loading of CSVs + attr_accessor :shrouds # CSV column separator + attr_accessor :swab # default is :counter attr_accessor :mop # default is :clean (only has an effect if :swab is :none) since overwriting is irrelevant for a new file attr_accessor :swabbie # value of the counter / timestamp + attr_accessor :maroon # text of csv + attr_accessor :nocturnal # basename of the filepath (i.e. filename) 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 # CsvPirate only works for commissions of swag OR grub! - # :swag the ARrr collection of swag to work on (optional) - # :grub the ARrr class that the spyglasses will be used on (optional) - # :spyglasses named scopes in your model that will refine the rows in the CSV according to conditions of the spyglasses, - # and order them according to the order of the spyglasses (optional) - # :booty booty (columns/methods) on your model that you want printed in the CSV, also used to create the figurehead (CSV header) - # :chart name of directory where you want to hide your loot - # :wagonner name of document where you will give detailed descriptions of the loot - # :aft filename extention ('.csv') - # :chronometer keeps track of when you hunt for treasure - # :gibbet filename spacer after the date, and before the iterative counter/timestamp. MuST contain a '.' - # :swab can be :counter, :timestamp, or :none + # :swag the ARrr collection of swag to work on (optional) + # :grub the ARrr class that the spyglasses will be used on (optional) + # :spyglasses named scopes in your model that will refine the rows in the CSV according to conditions of the spyglasses, + # and order them according to the order of the spyglasses (optional) + # :booty booty (columns/methods) on your model that you want printed in the CSV, also used to create the figurehead (CSV header) + # :chart name of directory where you want to hide your loot + # :wagonner name of document where you will give detailed descriptions of the loot + # :aft filename extention ('.csv') + # :shrouds CSV column separator, default is ','. For tsv, tab-delimited, "\t" + # :chronometer keeps track of when you hunt for treasure + # :gibbet filename spacer after the date, and before the iterative counter/timestamp. MuST contain a '.' + # :swab can be :counter, :timestamp, or :none # :counter - default, each successive run will create a new file using a counter # :timestamp - each successive run will create a new file using a HHMMSS time stamp # :none - no iterative file naming convention, just use waggoner and aft - # :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 + # :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 # :clear - do not use :counter or :timestamp, and instead overwrite the file # :dirty - do not use :counter, or :timestamp, or :overwrite. Just keep adding on. + # :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)? # See README for examples def initialize(*args) + raise ArgumentError, "must provide required options" if args.blank? @swag = args.first[:swag] @grub = args.first[:grub] # if they provide both - raise ArgumentError, "must provide either specify :swag or :grub" if !args.first[:swag].blank? && !args.first[:grub].blank? + raise ArgumentError, "must provide either :swag or :grub" if !args.first[:swag].blank? && !args.first[:grub].blank? # if they provide neither - raise ArgumentError, "must provide either specify :swag or :grub, not both" if args.first[:swag].blank? && args.first[:grub].blank? + raise ArgumentError, "must provide either :swag or :grub, not both" if args.first[:swag].blank? && args.first[:grub].blank? @swab = args.first[:swab] || :counter raise ArgumentError, ":swab is #{args.first[:swab].inspect}, but must be one of #{CsvPirate::BOOKIE.inspect}" unless CsvPirate::BOOKIE.include?(args.first[:swab]) @mop = args.first[:mop] || :clean @@ -94,23 +101,29 @@ @chart = args.first[:chart] || 'log/' @aft = args.first[:aft] || '.csv' @chronometer = args.first[:chronometer] || Date.today @spyglasses = (args.first[:spyglasses] || [:all]) if self.grub + @shrouds = args.first[:shrouds] || ',' # for tsv, tab-delimited, "\t" - @astrolabe = args.first[:astrolabe] || false - @bury_treasure = args.first[:astrolabe] || true + @bury_treasure = args.first[:astrolabe] || false @buried_treasure = [] # Initialize doesn't write anything to a CSV, # but does create the traverse_board and opens the waggoner for reading / writing Dir.mkdir(self.traverse_board) if !self.astrolabe && Dir.glob(self.traverse_board).empty? + # This will contain the text of the csv from this particular execution + @maroon = "" + # Once the traverse_board (dir) exists, then check if the rhumb_lines (file) already exists, and set our rhumb_lines counter @swabbie = self.insult_swabbie + + @nocturnal = File.basename(self.poop_deck) + # Then open the rhumb_lines self.rhumb_lines = File.open(File.expand_path(self.poop_deck),self.astrolabe ? "r" : "a") end def self.create(*args) @@ -120,10 +133,11 @@ :gibbet => args.first[:gibbet], :chronometer => args.first[:chronometer], :waggoner => args.first[:waggoner], :swag => args.first[:swag], :swab => args.first[:swab], + :shrouds => args.first[:shrouds], :mop => args.first[:mop], :grub => args.first[:grub], :spyglasses => args.first[:spyglasses], :booty => args.first[:booty], :astrolabe => args.first[:astrolabe], @@ -176,44 +190,53 @@ # - restricted to loot that can be seen through spyglasses (if provided)! def hoist_mainstay self.swab_poop_deck - self.figurehead - - self.bury_treasure ? self.buried_treasure = self.dead_mans_chest : self.dead_mans_chest + self.dead_mans_chest self.rhumb_lines.close self.jolly_roger if CsvPirate.parlay > 1 - # returns the array that was created before exporting it to CSV - return self.bury_treasure ? self.buried_treasure : true + # returns the text of this CSV export + return self.maroon end def dead_mans_chest - self.dig_for_treasure do |treasure| - self.scrivener(treasure.map {|x| "#{x}"}.to_csv) # |x| marks the spot! + self.maroon = FasterCSV.generate(:col_sep => self.shrouds) do |csv| + self.sounding(csv) end + self.scrivener(self.maroon) + self.maroon end def jolly_roger - if self.buried_treasure.is_a?(Array) - puts "Found #{self.buried_treasure.length} deniers buried here: '#{self.poop_deck}'" if CsvPirate.parlay > 1 - puts "You must weigh_anchor to review your plunder!" if CsvPirate.parlay > 1 - else - puts "Failed to locate treasure" if CsvPirate.parlay > 1 + if self.bury_treasure + if self.buried_treasure.is_a?(Array) + puts "Found #{self.buried_treasure.length} deniers buried here: '#{self.poop_deck}'" if CsvPirate.parlay > 1 + puts "You must weigh_anchor to review your plunder!" if CsvPirate.parlay > 1 + else + puts "Failed to locate treasure" if CsvPirate.parlay > 1 + end end end - # write the header of the CSV (column/method names) - def figurehead - self.scrivener(self.booty.to_csv) + def sounding(csv) + # create the header of the CSV (column/method names) + csv << self.booty + # create the data for the csv + self.dig_for_treasure do |treasure| + moidore = treasure.map {|x| "#{x}"} + csv << moidore # |x| marks the spot! + self.buried_treasure << moidore if self.bury_treasure + end end - + def traverse_board - "#{RAILS_ROOT}/#{self.chart}" + #If we have rails environment then we use rails root, otherwise self.chart stands on its own as a relative path + "#{defined?(Rails) ? Rails.root + '/' : defined?(RAILS_ROOT) ? RAILS_ROOT + '/' : ''}#{self.chart}" end def sand_glass "#{self.chronometer.respond_to?(:strftime) ? '.' + self.chronometer.strftime("%Y%m%d") : ''}" end @@ -221,72 +244,80 @@ #complete file path def poop_deck "#{self.analemma}#{self.swabbie}#{self.aft}" end + def merchantman + "#{self.waggoner}#{self.sand_glass}#{self.gibbet}" + end + def analemma - "#{self.traverse_board}#{self.waggoner}#{self.sand_glass}#{self.gibbet}" + "#{self.traverse_board}#{self.merchantman}" end + # Swabs the poop_deck if the mop is clean. (!) + def swab_poop_deck + self.rhumb_lines.truncate(0) if self.swab == :none && self.mop == :clean && File.size(self.poop_deck) > 0 + end + + # Must be done on order to rummage through the loot found by the pirate ship + def weigh_anchor + CsvPirate.rinse(self.poop_deck) + end + + # Sink your own ship! Or run a block of code on each row of the current CSV + def scuttle(&block) + return false unless block_given? + CsvPirate.broadside(self.poop_deck) do |careen| + yield careen + end + end + + protected + def lantern "#{self.analemma}.*" end - + def filibuster(flotsam) base = File.basename(flotsam, self.aft) index = base.rindex('.') tail = index.nil? ? nil : base[index+1,base.length] # Ensure numbers counter = tail.nil? ? 0 : tail[/\d*/].to_i end - + def boatswain return self.swabbie unless self.swabbie.nil? counter = 0 bowspirit = Dir.glob(self.lantern) highval = 0 bowspirit.each do |flotsam| counter = self.filibuster(flotsam) highval = ((highval <=> counter) == 1) ? highval : counter counter = 0 end - self.swabbie = ".#{highval + 1}" + ".#{highval + 1}" end def coxswain return self.swabbie unless self.swabbie.nil? - self.swabbie = ".#{Time.now.strftime("%I%M%S")}" + ".#{Time.now.strftime("%I%M%S")}" end - # Swabs the poop_deck if the mop is clean. (!) - def swab_poop_deck - self.rhumb_lines.truncate(0) if self.swab == :none && self.mop == :clean && File.size(self.poop_deck) > 0 - end - # Sets the swabby file counter def insult_swabbie return case self.swab when :counter self.boatswain when :timestamp self.coxswain else - self.swabbie = "" + "" end end - # Must be done on order to rummage through the loot found by the pirate ship - def weigh_anchor - CsvPirate.rinse(self.poop_deck) - end - - # Sink your own ship! Or run a block of code on each row of the current CSV - def scuttle(&block) - return false unless block_given? - CsvPirate.broadside(self.poop_deck) do |careen| - yield careen - end - end + public ######################################## ############ CLASS METHODS ############# ########################################