stockboy 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +5 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +24 -0
- data/Gemfile +12 -0
- data/Guardfile +10 -0
- data/LICENSE +21 -0
- data/README.md +293 -0
- data/Rakefile +30 -0
- data/lib/stockboy.rb +80 -0
- data/lib/stockboy/attribute.rb +11 -0
- data/lib/stockboy/attribute_map.rb +74 -0
- data/lib/stockboy/candidate_record.rb +130 -0
- data/lib/stockboy/configuration.rb +62 -0
- data/lib/stockboy/configurator.rb +176 -0
- data/lib/stockboy/dsl.rb +68 -0
- data/lib/stockboy/exceptions.rb +3 -0
- data/lib/stockboy/filter.rb +58 -0
- data/lib/stockboy/filter_chain.rb +41 -0
- data/lib/stockboy/filters.rb +11 -0
- data/lib/stockboy/filters/missing_email.rb +37 -0
- data/lib/stockboy/job.rb +241 -0
- data/lib/stockboy/mapped_record.rb +59 -0
- data/lib/stockboy/provider.rb +238 -0
- data/lib/stockboy/providers.rb +11 -0
- data/lib/stockboy/providers/file.rb +135 -0
- data/lib/stockboy/providers/ftp.rb +205 -0
- data/lib/stockboy/providers/http.rb +123 -0
- data/lib/stockboy/providers/imap.rb +290 -0
- data/lib/stockboy/providers/soap.rb +120 -0
- data/lib/stockboy/railtie.rb +28 -0
- data/lib/stockboy/reader.rb +59 -0
- data/lib/stockboy/readers.rb +11 -0
- data/lib/stockboy/readers/csv.rb +115 -0
- data/lib/stockboy/readers/fixed_width.rb +121 -0
- data/lib/stockboy/readers/spreadsheet.rb +144 -0
- data/lib/stockboy/readers/xml.rb +155 -0
- data/lib/stockboy/registry.rb +42 -0
- data/lib/stockboy/source_record.rb +43 -0
- data/lib/stockboy/string_pool.rb +35 -0
- data/lib/stockboy/template_file.rb +44 -0
- data/lib/stockboy/translations.rb +70 -0
- data/lib/stockboy/translations/boolean.rb +58 -0
- data/lib/stockboy/translations/date.rb +41 -0
- data/lib/stockboy/translations/decimal.rb +33 -0
- data/lib/stockboy/translations/default_empty_string.rb +38 -0
- data/lib/stockboy/translations/default_false.rb +41 -0
- data/lib/stockboy/translations/default_nil.rb +38 -0
- data/lib/stockboy/translations/default_true.rb +41 -0
- data/lib/stockboy/translations/default_zero.rb +41 -0
- data/lib/stockboy/translations/integer.rb +33 -0
- data/lib/stockboy/translations/string.rb +33 -0
- data/lib/stockboy/translations/time.rb +41 -0
- data/lib/stockboy/translations/uk_date.rb +51 -0
- data/lib/stockboy/translations/us_date.rb +51 -0
- data/lib/stockboy/translator.rb +66 -0
- data/lib/stockboy/version.rb +3 -0
- data/spec/fixtures/.gitkeep +0 -0
- data/spec/fixtures/files/a_garbage.csv +1 -0
- data/spec/fixtures/files/test_data-20120101.csv +1 -0
- data/spec/fixtures/files/test_data-20120202.csv +1 -0
- data/spec/fixtures/files/z_garbage.csv +1 -0
- data/spec/fixtures/jobs/test_job.rb +1 -0
- data/spec/fixtures/soap/get_list/fault.xml +8 -0
- data/spec/fixtures/soap/get_list/success.xml +18 -0
- data/spec/fixtures/spreadsheets/test_data.xls +0 -0
- data/spec/fixtures/spreadsheets/test_row_options.xls +0 -0
- data/spec/fixtures/xml/body.xml +14 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/stockboy/attribute_map_spec.rb +59 -0
- data/spec/stockboy/attribute_spec.rb +11 -0
- data/spec/stockboy/candidate_record_spec.rb +150 -0
- data/spec/stockboy/configuration_spec.rb +28 -0
- data/spec/stockboy/configurator_spec.rb +127 -0
- data/spec/stockboy/filter_chain_spec.rb +40 -0
- data/spec/stockboy/filter_spec.rb +41 -0
- data/spec/stockboy/filters/missing_email_spec.rb +26 -0
- data/spec/stockboy/filters_spec.rb +38 -0
- data/spec/stockboy/job_spec.rb +238 -0
- data/spec/stockboy/mapped_record_spec.rb +30 -0
- data/spec/stockboy/provider_spec.rb +34 -0
- data/spec/stockboy/providers/file_spec.rb +116 -0
- data/spec/stockboy/providers/ftp_spec.rb +143 -0
- data/spec/stockboy/providers/http_spec.rb +94 -0
- data/spec/stockboy/providers/imap_spec.rb +76 -0
- data/spec/stockboy/providers/soap_spec.rb +107 -0
- data/spec/stockboy/providers_spec.rb +38 -0
- data/spec/stockboy/readers/csv_spec.rb +68 -0
- data/spec/stockboy/readers/fixed_width_spec.rb +52 -0
- data/spec/stockboy/readers/spreadsheet_spec.rb +121 -0
- data/spec/stockboy/readers/xml_spec.rb +94 -0
- data/spec/stockboy/readers_spec.rb +30 -0
- data/spec/stockboy/source_record_spec.rb +19 -0
- data/spec/stockboy/template_file_spec.rb +30 -0
- data/spec/stockboy/translations/boolean_spec.rb +48 -0
- data/spec/stockboy/translations/date_spec.rb +38 -0
- data/spec/stockboy/translations/decimal_spec.rb +23 -0
- data/spec/stockboy/translations/default_empty_string_spec.rb +32 -0
- data/spec/stockboy/translations/default_false_spec.rb +25 -0
- data/spec/stockboy/translations/default_nil_spec.rb +32 -0
- data/spec/stockboy/translations/default_true_spec.rb +25 -0
- data/spec/stockboy/translations/default_zero_spec.rb +32 -0
- data/spec/stockboy/translations/integer_spec.rb +22 -0
- data/spec/stockboy/translations/string_spec.rb +22 -0
- data/spec/stockboy/translations/time_spec.rb +27 -0
- data/spec/stockboy/translations/uk_date_spec.rb +37 -0
- data/spec/stockboy/translations/us_date_spec.rb +37 -0
- data/spec/stockboy/translations_spec.rb +55 -0
- data/spec/stockboy/translator_spec.rb +27 -0
- data/stockboy.gemspec +32 -0
- metadata +305 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9084ee54795b124c1f8d696f121f9bf2c157d203
|
4
|
+
data.tar.gz: e55ec14784707d3c7faa55339a23d2f27832f33d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b2aee64506bd8ac04e4e8cd110fe882b6722e11eeae34ddcb7bfb2f1882615a1d9b82f621ee01ef45ae234ad98b2019bbdfd1e7ec2d2dd6f911e160d30ab4e32
|
7
|
+
data.tar.gz: 70429f68f99fbfb65dfa8cc24bb2c0e20a4a49b6a33b3147ab9e8feeb542fff794d2f45ce3d94d2ab9a168998d52ca7d07881b6b5a8b23aaaf7ed786946b831d
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 0.5.0 / 2013-12-03
|
4
|
+
|
5
|
+
[FEATURE] YARD documentation throughout
|
6
|
+
[FEATURE] Triggers for invoking actions in job context
|
7
|
+
[FEATURE] Add generic `delete_data` method for cleanup of matched files
|
8
|
+
[ENHANCEMENT] Expose provider `client` for reuse
|
9
|
+
[ENHANCEMENT] Expose provider `matching_file` for reuse
|
10
|
+
[BUGFIX] Add missing file validations
|
11
|
+
|
12
|
+
## 0.4.3 / 2013-11-22
|
13
|
+
|
14
|
+
[ENHANCEMENT] Optimize CSV memory usage with shared hash keys
|
15
|
+
[BUGFIX] Missed a required file for SOAP/XML
|
16
|
+
|
17
|
+
## 0.4.2 / 2013-11-21
|
18
|
+
|
19
|
+
[ENHANCEMENT] Use consistent conversion for XML hash keys
|
20
|
+
|
21
|
+
## 0.4.1 / 2013-11-19
|
22
|
+
|
23
|
+
First post!
|
24
|
+
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
group :specs do
|
5
|
+
guard 'rspec' do
|
6
|
+
watch(%r{^spec/.+_spec\.rb$})
|
7
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
8
|
+
watch('spec/spec_helper.rb') { "spec" }
|
9
|
+
end
|
10
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Andrew Vit
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,293 @@
|
|
1
|
+
# Stockboy
|
2
|
+
|
3
|
+
Stockboy helps you receive and unpack data onto your shelves. You might
|
4
|
+
consider using it to synchronize data exported from external sources, or
|
5
|
+
migrating your own data from legacy systems. (TL;DR, Stockboy is a Ruby
|
6
|
+
[DSL][dsl] for doing [ETL][etl].)
|
7
|
+
|
8
|
+
|
9
|
+
## Goals
|
10
|
+
|
11
|
+
Stockboy was originally developed at [Guestfolio][gf] to help synchronize data
|
12
|
+
from many external systems that export periodic reports in various incompatible
|
13
|
+
ways. Each data source might vary orthogonally on:
|
14
|
+
|
15
|
+
* __Where the data resides:__
|
16
|
+
whether a SOAP service, sent to an IMAP mailbox, an FTP server, or simply a
|
17
|
+
local file.
|
18
|
+
* __How the data is formatted:__
|
19
|
+
whether CSV, Excel, XML, JSON, or some other obscure format.
|
20
|
+
* __How the records are structured:__
|
21
|
+
what fields are included, and how they are named.
|
22
|
+
* __What format the fields are:__
|
23
|
+
such as different date formats (DMY vs. MDY), whether names are "first,
|
24
|
+
last", or what do do with missing values.
|
25
|
+
* __Which records to process:__
|
26
|
+
selecting whether records are incomplete, or valid and needing to be added,
|
27
|
+
updated or deleted.
|
28
|
+
|
29
|
+
The goal of Stockboy is to provide a clean, but flexible DSL for declaring
|
30
|
+
these configurations and keeping them external to your application, letting
|
31
|
+
your app standardize on handling one common interface for the many different
|
32
|
+
sources.
|
33
|
+
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
Following your defined job template (see below), a Stockboy job will process
|
38
|
+
incoming data into abstract "records". Stockboy leaves it up to your
|
39
|
+
application to decide what to do with them.
|
40
|
+
|
41
|
+
job = Job.define("my_template")
|
42
|
+
|
43
|
+
job.process
|
44
|
+
records = job.records #=> Hash of records sorted by filter key
|
45
|
+
other = job.unfiltered_records #=> Array of records unmatched by a filter
|
46
|
+
all = job.all_records #=> Array
|
47
|
+
|
48
|
+
Yielding processed results to a block is also supported:
|
49
|
+
|
50
|
+
job.process do |records, unfiltered|
|
51
|
+
records[:updated].each { |r| YourModel.create(r.attributes) }
|
52
|
+
records[:no_data].each { |r| log.warn "No data for #{r.id}" }
|
53
|
+
unfiltered_records.each { |r| log.info "Skipping: #{r.raw_hash}" }
|
54
|
+
end
|
55
|
+
|
56
|
+
### Records
|
57
|
+
|
58
|
+
Each record exposes both the source values and the mapped output values
|
59
|
+
according to your defined mapping. Typically the mapped fields should
|
60
|
+
correspond to the actual attributes on your application models. These can be
|
61
|
+
accessed as individual methods, or by converting the record to a hash.
|
62
|
+
|
63
|
+
record.input["RawEmailField"] # => "ARTHUR@EXAMPLE.COM"
|
64
|
+
record.output.email # => "arthur@example.com"
|
65
|
+
|
66
|
+
record.to_hash or record.attributes
|
67
|
+
#=> {check_in: #<Time ...>, location_id: 123, first_name: "Arthur", ...}
|
68
|
+
|
69
|
+
record.to_model(YourModel) or YourModel.new(record.attributes)
|
70
|
+
#=> #<YourModel ...>
|
71
|
+
|
72
|
+
|
73
|
+
## Job Template DSL
|
74
|
+
|
75
|
+
Stockboy job templates are defined in Ruby but are simple and abstract enough
|
76
|
+
to be considered more _configuration_ than _code_. They should reside in the
|
77
|
+
[template load path](#stockboy-configuration) for easy loading. Once defined,
|
78
|
+
job templates are parsed and loaded at runtime, so they can be added or updated
|
79
|
+
separately without needing to restart a long-running process, e.g. Rails or
|
80
|
+
Sidekiq.
|
81
|
+
|
82
|
+
Writing a job template requires you to declare three parts:
|
83
|
+
|
84
|
+
### Example
|
85
|
+
|
86
|
+
# config/stockboy_jobs/my_template.rb
|
87
|
+
|
88
|
+
provider :ftp do
|
89
|
+
host "example.com"
|
90
|
+
username "mystore"
|
91
|
+
password "123456"
|
92
|
+
file_name "dailyreport-*.csv"
|
93
|
+
file_pick :first
|
94
|
+
end
|
95
|
+
|
96
|
+
reader :csv do
|
97
|
+
headers true
|
98
|
+
col_sep "|"
|
99
|
+
encoding "Windows-1252"
|
100
|
+
end
|
101
|
+
|
102
|
+
attributes do
|
103
|
+
email from: 'RawEmailAddress'
|
104
|
+
first_name as: proc{ |r| r['Full-Name'].split(' ').first }
|
105
|
+
last_name as: proc{ |r| r['Full-Name'].split(' ').last }
|
106
|
+
birthdate as: [:time]
|
107
|
+
score as: [:integer, :default_zero]
|
108
|
+
end
|
109
|
+
|
110
|
+
filter(:invalid_email) do |input, _|
|
111
|
+
not(input.email.include?('@') or input['EmailAddress'] == '')
|
112
|
+
end
|
113
|
+
|
114
|
+
filter(:missing_code) do |_, output|
|
115
|
+
output.product_code.nil?
|
116
|
+
end
|
117
|
+
|
118
|
+
Looking at the parts of this template:
|
119
|
+
|
120
|
+
### 1. Get it with a provider
|
121
|
+
|
122
|
+
The provider block describes the connection parameters for finding and fetching
|
123
|
+
data, which is returned as a raw string blob. It can handle some complexity to
|
124
|
+
determine which file to pick from an email attachment or FTP directory, for
|
125
|
+
example.
|
126
|
+
|
127
|
+
See: [File][file], [FTP][ftp], [HTTP][http], [IMAP][imap], [SOAP][soap]
|
128
|
+
|
129
|
+
[file]: lib/stockboy/providers/file.rb
|
130
|
+
[ftp]: lib/stockboy/providers/ftp.rb
|
131
|
+
[http]: lib/stockboy/providers/http.rb
|
132
|
+
[imap]: lib/stockboy/providers/imap.rb
|
133
|
+
[soap]: lib/stockboy/providers/soap.rb
|
134
|
+
|
135
|
+
|
136
|
+
### 2. Parse it with a reader
|
137
|
+
|
138
|
+
The reader block describes how to turn the raw string from the provider into
|
139
|
+
sets of fields. This extracts the raw data tokens, which we can then map to our
|
140
|
+
application's domain.
|
141
|
+
|
142
|
+
See: [CSV][csv], [Fixed-Width][fix], [Spreadsheet][xls], [XML][xml]
|
143
|
+
|
144
|
+
[csv]: lib/stockboy/readers/csv.rb
|
145
|
+
[fix]: lib/stockboy/readers/fixed_width.rb
|
146
|
+
[xls]: lib/stockboy/readers/spreadsheet.rb
|
147
|
+
[xml]: lib/stockboy/readers/xml.rb
|
148
|
+
|
149
|
+
|
150
|
+
### 3. Collect it into attributes
|
151
|
+
|
152
|
+
The attributes block is the main part of the template definition. This
|
153
|
+
describes which fields to extract from the parsed data, and how to represent
|
154
|
+
each value in the output record. The output attributes are defined by calling
|
155
|
+
the attribute's name plus two options:
|
156
|
+
|
157
|
+
#### from:
|
158
|
+
When the field name from the source doesn't match the desired attribute name,
|
159
|
+
this option should be used to name the correct field to read from the source
|
160
|
+
record.
|
161
|
+
|
162
|
+
#### as:
|
163
|
+
By default, attributes are returned as the original raw string data value, but
|
164
|
+
translators can be applied to change the input to any format. Acceptable
|
165
|
+
options include a symbol for a built-in translator (e.g. `:date`) or any Proc
|
166
|
+
or callable object responding to `call(source_record)`.
|
167
|
+
|
168
|
+
Translator blocks can access record fields as either:
|
169
|
+
|
170
|
+
| Indexes for raw input fields | Methods for final attribute names |
|
171
|
+
| :-------------------------------: | :-------------------------------: |
|
172
|
+
| `->(r){ r['RawEmail'].downcase }` | `->(r){ r.email.downcase }` |
|
173
|
+
|
174
|
+
Since the entire record context is passed, you can combine multiple input
|
175
|
+
fields into one attribute (e.g. combining date plus time). You can also define
|
176
|
+
two attributes that extract different data from the same field, e.g. splitting
|
177
|
+
a full name field into first and last.
|
178
|
+
|
179
|
+
Translations are applied in order when given as an array. Since translators are
|
180
|
+
designed to handle invalid data, they will catch exceptions and return a `nil`
|
181
|
+
so it's a good idea to have default values at the end of the chain.
|
182
|
+
|
183
|
+
#### Built-in attribute translators:
|
184
|
+
|
185
|
+
* [`:boolean`][bool]
|
186
|
+
Common true/false strings to `True` or `False` (e.g. '1'/'0' or 't'/'f')
|
187
|
+
* [`:date`][date]
|
188
|
+
ISO-8601 or common strings to `Date` (e.g. "2012-12-21" or "Dec 12, 2012")
|
189
|
+
* [`:uk_date`][ukda]
|
190
|
+
Date strings from UK format to `Date` (e.g. "DD/MM/YY")
|
191
|
+
* [`:us_date`][usda]
|
192
|
+
Date strings from US format to `Date` (e.g. "MM/DD/YY")
|
193
|
+
* [`:decimal`][deci]
|
194
|
+
Numeric strings to `BigDecimal` (e.g. prices)
|
195
|
+
* [`:integer`][intg]
|
196
|
+
Numeric strings to `Fixnum` integers
|
197
|
+
* [`:string`][stri]
|
198
|
+
Clean strings with leading/trailing whitespace trimmed
|
199
|
+
* [`:or_empty`][dest]
|
200
|
+
Returns `""` for blank values
|
201
|
+
* [`:or_nil`][dest]
|
202
|
+
Returns `nil` for blank values
|
203
|
+
* [`:or_zero`][dzer]
|
204
|
+
Returns `0` for blank values
|
205
|
+
|
206
|
+
[bool]: lib/stockboy/translators/boolean.rb
|
207
|
+
[date]: lib/stockboy/translators/date.rb
|
208
|
+
[deci]: lib/stockboy/translators/decimal.rb
|
209
|
+
[dest]: lib/stockboy/translators/default_empty_string.rb
|
210
|
+
[dnil]: lib/stockboy/translators/default_nil.rb
|
211
|
+
[dzer]: lib/stockboy/translators/default_zero.rb
|
212
|
+
[intg]: lib/stockboy/translators/integer.rb
|
213
|
+
[stri]: lib/stockboy/translators/string.rb
|
214
|
+
[time]: lib/stockboy/translators/time.rb
|
215
|
+
[ukda]: lib/stockboy/translators/uk_date.rb
|
216
|
+
[usda]: lib/stockboy/translators/us_date.rb
|
217
|
+
|
218
|
+
|
219
|
+
### 4. Funnel it with filters
|
220
|
+
|
221
|
+
Filters are optional, but they are very helpful for funneling the data into
|
222
|
+
your workflow. For example, you may need to partition records for different
|
223
|
+
handling based on a status field.
|
224
|
+
|
225
|
+
Filters are applied in the order that they are declared. The first filter that
|
226
|
+
returns `true` when traversing a record will capture it. Records that fall
|
227
|
+
through all the filters without matching anything are considered "unfiltered".
|
228
|
+
|
229
|
+
job.process
|
230
|
+
job.records[:update] #=> Array
|
231
|
+
job.unfiltered_records #=> Array
|
232
|
+
job.all_records #=> Array
|
233
|
+
|
234
|
+
Filters can inspect records either pre- or post-translation. Often you just
|
235
|
+
need to look at the raw input parameters, but it's also possible to get the
|
236
|
+
output values from the second block parameter:
|
237
|
+
|
238
|
+
filter(:example) do |input, output|
|
239
|
+
input["RawEmailAddress"] =~ /gmail/ or output.bounce_count > 1
|
240
|
+
end
|
241
|
+
|
242
|
+
---
|
243
|
+
|
244
|
+
## Installation
|
245
|
+
|
246
|
+
Add `gem 'stockboy'` to your Gemfile and run `bundle install`.
|
247
|
+
|
248
|
+
Supported on Ruby 1.9+.
|
249
|
+
|
250
|
+
|
251
|
+
<a name="stockboy-configuration"></a>
|
252
|
+
## Configuration
|
253
|
+
|
254
|
+
When loaded under a Rails app, Stockboy will look for `config/stockboy.rb` for
|
255
|
+
self-configuration if it's present.
|
256
|
+
|
257
|
+
### Template Load Paths
|
258
|
+
|
259
|
+
Template load paths are intended for storing your defined job templates for
|
260
|
+
different data sources. (`config/stockboy_jobs/` is the default when loaded in
|
261
|
+
a Rails app; else it must be defined.)
|
262
|
+
|
263
|
+
Stockboy.configuration do |config|
|
264
|
+
config.template_load_paths = ['config/job_imports', 'config/log_imports']
|
265
|
+
end
|
266
|
+
|
267
|
+
### Register Custom Providers / Readers
|
268
|
+
|
269
|
+
Beyond the standard providers (`:ftp`, `:soap`, etc.) and readers (`:csv`,
|
270
|
+
`:xml`), you can register your own for fetching or parsing data from different
|
271
|
+
sources. (Contributions welcome.)
|
272
|
+
|
273
|
+
Stockboy::Readers.register :m3u, PlaylistReader
|
274
|
+
Stockboy::Providers.register :gopher, GopherProvider
|
275
|
+
Stockboy::Translations.register :product_code, YourProductCodeTranslator
|
276
|
+
|
277
|
+
See the [Reader][reader], [Provider][provider], and [Translator][translator]
|
278
|
+
for details on implementing your own custom classes.
|
279
|
+
|
280
|
+
[provider]: lib/stockboy/provider.rb
|
281
|
+
[reader]: lib/stockboy/reader.rb
|
282
|
+
[translator]: lib/stockboy/translator.rb
|
283
|
+
|
284
|
+
## Development
|
285
|
+
|
286
|
+
Contributions and pull requests are welcome.
|
287
|
+
|
288
|
+
bundle install
|
289
|
+
bundle exec rake # runs tests
|
290
|
+
|
291
|
+
[gf]: http://guestfolio.com/
|
292
|
+
[etl]: https://en.wikipedia.org/wiki/Extract,_transform,_load
|
293
|
+
[dsl]: https://en.wikipedia.org/wiki/Domain-specific_language
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#
|
2
|
+
# Bundler
|
3
|
+
#
|
4
|
+
|
5
|
+
require "bundler/gem_tasks"
|
6
|
+
|
7
|
+
#
|
8
|
+
# RSpec
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rspec/core/rake_task"
|
12
|
+
RSpec::Core::RakeTask.new
|
13
|
+
|
14
|
+
#
|
15
|
+
# YARD
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'yard'
|
19
|
+
require "yard/rake/yardoc_task"
|
20
|
+
YARD::Rake::YardocTask.new do |t|
|
21
|
+
# t.options += ['--title', "Stockboy Documentation"]
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Stockboy
|
26
|
+
#
|
27
|
+
|
28
|
+
task :default => :spec
|
29
|
+
|
30
|
+
task :test => :spec
|
data/lib/stockboy.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'stockboy/version'
|
2
|
+
require 'stockboy/exceptions'
|
3
|
+
require 'stockboy/dsl'
|
4
|
+
require 'stockboy/job'
|
5
|
+
|
6
|
+
# Registries
|
7
|
+
require 'stockboy/translations'
|
8
|
+
require 'stockboy/providers'
|
9
|
+
require 'stockboy/readers'
|
10
|
+
require 'stockboy/filters'
|
11
|
+
|
12
|
+
# Translations
|
13
|
+
require 'stockboy/translations/default_empty_string'
|
14
|
+
require 'stockboy/translations/default_false'
|
15
|
+
require 'stockboy/translations/default_true'
|
16
|
+
require 'stockboy/translations/default_nil'
|
17
|
+
require 'stockboy/translations/default_zero'
|
18
|
+
require 'stockboy/translations/boolean'
|
19
|
+
require 'stockboy/translations/integer'
|
20
|
+
require 'stockboy/translations/decimal'
|
21
|
+
require 'stockboy/translations/time'
|
22
|
+
require 'stockboy/translations/date'
|
23
|
+
require 'stockboy/translations/us_date'
|
24
|
+
require 'stockboy/translations/uk_date'
|
25
|
+
|
26
|
+
# Filters
|
27
|
+
require 'stockboy/filters/missing_email'
|
28
|
+
|
29
|
+
# Providers
|
30
|
+
require 'stockboy/providers/ftp'
|
31
|
+
require 'stockboy/providers/http'
|
32
|
+
require 'stockboy/providers/imap'
|
33
|
+
require 'stockboy/providers/soap'
|
34
|
+
require 'stockboy/providers/file'
|
35
|
+
|
36
|
+
# Readers
|
37
|
+
require 'stockboy/readers/csv'
|
38
|
+
require 'stockboy/readers/xml'
|
39
|
+
require 'stockboy/readers/fixed_width'
|
40
|
+
require 'stockboy/readers/spreadsheet'
|
41
|
+
|
42
|
+
module Stockboy
|
43
|
+
|
44
|
+
module Filters
|
45
|
+
register :missing_email, MissingEmail
|
46
|
+
end
|
47
|
+
|
48
|
+
module Providers
|
49
|
+
register :file, File
|
50
|
+
register :ftp, FTP
|
51
|
+
register :http, HTTP
|
52
|
+
register :soap, SOAP
|
53
|
+
register :imap, IMAP
|
54
|
+
end
|
55
|
+
|
56
|
+
module Readers
|
57
|
+
register :csv, CSV
|
58
|
+
register :xml, XML
|
59
|
+
register :fixed_width, FixedWidth
|
60
|
+
register :spreadsheet, Spreadsheet
|
61
|
+
end
|
62
|
+
|
63
|
+
module Translations
|
64
|
+
register :or_false, DefaultFalse
|
65
|
+
register :or_true, DefaultTrue
|
66
|
+
register :or_nil, DefaultNil
|
67
|
+
register :or_empty, DefaultEmptyString
|
68
|
+
register :or_zero, DefaultZero
|
69
|
+
register :boolean, Boolean
|
70
|
+
register :integer, Integer
|
71
|
+
register :decimal, Decimal
|
72
|
+
register :time, Time
|
73
|
+
register :date, Date
|
74
|
+
register :us_date, USDate
|
75
|
+
register :uk_date, UKDate
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
require 'stockboy/railtie' if defined? Rails
|