cascade-rb 0.1.2 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e7c151d9e2391755cff0beda2f782a240b9d2ad
4
- data.tar.gz: cf31282323bff8bc1c8f14125e758dbbd62a55d0
3
+ metadata.gz: e76a5428ad502dfd46ba38144264758b9db61701
4
+ data.tar.gz: c806af678c7b76c650100d0468b10894d6fd1e6d
5
5
  SHA512:
6
- metadata.gz: aa602951882137f43d3ba53173a592a0ff5c62354726ba3b4bca9ee8645aa64e5eb90e712d81b5ded63064fde8399c1b3a87854a9a91d532d1c5de75d0d62f69
7
- data.tar.gz: 976a18f137dc262bd9862ef366ca24f93211c40aaeb5b7418045557292ca06c337d7eb4ce2fda0d9c8c029c9df2f4c9a46d6f2e71da2dfd36c22717c2dd017a2
6
+ metadata.gz: 81b4fee7d44a42ae18deea8c2cb61c7629bd56703350833f9cd0e3e52b01b1809c38e8a4c709d9cdfe7c596c9680e4079fb8c5c18b0cc289d4d118b67e6e0425
7
+ data.tar.gz: 12fb5bf658fd193b8dd92a45f90b9de140f834f534e3902fe0948f90b7507fdd6bb73a789ce70a9feeb12bed6e4901232eb886855046b22d47b6b77dc9c2af32
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # [Cascade]
2
2
 
