importu 0.1.0
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.
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/README.md +163 -0
- data/importu.gemspec +29 -0
- data/lib/importu.rb +12 -0
- data/lib/importu/converters.rb +82 -0
- data/lib/importu/core_ext.rb +3 -0
- data/lib/importu/core_ext/array/deep_freeze.rb +7 -0
- data/lib/importu/core_ext/deep_freeze.rb +3 -0
- data/lib/importu/core_ext/hash/deep_freeze.rb +7 -0
- data/lib/importu/core_ext/object/deep_freeze.rb +6 -0
- data/lib/importu/dsl.rb +127 -0
- data/lib/importu/exceptions.rb +34 -0
- data/lib/importu/importer.rb +119 -0
- data/lib/importu/importer/csv.rb +52 -0
- data/lib/importu/importer/json.rb +45 -0
- data/lib/importu/importer/xml.rb +55 -0
- data/lib/importu/record.rb +124 -0
- data/lib/importu/version.rb +3 -0
- data/spec/factories/importer.rb +12 -0
- data/spec/factories/importer_record.rb +13 -0
- data/spec/factories/json_importer.rb +14 -0
- data/spec/factories/xml_importer.rb +12 -0
- data/spec/lib/importu/converters_spec.rb +276 -0
- data/spec/lib/importu/dsl_spec.rb +26 -0
- data/spec/lib/importu/exceptions_spec.rb +96 -0
- data/spec/lib/importu/importer/json_spec.rb +37 -0
- data/spec/lib/importu/importer/xml_spec.rb +14 -0
- data/spec/lib/importu/record_spec.rb +123 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/matchers/delegate_matcher.rb +42 -0
- metadata +218 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Importu::Importer::Xml do
|
4
|
+
subject(:importer) { build(:xml_importer, :infile => infile) }
|
5
|
+
|
6
|
+
context "input file is blank" do
|
7
|
+
let(:infile) { StringIO.new }
|
8
|
+
|
9
|
+
it "raises an InvalidInput exception" do
|
10
|
+
expect { importer }.to raise_error Importu::InvalidInput
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Importu::Record do
|
4
|
+
subject(:record) { build(:importer_record) }
|
5
|
+
|
6
|
+
it "includes Enumerable" do
|
7
|
+
record.should be_a_kind_of(Enumerable)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#importer" do
|
11
|
+
it "returns the importer used during construction" do
|
12
|
+
importer = build(:importer)
|
13
|
+
record = build(:importer_record, :importer => importer)
|
14
|
+
record.importer.should be importer
|
15
|
+
end
|
16
|
+
|
17
|
+
it "is delegated from #preprocessor" do
|
18
|
+
record.should delegate(:preprocessor).to(:importer)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "is delegated from #postprocessor" do
|
22
|
+
record.should delegate(:postprocessor).to(:importer)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "is delegated from #definitions" do
|
26
|
+
record.should delegate(:definitions).to(:importer)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "is delegated from #converters" do
|
30
|
+
record.should delegate(:converters).to(:importer)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#data" do
|
35
|
+
it "returns the data used during construction" do
|
36
|
+
data = { "foo" => "bar" }
|
37
|
+
record = build(:importer_record, :data => data)
|
38
|
+
record.data.should == data
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#raw_data" do
|
43
|
+
it "returns the raw_data used during construction" do
|
44
|
+
raw_data = "this,is\tsome_raw_data\n"
|
45
|
+
record = build(:importer_record, :raw_data => raw_data)
|
46
|
+
record.raw_data.should == raw_data
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#definitions" do
|
51
|
+
it "returns the definitions defined in importer on construction" do
|
52
|
+
importer = build(:importer)
|
53
|
+
importer.stub(:definitions => { :foo => :bar })
|
54
|
+
record = build(:importer_record, :importer => importer)
|
55
|
+
record.definitions.should be importer.definitions
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#record_hash" do
|
60
|
+
it "tries to generate a record hash on first access" do
|
61
|
+
expected = { :foo => 1, :bar => 2 }
|
62
|
+
record.should_receive(:generate_record_hash).and_return(expected)
|
63
|
+
record.record_hash.should eq expected
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should not try to regenerate record hash no subsequent access" do
|
67
|
+
expected = { :foo => 1, :bar => 2 }
|
68
|
+
record.should_receive(:generate_record_hash).once.and_return(expected)
|
69
|
+
record.record_hash
|
70
|
+
record.record_hash.should eq expected
|
71
|
+
end
|
72
|
+
|
73
|
+
it "is aliased from #to_hash" do
|
74
|
+
record.should_receive(:record_hash).and_return(:called)
|
75
|
+
record.to_hash.should == :called
|
76
|
+
end
|
77
|
+
|
78
|
+
it "is delegated from #keys" do
|
79
|
+
record.should delegate(:keys).to(:record_hash)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "is delegated from #values" do
|
83
|
+
record.should delegate(:values).to(:record_hash)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "is delegated from #each" do
|
87
|
+
record.should delegate(:each).to(:record_hash)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "is delegated from #[]" do
|
91
|
+
record.should delegate(:[]).to(:record_hash)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "is delegated from #key?" do
|
95
|
+
record.should delegate(:key?).to(:record_hash)
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#convert" do
|
99
|
+
context "with a :default option" do
|
100
|
+
it "returns data value if data value not nil" do
|
101
|
+
record.converters[:clean] = proc { "value1" }
|
102
|
+
record.convert(:field1, :clean, :default => "foobar").should eq "value1"
|
103
|
+
end
|
104
|
+
|
105
|
+
it "returns default value if data value is nil" do
|
106
|
+
record.converters[:clean] = proc { nil }
|
107
|
+
record.convert(:field1, :clean, :default => "foobar").should eq "foobar"
|
108
|
+
end
|
109
|
+
|
110
|
+
it "returns default value if data field is missing and not required" do
|
111
|
+
record.converters[:clean] = proc { raise Importu::MissingField, "field1" }
|
112
|
+
record.convert(:field1, :clean, :default => "foobar").should eq "foobar"
|
113
|
+
end
|
114
|
+
|
115
|
+
it "raises an exception if data field is missing and is required" do
|
116
|
+
record.converters[:clean] = proc { raise Importu::MissingField, "field1" }
|
117
|
+
expect { record.convert(:field1, :clean, :default => "foobar", :required => true) }.to raise_error(Importu::MissingField)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
ENV['RAILS_ENV'] ||= 'test'
|
2
|
+
|
3
|
+
require 'importu'
|
4
|
+
require 'factory_girl'
|
5
|
+
|
6
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
7
|
+
# in spec/support/ and its subdirectories.
|
8
|
+
Dir[File.expand_path('../support/**/*.rb', __FILE__)].each {|f| require f }
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.include FactoryGirl::Syntax::Methods
|
12
|
+
end
|
13
|
+
|
14
|
+
FactoryGirl.find_definitions
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# https://gist.github.com/807456
|
2
|
+
|
3
|
+
# RSpec matcher to spec delegations.
|
4
|
+
#
|
5
|
+
# Usage:
|
6
|
+
#
|
7
|
+
# describe Post do
|
8
|
+
# it { should delegate(:name).to(:author).with_prefix } # post.author_name
|
9
|
+
# it { should delegate(:month).to(:created_at) }
|
10
|
+
# it { should delegate(:year).to(:created_at) }
|
11
|
+
# end
|
12
|
+
|
13
|
+
RSpec::Matchers.define :delegate do |method|
|
14
|
+
match do |delegator|
|
15
|
+
@method = @prefix ? :"#{@to}_#{method}" : method
|
16
|
+
@delegator = delegator
|
17
|
+
begin
|
18
|
+
@delegator.send(@to)
|
19
|
+
rescue NoMethodError
|
20
|
+
raise "#{@delegator} does not respond to #{@to}!"
|
21
|
+
end
|
22
|
+
@delegator.stub(@to).and_return double('receiver')
|
23
|
+
@delegator.send(@to).stub(method).and_return :called
|
24
|
+
@delegator.send(@method) == :called
|
25
|
+
end
|
26
|
+
|
27
|
+
description do
|
28
|
+
"delegate :#{@method} to its #{@to}#{@prefix ? ' with prefix' : ''}"
|
29
|
+
end
|
30
|
+
|
31
|
+
failure_message_for_should do |text|
|
32
|
+
"expected #{@delegator} to delegate :#{@method} to its #{@to}#{@prefix ? ' with prefix' : ''}"
|
33
|
+
end
|
34
|
+
|
35
|
+
failure_message_for_should_not do |text|
|
36
|
+
"expected #{@delegator} not to delegate :#{@method} to its #{@to}#{@prefix ? ' with prefix' : ''}"
|
37
|
+
end
|
38
|
+
|
39
|
+
chain(:to) { |receiver| @to = receiver }
|
40
|
+
chain(:with_prefix) { @prefix = true }
|
41
|
+
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: importu
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Daniel Hedlund
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-12-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.0.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: activerecord
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 3.0.0
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 3.0.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: multi_json
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: nokogiri
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: bundler
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.0.0
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.0.0
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rspec
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: rdoc
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: factory_girl
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 3.5.0
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 3.5.0
|
142
|
+
description: Importu is a framework for importing data
|
143
|
+
email:
|
144
|
+
- daniel@lincracy.com
|
145
|
+
executables: []
|
146
|
+
extensions: []
|
147
|
+
extra_rdoc_files: []
|
148
|
+
files:
|
149
|
+
- .gitignore
|
150
|
+
- Gemfile
|
151
|
+
- README.md
|
152
|
+
- importu.gemspec
|
153
|
+
- lib/importu.rb
|
154
|
+
- lib/importu/converters.rb
|
155
|
+
- lib/importu/core_ext.rb
|
156
|
+
- lib/importu/core_ext/array/deep_freeze.rb
|
157
|
+
- lib/importu/core_ext/deep_freeze.rb
|
158
|
+
- lib/importu/core_ext/hash/deep_freeze.rb
|
159
|
+
- lib/importu/core_ext/object/deep_freeze.rb
|
160
|
+
- lib/importu/dsl.rb
|
161
|
+
- lib/importu/exceptions.rb
|
162
|
+
- lib/importu/importer.rb
|
163
|
+
- lib/importu/importer/csv.rb
|
164
|
+
- lib/importu/importer/json.rb
|
165
|
+
- lib/importu/importer/xml.rb
|
166
|
+
- lib/importu/record.rb
|
167
|
+
- lib/importu/version.rb
|
168
|
+
- spec/factories/importer.rb
|
169
|
+
- spec/factories/importer_record.rb
|
170
|
+
- spec/factories/json_importer.rb
|
171
|
+
- spec/factories/xml_importer.rb
|
172
|
+
- spec/lib/importu/converters_spec.rb
|
173
|
+
- spec/lib/importu/dsl_spec.rb
|
174
|
+
- spec/lib/importu/exceptions_spec.rb
|
175
|
+
- spec/lib/importu/importer/json_spec.rb
|
176
|
+
- spec/lib/importu/importer/xml_spec.rb
|
177
|
+
- spec/lib/importu/record_spec.rb
|
178
|
+
- spec/spec_helper.rb
|
179
|
+
- spec/support/matchers/delegate_matcher.rb
|
180
|
+
homepage: https://github.com/lincracy/importu
|
181
|
+
licenses:
|
182
|
+
- MIT
|
183
|
+
post_install_message:
|
184
|
+
rdoc_options: []
|
185
|
+
require_paths:
|
186
|
+
- lib
|
187
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
188
|
+
none: false
|
189
|
+
requirements:
|
190
|
+
- - ! '>='
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0'
|
193
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
|
+
none: false
|
195
|
+
requirements:
|
196
|
+
- - ! '>='
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
199
|
+
requirements: []
|
200
|
+
rubyforge_project:
|
201
|
+
rubygems_version: 1.8.23
|
202
|
+
signing_key:
|
203
|
+
specification_version: 3
|
204
|
+
summary: A framework for importing data
|
205
|
+
test_files:
|
206
|
+
- spec/factories/importer.rb
|
207
|
+
- spec/factories/importer_record.rb
|
208
|
+
- spec/factories/json_importer.rb
|
209
|
+
- spec/factories/xml_importer.rb
|
210
|
+
- spec/lib/importu/converters_spec.rb
|
211
|
+
- spec/lib/importu/dsl_spec.rb
|
212
|
+
- spec/lib/importu/exceptions_spec.rb
|
213
|
+
- spec/lib/importu/importer/json_spec.rb
|
214
|
+
- spec/lib/importu/importer/xml_spec.rb
|
215
|
+
- spec/lib/importu/record_spec.rb
|
216
|
+
- spec/spec_helper.rb
|
217
|
+
- spec/support/matchers/delegate_matcher.rb
|
218
|
+
has_rdoc:
|