Cleanup and tests of yaml method
parent
d53fbc1715
commit
f140ff32fa
|
|
@ -6,8 +6,9 @@ Squib follows [semantic versioning](http://semver.org).
|
||||||
Features:
|
Features:
|
||||||
* `circle` method now supports various `arc` options, so you can draw partial circles (#211) by @sparr
|
* `circle` method now supports various `arc` options, so you can draw partial circles (#211) by @sparr
|
||||||
* `save_sheet` method now supports `rtl` or "right-to-left", for easier duplex printing of backs (#204, #208) by @sparr
|
* `save_sheet` method now supports `rtl` or "right-to-left", for easier duplex printing of backs (#204, #208) by @sparr
|
||||||
|
* `yaml` method for reading in data, much like `csv` and `xlsx` by @blinks
|
||||||
|
|
||||||
Special thanks to @sparr for all of his work!!
|
Special thanks to @sparr and @blinks for all of their work!!
|
||||||
|
|
||||||
## v0.13.2 / 2017-01-27
|
## v0.13.2 / 2017-01-27
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
yaml
|
||||||
|
====
|
||||||
|
|
||||||
|
Pulls deck data from a YAML files into a ``Squib::DataFrame`` (essentially a hash of arrays).
|
||||||
|
|
||||||
|
Parsing uses Ruby's built-in Yaml package.
|
||||||
|
|
||||||
|
The ``yaml`` method is a member of ``Squib::Deck``, but it is also available outside of the Deck DSL with ``Squib.yaml()``. This allows a construction like::
|
||||||
|
|
||||||
|
data = Squib.Yaml file: 'data.yml'
|
||||||
|
Squib::Deck.new(cards: data['name'].size) do
|
||||||
|
end
|
||||||
|
|
||||||
|
The Yaml file format assumes that the entire deck is an array, then each element of the array is a hash. Every key encountered in that hash will translate to a "column" in the data frame. If a key exists in one card and not in another, then it defaults to ``nil``.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Case matters in your Yaml keys.
|
||||||
|
|
||||||
|
Options
|
||||||
|
-------
|
||||||
|
|
||||||
|
file
|
||||||
|
default: ``'deck.yml'``
|
||||||
|
|
||||||
|
the YAML-formatted file to open. Opens relative to the current directory. If ``data`` is set, this option is overridden.
|
||||||
|
|
||||||
|
data
|
||||||
|
default: ``nil``
|
||||||
|
|
||||||
|
when set, method will parse this Yaml data instead of reading the file.
|
||||||
|
|
||||||
|
explode
|
||||||
|
default: ``'qty'``
|
||||||
|
|
||||||
|
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 ``yaml`` 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.yaml(file: 'sample.yaml') 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
|
||||||
|
--------
|
||||||
|
|
||||||
|
|
||||||
|
To get the sample Excel files, go to `its source <https://github.com/andymeneely/squib/tree/dev/samples/data>`_
|
||||||
|
|
||||||
|
.. literalinclude:: ../../samples/data/_csv.rb
|
||||||
|
:language: ruby
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
Here's the sample.csv
|
||||||
|
|
||||||
|
.. literalinclude:: ../../samples/data/sample.csv
|
||||||
|
:language: text
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
Here's the quantity_explosion.csv
|
||||||
|
|
||||||
|
.. literalinclude:: ../../samples/data/quantity_explosion.csv
|
||||||
|
:language: text
|
||||||
|
:linenos:
|
||||||
|
|
@ -72,14 +72,22 @@ module Squib
|
||||||
def yaml(opts = {})
|
def yaml(opts = {})
|
||||||
input = Args::InputFile.new(file: 'deck.yml').load!(opts)
|
input = Args::InputFile.new(file: 'deck.yml').load!(opts)
|
||||||
import = Args::Import.new.load!(opts)
|
import = Args::Import.new.load!(opts)
|
||||||
s = YAML.load_file(input.file[0])
|
yml = YAML.load_file(input.file[0])
|
||||||
data = Squib::DataFrame.new
|
data = Squib::DataFrame.new
|
||||||
# Get a universal list of keys to ensure everything is covered.
|
# Get a universal list of keys to ensure everything is covered.
|
||||||
keys = s.map {|c| c.keys}.flatten.uniq
|
keys = yml.map { |c| c.keys}.flatten.uniq
|
||||||
# Initialize the data frame; why is [] not the default value?
|
keys.each { |k| data[k] = [] } #init arrays
|
||||||
keys.each {|k| data[k] = [] }
|
yml.each do |card|
|
||||||
# Load all cards into the frame, nil value if key isn't set.
|
# nil value if key isn't set.
|
||||||
s.each {|card| keys.each {|k| data[k] << card[k] } }
|
keys.each { |k| data[k] << card[k] }
|
||||||
|
end
|
||||||
|
if block_given?
|
||||||
|
data.each do |header, col|
|
||||||
|
col.map! do |val|
|
||||||
|
yield(header, val)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
explode_quantities(data, import.explode)
|
explode_quantities(data, import.explode)
|
||||||
end
|
end
|
||||||
module_function :yaml
|
module_function :yaml
|
||||||
|
|
|
||||||
|
|
@ -169,4 +169,44 @@ describe Squib::Deck do
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context '#yaml' do
|
||||||
|
it 'loads basic data' do
|
||||||
|
expect(Squib.yaml(file: yaml_file('basic.yml')).to_h).to eq({
|
||||||
|
'Name' => %w(Larry Curly Mo),
|
||||||
|
'Number' => [4.0, 5.0, 6.0], # numbers get auto-converted to integers
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'explodes quantities' do
|
||||||
|
expect(Squib.yaml(explode: 'qty', file: yaml_file('qty.yml')).to_h).to eq({
|
||||||
|
'name' => %w(ha ha he),
|
||||||
|
'qty' => [2, 2, 1],
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'handles silence' do
|
||||||
|
expect(Squib.yaml(file: yaml_file('nilly.yml')).to_h).to eq({
|
||||||
|
'name' => %w(foo bar),
|
||||||
|
'desc' => [nil, 'Hello'],
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'yields to block when given' do
|
||||||
|
data = Squib.yaml(file: yaml_file('basic.yml')) do |header, value|
|
||||||
|
case header
|
||||||
|
when 'Name'
|
||||||
|
'he'
|
||||||
|
when 'Number'
|
||||||
|
value * 2
|
||||||
|
else
|
||||||
|
'ha'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
expect(data.to_h).to eq({
|
||||||
|
'Name' => %w(he he he),
|
||||||
|
'Number' => [8.0, 10.0, 12.0],
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
- Name: Larry
|
||||||
|
Number: 4.0
|
||||||
|
- Name: Curly
|
||||||
|
Number: 5.0
|
||||||
|
- Name: Mo
|
||||||
|
Number: 6.0
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
- name: foo
|
||||||
|
- name: bar
|
||||||
|
desc: Hello
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
- name: ha
|
||||||
|
qty: 2
|
||||||
|
- name: he
|
||||||
|
qty: 1
|
||||||
|
|
@ -46,6 +46,10 @@ def xlsx_file(file)
|
||||||
"#{File.expand_path(File.dirname(__FILE__))}/data/xlsx/#{file}"
|
"#{File.expand_path(File.dirname(__FILE__))}/data/xlsx/#{file}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def yaml_file(file)
|
||||||
|
"#{File.expand_path(File.dirname(__FILE__))}/data/yaml/#{file}"
|
||||||
|
end
|
||||||
|
|
||||||
def project_template(file)
|
def project_template(file)
|
||||||
"#{File.expand_path(File.dirname(__FILE__))}/../lib/squib/project_template/#{file}"
|
"#{File.expand_path(File.dirname(__FILE__))}/../lib/squib/project_template/#{file}"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue