Browse Source

csv: yield to block on each cell

Closes #151

Related to #145
dev
Andy Meneely 10 years ago
parent
commit
795b4e4478
  1. 13
      docs/dsl/csv.rst
  2. 15
      docs/dsl/xlsx.rst
  3. 13
      lib/squib/api/data.rb
  4. 29
      spec/api/api_data_spec.rb
  5. 3
      spec/data/csv/yield.csv

13
docs/dsl/csv.rst

@ -44,6 +44,19 @@ col_sep
CSV custom options in Ruby standard lib.
All of the options in Ruby's std lib version of CSV are supported **except** ``headers`` is always ``true`` and ``converters`` is always set to ``:numeric``. See the `Ruby Docs <http://ruby-doc.org/stdlib-2.2.0/libdoc/csv/rdoc/CSV.html#method-c-new>`_ for information on the options.
Individual Pre-processing
-------------------------
The ``xlsx`` method also takes in a block that will be executed for each cell in your data. This is useful for processing individual cells, like putting a dollar sign in front of dollars, or converting from a float to an integer. The value of the block will be what is assigned to that cell. For example::
resource_data = Squib.csv(file: 'sample.xlsx') do |header, value|
case header
when 'Cost'
"$#{value}k" # e.g. "3" becomes "$3k"
else
value # always return the original value if you didn't do anything to it
end
end
Examples
--------

15
docs/dsl/xlsx.rst

@ -9,7 +9,6 @@ The ``xlsx`` method is a member of ``Squib::Deck``, but it is also available out
Squib::Deck.new(cards: data['name'].size) do
end
Options
-------
@ -33,5 +32,19 @@ explode
Quantity explosion will be applied to the column this name. For example, rows in the csv with a ``'qty'`` of 3 will be duplicated 3 times.
Individual Pre-processing
-------------------------
The ``xlsx`` method also takes in a block that will be executed for each cell in your data. This is useful for processing individual cells, like putting a dollar sign in front of dollars, or converting from a float to an integer. The value of the block will be what is assigned to that cell. For example::
resource_data = Squib.xlsx(file: 'sample.xlsx') do |header, value|
case header
when 'Cost'
"$#{value}k" # e.g. "3" becomes "$3k"
else
value # always return the original value if you didn't do anything to it
end
end
Examples
--------

13
lib/squib/api/data.rb

@ -32,6 +32,7 @@ module Squib
# DSL method. See http://squib.readthedocs.org
def csv(opts = {})
# TODO refactor all this out to separate methods, and its own class
import = Args::Import.new.load!(opts)
file = Args::InputFile.new(file: 'deck.csv').load!(opts).file[0]
data = opts.key?(:data) ? opts[:data] : File.read(file)
@ -47,10 +48,20 @@ module Squib
if import.strip?
new_hash = Hash.new
hash.each do |header, col|
new_hash[header] = col.map { |str| str = str.strip if str.respond_to?(:strip); str }
new_hash[header] = col.map do |str|
str = str.strip if str.respond_to?(:strip)
str
end
end
hash = new_hash
end
if block_given?
hash.each do |header, col|
col.map! do |val|
yield(header, val)
end
end
end
return explode_quantities(hash, import.explode)
end
module_function :csv

29
spec/api/api_data_spec.rb

@ -76,6 +76,35 @@ describe Squib::Deck do
})
end
it 'yields to block when given' do
data = Squib.csv(file: csv_file('basic.csv')) do |header, value|
case header
when 'h1'
value * 2
else
'ha'
end
end
expect(data).to eq({
'h1' => [2, 6],
'h2' => %w(ha ha),
})
end
it 'replaces newlines whenever its a string' do
data = Squib.csv(file: csv_file('yield.csv')) do |header, value|
if value.respond_to? :gsub
value.gsub '%n', "\n"
else
value
end
end
expect(data).to eq({
'a' => ["foo\nbar", 1],
'b' => [1, "blah\n"],
})
end
end
context '#xlsx' do

3
spec/data/csv/yield.csv

@ -0,0 +1,3 @@
a,b
foo%nbar,1
1,blah%n
1 a b
2 foo%nbar 1
3 1 blah%n
Loading…
Cancel
Save