README.md in csv2hash-0.2.1 vs README.md in csv2hash-0.3.0
- old
+ new
@@ -1,16 +1,15 @@
# Csv2Hash
-[![Code Climate](https://codeclimate.com/github/joel/csv2hash.png)](https://codeclimate.com/github/joel/csv2hash)
+[![Code Climate](https://codeclimate.com/github/FinalCAD/csv2hash.png)](https://codeclimate.com/github/FinalCAD/csv2hash)
-[![Dependency Status](https://gemnasium.com/joel/csv2hash.png)](https://gemnasium.com/joel/csv2hash)
+[![Dependency Status](https://gemnasium.com/FinalCAD/csv2hash.png)](https://gemnasium.com/FinalCAD/csv2hash)
-[![Build Status](https://travis-ci.org/joel/csv2hash.png?branch=master)](https://travis-ci.org/joel/csv2hash) (Travis CI)
+[![Build Status](https://travis-ci.org/FinalCAD/csv2hash.png?branch=master)](https://travis-ci.org/FinalCAD/csv2hash) (Travis CI)
-[![Coverage Status](https://coveralls.io/repos/joel/csv2hash/badge.png)](https://coveralls.io/r/joel/csv2hash)
+[![Coverage Status](https://coveralls.io/repos/FinalCAD/csv2hash/badge.png)](https://coveralls.io/r/FinalCAD/csv2hash)
-
It is a DSL to validate and map a CSV to a Ruby Hash.
## Installation
Add this line to your application's Gemfile:
@@ -29,37 +28,49 @@
Parsing is based on rules, you must defined rules of parsing
### Rules
-You should declare a definition for you CSV, and then define for each cell what you would expect.
+You should declared a definition for you CSV, and then define for each cell what you would expect.
Example :
If you want the very first cell, located on the first line and on the first column to be a string with values are either 'yes' either 'no', you can write the following validation rule:
+```
{ name: 'aswering', type: 'string', values: ['yes', 'no'], position: [0,0] }
+```
:type attribute has 'string' for default value, therefore you can just write this:
+```
{ name: 'aswering', values: ['yes', 'no'], position: [0,0] }
+```
You can define you own message but default message is 'undefined :key on :position'
+```
{ name: 'aswering', values: ['yes', 'no'], position: [0,0], message: 'this value is not supported' }
+```
You can also define Range of values
+```
{ name: 'score', values: 0..5, position: [0,0] }
+```
The message is parsed:
+```
{ ..., message: 'value of :name is not supported, please you one of :values' }
+```
It produces :
+```
value of answering is not supported, please use one of [yes, no]
+```
### Default values
Only position is required:
@@ -75,11 +86,11 @@
* allow_blank: false
* extra_validator: nil
## Define where your data is expected
-**IMPORTANT!** Position mean [Y, X], where Y is rows, X columns
+**IMPORTANT!** Position means [Y, X], where Y is rows, X columns
A definition should be provided. There are 2 types of definitions:
* search for data at a precise position in the table: `y,x`
* or search for data in a column of rows, where all the rows are the same: `x` (column index)
@@ -96,20 +107,21 @@
| Last Name | Doe | yes |
Precise position validation sample:
+```
class MyParser
- attr_accessor :file_path
+ attr_accessor :file_path_or_data
- def initialize file_path
- @file_path = file_path
+ def initialize file_path_or_data
+ @file_path_or_data = file_path_or_data
end
def data
- @data_wrapper ||= Csv2hash.new(definition, file_path).parse
+ @data_wrapper ||= Csv2hash::Main.new(definition, file_path_or_data).parse
end
private
def rules
@@ -122,10 +134,11 @@
def definition
Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::MAPPING, header_size: 1)
end
end
+```
### Validation of a collection (Regular CSV)
Consider the following CSV:
@@ -134,20 +147,21 @@
| jo | John | Doe |
| ja | Jane | Doe |
Collection validation sample:
+```
class MyParser
- attr_accessor :file_path
+ attr_accessor :file_path_or_data
- def initialize file_path
- @file_path = file_path
+ def initialize file_path_or_data
+ @file_path_or_data = file_path_or_data
end
def data
- @data_wrapper ||= Csv2hash.new(definition, file_path).parse
+ @data_wrapper ||= Csv2hash::Main.new(definition, file_path_or_data).parse
end
private
def rules
@@ -161,72 +175,83 @@
def definition
Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::COLLECTION, header_size: 1)
end
end
+```
### Structure validation rules
You may want to validate some structure, like min or max number of columns, definition accepts structure_rules as a key for the third parameter.
Current validations are: MinColumn, MaxColumn
-class MyParser
+```
+ class MyParser
- attr_accessor :file_path
+ attr_accessor :file_path_or_data
- def initialize file_path
- @file_path = file_path
- end
+ def initialize file_path_or_data
+ @file_path_or_data = file_path_or_data
+ end
- def data
- @data_wrapper ||= Csv2hash.new(definition, file_path).parse
- end
+ def data
+ @data_wrapper ||= Csv2hash::Main.new(definition, file_path_or_data).parse
+ end
- private
+ private
- def rules
- [].tap do |mapping|
- mapping << { position: 0, key: 'nickname' }
- mapping << { position: 1, key: 'first_name' }
- mapping << { position: 2, key: 'last_name' }
- end
- end
+ def rules
+ [].tap do |mapping|
+ mapping << { position: 0, key: 'nickname' }
+ mapping << { position: 1, key: 'first_name' }
+ mapping << { position: 2, key: 'last_name' }
+ end
+ end
- def definition
- Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::COLLECTION, structure_rules: { 'MinColumns' => 2, 'MaxColumns' => 3 })
+ def definition
+ Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::COLLECTION,
+ structure_rules: { 'MinColumns' => 2, 'MaxColumns' => 3 })
+ end
end
-end
+```
-
### CSV Headers
You can define the number of rows to skip in the header of the CSV.
+```
Definition.new(rules, type, header_size: 0)
+```
### Parser and configuration
Pasrer can take several parameters like that:
- definition, file_path, exception_mode=true, data_source=nil, ignore_blank_line=false
+```
+ definition, file_path_or_data, exception_mode=true, ignore_blank_line=false
+```
-you can pass directly Array of data (Array at 2 dimensions) really useful for testing, if you don't care about blank lines in your CSV you can ignore them.
+in file_path_or_data attribubte you can pass directly an Array of data (Array with 2 dimensions) really useful for testing, if you don't care about blank lines in your CSV you can ignore them.
### Response
The parser return values wrapper into DataWrapper Object, you can call ```.valid?``` method on this Object and grab either data or errors like that :
+```
response = parser.parse
if response.valid?
response.data
else
response.errors
end
+```
data or errors are Array, but errors can be formatted on csv format with .to_csv call
+```
response.errors.to_csv
+```
## Exception or Not !
You can choose into 2 different modes of parsing, either **exception mode** for raise exception in first breaking rules or **csv mode** for get csv original data + errors throwing into added columns.
@@ -234,17 +259,20 @@
`.parse()` return `data_wrapper` if `.parse()` is invalid, you can code your own behavior:
in your code
- parser = Csv2hash.new(definition, 'file_path').new
+```
+ parser = Csv2hash::Main.new(definition, file_path_or_data, exception_mode=true, ignore_blank_line=false).new
response = parser.parse
return response if response.valid?
# Whatever
+```
In the same time Csv2hash call **notify(response)** method when CSV parsing fail, you can add your own Notifier:
+```
module Csv2hash
module Plugins
class Notifier
def initialize csv2hash
csv2hash.notifier.extend NotifierWithEmail
@@ -260,18 +288,21 @@
end
end
end
end
end
+```
Or other implementation
### Errors Format
errors is a Array of Hash
+```
{ y: 1, x: 0, message: 'message', key: 'key', value: '' }
+```
## Sample
### Csv data
@@ -279,37 +310,64 @@
|-------------|----------------------|
| Nickname | nil |
### Rule
+```
{ position: [1,1], key: 'nickname', allow_blank: false }
+```
### Error
+```
{ y: 1, x: 1, message: 'undefined nikcname on [0, 0]', key: 'nickname', value: nil }
+```
## Personal Validator Rule
You can define your own Validator
For downcase validation
+```
class DowncaseValidator < Csv2hash::ExtraValidator
def valid? value
!!(value.match /^[a-z]+$/)
end
end
+```
in your rule
+```
{ position: [0,0], key: 'name', extra_validator: DowncaseValidator.new,
message: 'your data should be written in lowercase only.' }
+```
Csv data
+```
[ [ 'Foo' ] ]
+```
+# Upgrading from 0.2 to 0.3
+
+```Csv2hash``` become an ```Module```, ```Csv2hash.new``` no longer works, please use ```Csv2hash::Main.new``` instead.
+Signature of ```Csv2hash::Main#new``` has changed too
+
+Prior to 0.3 :
+
+```
+ Csv2Hash.new(definition, file_path, exception_mode=true, data_source=nil, ignore_blank_line=false)
+```
+
+Starting from 0.3 :
+
+```
+ Csv2Hash::Main.new(definition, file_path_or_data, exception_mode=true, ignore_blank_line=false)
+```
+
# Upgrading from 0.1 to 0.2
The signature of Definition#new has changed, the last parameter is a configuration hash, while in versions prior to 0.2 it was an integer (header_size) consider upgrading your code :
Prior to 0.2 :
@@ -317,10 +375,11 @@
```
Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::COLLECTION, 1)
```
Starting from 0.2 :
+
```
Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::COLLECTION, header_size: 1)
```
If no configuration is passed, header_size defaults remains to 0
@@ -329,6 +388,6 @@
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
-5. Create new Pull Request
\ No newline at end of file
+5. Create new Pull Request