3
- [![Codeship Status for ignat-zakrevsky/cascade](https://codeship.com/projects/d7590880-9943-0132-4aa6-1e41bc68e178/status?branch=master)](https://codeship.com/projects/63625) [![Code Climate](https://codeclimate.com/github/ignat-zakrevsky/cascade/badges/gpa.svg)](https://codeclimate.com/github/ignat-zakrevsky/cascade) [![Test Coverage](https://codeclimate.com/github/ignat-zakrevsky/cascade/badges/coverage.svg)](https://codeclimate.com/github/ignat-zakrevsky/cascade)
3
+ [![Codeship Status for ignat-zakrevsky/cascade](https://codeship.com/projects/d7590880-9943-0132-4aa6-1e41bc68e178/status?branch=master)](https://codeship.com/projects/63625) [![Code Climate](https://codeclimate.com/github/ignat-zakrevsky/cascade/badges/gpa.svg)](https://codeclimate.com/github/ignat-zakrevsky/cascade) [![Test Coverage](https://codeclimate.com/github/ignat-zakrevsky/cascade/badges/coverage.svg)](https://codeclimate.com/github/ignat-zakrevsky/cascade) [![Gem Version](https://badge.fury.io/rb/cascade-rb.svg)](http://badge.fury.io/rb/cascade-rb)
4
4
 
5
- The main aim of this repo is to provide some kind of template for parsers.
5
+ The main aim of this gem is to provide some kind of template for parsing files.
6
6
  Usually, parsing file process contains next steps:
7
7
 
8
8
  1. Retreiving info from file
@@ -15,11 +15,108 @@ Usually, parsing file process contains next steps:
15
15
 
16
16
  Cascade pretends to simplify main part of this step to save your time.
17
17
 
18
+ ## Examples
19
+
20
+ [Minimal working example](https://github.com/ignat-zakrevsky/cascade-example)
21
+
22
+ [More complicated example](https://github.com/ignat-zakrevsky/cascade-example/tree/json-example)
23
+
24
+ ## Installation
25
+ Install the cascade-rb package from Rubygems:
26
+ ```
27
+ gem install cascade-rb
28
+ ```
29
+
30
+ or add it to your Gemfile for Bundler:
31
+ ```ruby
32
+ gem 'cascade-rb'
33
+ ```
34
+
18
35
  ## Usage
19
- - Configure database config
20
- `cp config/database.yml.sample config/database.yml`
21
- - Change `./config/columns_match.yml` to correspond your scheme
22
- - Create necessary ActiveRecord models
23
- - Add necessary parsers
24
- - Run it
36
+ Require gem files
37
+ ```ruby
38
+ require 'cascade'
39
+ ```
40
+
41
+ Configure it!
42
+ ```ruby
43
+ Cascade.configuration do
44
+ # [Object#call] will be used for undefined fields types
45
+ Cascade::RowProcessor.deafult_presenter
46
+ # [Boolean] will throw exception in case of unavailable presenter
47
+ Cascade::RowProcessor.use_default_presenter
48
+ # [String] filepath with columns mapping, see below
49
+ Cascade::ColumnsMatching.mapping_file
50
+ # [Boolean] will raise fields parsing exceptions
51
+ Cascade::ErrorHandler.raise_parse_errors
52
+ end
53
+ ```
54
+
55
+ Provide file for parsing and run it!
56
+ ```ruby
57
+ Cascade::DataParser.new("data_test.txt").call
58
+ ```
59
+
60
+ ## Columns mapping
61
+ Parsing file description should have next structure [(example)](https://github.com/ignat-zakrevsky/cascade-example/blob/master/columns_mapping.yml)
62
+ ```yaml
63
+ mapping:
64
+ name: type
65
+ ```
66
+
67
+ ## Columns parsing
68
+ There are several alredy defined fields parsers (types):
69
+
70
+ - currency
71
+ - boolean
72
+ - country_iso
73
+ - string
74
+
75
+ Feel free to add new fields parsers and provide it through PR.
25
76
 
77
+ ## Components replaceability
78
+ There is a lot of DI in this gem, so, you can replace each component of the parser. Let's assume you want to parse JSON files instead of CSV, save this to ActiveRecord model, and you need Date fields parsing, ok!
79
+ Writing new data provider:
80
+ ```ruby
81
+ class ParserJSON
82
+ def open(file)
83
+ JSON.parse(File.read(file))["rows"]
84
+ end
85
+ end
86
+ ```
87
+ Writing new data saver:
88
+ ```ruby
89
+ class PersonDataSaver
90
+ def call(person_data)
91
+ Person.create!(person_data)
92
+ end
93
+ end
94
+ ```
95
+ considering that there is no much logic even better
96
+ ```ruby
97
+ PERSON_SAVER = -> (person_data) { Person.create!(person_data) }
98
+ ```
99
+ Writing date parser:
100
+ ```ruby
101
+ class DateParser
102
+ def call(value)
103
+ Date.parse(value)
104
+ end
105
+ end
106
+ ```
107
+ or you can always use lambdas for such logic
108
+ ```ruby
109
+ DATE_PARSER = -> (value) { Date.parse(value) }
110
+ ```
111
+ Provide all this stuff into data parser
112
+ ```ruby
113
+ Cascade::DataParser.new("data_test.json",
114
+ row_processor: Cascade::RowProcessor.new(date: DateParser.new),
115
+ data_provider: ParserJSON.new,
116
+ data_saver: PERSON_SAVER
117
+ ).call
118
+ ```
119
+ And that's all!
120
+ [Example](https://github.com/ignat-zakrevsky/cascade-example/blob/json-example/main.rb)
121
+ ## Conventions
122
+ I'm fan of callable object as consequence I prefer #call methods for classes with one responsibility. [Nice video](http://www.rubytapas.com/episodes/35-Callable) that describes benefits of such approach
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Ignat Zakrevsky"]
10
10
  spec.email = %w(iezakrevsky@gmail.com)
11
11
  spec.summary = "Ruby data parser gem."
12
- spec.description = "Highly customizable ruby parser with a lot of DI"
12
+ spec.description = "Highly customizable data parser with a lot of DI"
13
13
  spec.homepage = "https://github.com/ignat-zakrevsky/cascade"
14
14
  spec.license = "MIT"
15
15
 
@@ -1,6 +1,7 @@
1
1
  require "cascade/version"
2
2
  require "cascade/columns_matching"
3
3
  require "cascade/row_processor"
4
+ require "cascade/error_handler"
4
5
  require "cascade/helpers/configuration"
5
6
 
6
7
  # Base gem module
@@ -1,5 +1,11 @@
1
+ require "cascade/helpers/configuration"
2
+
1
3
  module Cascade
2
4
  class ErrorHandler
5
+ extend Configuration
6
+
7
+ define_setting :raise_parse_errors, false
8
+
3
9
  HANDLING_EXCEPTIONS = [IsoCountryCodes::UnknownCodeError, IndexError]
4
10
  DEFAULT_ERROR_STORE = ->(row, reason) do
5
11
  @errors ||= []
@@ -8,6 +14,9 @@ module Cascade
8
14
 
9
15
  def initialize(options = {})
10
16
  @error_store = options.fetch(:error_store) { DEFAULT_ERROR_STORE }
17
+ @handling_exceptions = options.fetch(:handling_exceptions) do
18
+ HANDLING_EXCEPTIONS
19
+ end
11
20
  end
12
21
 
13
22
  # Runs passed block with catching throwing errors and storing in ErrorStore
@@ -16,8 +25,9 @@ module Cascade
16
25
  # problems with processing
17
26
  def with_errors_handling(row)
18
27
  yield
19
- rescue *HANDLING_EXCEPTIONS => exception
28
+ rescue *@handling_exceptions => exception
20
29
  @error_store.call(row, exception.to_s)
30
+ raise exception if self.class.raise_parse_errors
21
31
  end
22
32
  end
23
33
  end
@@ -1,5 +1,9 @@
1
1
  class Hash
2
- def reverse_merge(other_hash)
3
- other_hash.merge(self)
2
+ unless Hash.instance_methods.include? :reverse_merge
3
+ # Merges the caller into +other_hash+
4
+ #
5
+ def reverse_merge(other_hash)
6
+ other_hash.merge(self)
7
+ end
4
8
  end
5
9
  end
@@ -1,4 +1,4 @@
1
1
  module Cascade
2
2
  # current gem version
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.5"
4
4
  end
@@ -21,6 +21,14 @@ describe Cascade::ErrorHandler do
21
21
  subject.with_errors_handling(row) { raise exception }
22
22
  assert_includes @errors, [row, exception.to_s]
23
23
  end
24
+
25
+ it "raises #{exception} if raise_parse_errors setting is true" do
26
+ described_class.stub(:raise_parse_errors, true) do
27
+ assert_raises(exception) do
28
+ subject.with_errors_handling(row) { raise exception }
29
+ end
30
+ end
31
+ end
24
32
  end
25
33
 
26
34
  describe "DEFAULT_ERROR_STORE" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cascade-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ignat Zakrevsky
@@ -178,7 +178,7 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
- description: Highly customizable ruby parser with a lot of DI
181
+ description: Highly customizable data parser with a lot of DI
182
182
  email:
183
183
  - iezakrevsky@gmail.com
184
184
  executables: []
@@ -189,7 +189,6 @@ files:
189
189
  - ".hound.yml"
190
190
  - ".ruby-style.yml"
191
191
  - Gemfile
192
- - Gemfile.lock
193
192
  - README.md
194
193
  - Rakefile
195
194
  - cascade.gemspec
@@ -276,3 +275,4 @@ test_files:
276
275
  - spec/lib/statistics_stores/array_store_spec.rb
277
276
  - spec/lib/statistics_stores/counter_store_spec.rb
278
277
  - spec/spec_helper.rb
278
+ has_rdoc: