abstract_importer 1.2.1 → 1.3.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.
@@ -0,0 +1,82 @@
1
+ require "test_helper"
2
+
3
+
4
+ class ImporterTest < ActiveSupport::TestCase
5
+
6
+ setup do
7
+ options.merge!(strategy: {students: :insert})
8
+ end
9
+
10
+
11
+
12
+ context "with a simple data source" do
13
+ setup do
14
+ plan do |import|
15
+ import.students
16
+ end
17
+ end
18
+
19
+ should "import the records in batches" do
20
+ mock.proxy(Student).insert_many(satisfy { |arg| arg.length == 3 })
21
+ import!
22
+ assert_equal [456, 457, 458], account.students.pluck(:legacy_id)
23
+ end
24
+ end
25
+
26
+ context "with a complex data source" do
27
+ setup do
28
+ plan do |import|
29
+ import.students
30
+ import.parents
31
+ end
32
+ end
33
+
34
+ should "preserve mappings" do
35
+ import!
36
+ harry = account.students.find_by_name("Harry Potter")
37
+ assert_equal ["James Potter", "Lily Potter"], harry.parents.pluck(:name)
38
+ end
39
+
40
+ should "preserve mappings even when a record was previously imported" do
41
+ harry = account.students.create!(name: "Harry Potter", legacy_id: 456)
42
+ import!
43
+ assert_equal ["James Potter", "Lily Potter"], harry.parents.pluck(:name)
44
+ end
45
+ end
46
+
47
+ context "When records already exist" do
48
+ setup do
49
+ plan do |import|
50
+ import.students
51
+ end
52
+ account.students.create!(name: "Ron Weasley", legacy_id: 457)
53
+ end
54
+
55
+ should "not import existing records twice" do
56
+ import!
57
+ assert_equal 3, account.students.count
58
+ end
59
+ end
60
+
61
+ context "When the import would create a duplicate record" do
62
+ setup do
63
+ plan do |import|
64
+ import.students do |options|
65
+ options.rescue_batch do |batch|
66
+ names = parent.students.pluck :name
67
+ batch.reject! { |student| names.member? student[:name] }
68
+ end
69
+ end
70
+ end
71
+ account.students.create!(name: "Ron Weasley")
72
+ end
73
+
74
+ should "not import existing records twice" do
75
+ import!
76
+ assert_equal 3, account.students.count
77
+ end
78
+ end
79
+
80
+
81
+
82
+ end
@@ -0,0 +1,29 @@
1
+ require "test_helper"
2
+
3
+
4
+ class ReplaceStrategyTest < ActiveSupport::TestCase
5
+
6
+ setup do
7
+ options.merge!(strategy: {students: :replace})
8
+ end
9
+
10
+
11
+
12
+ context "When records already exist" do
13
+ setup do
14
+ plan do |import|
15
+ import.students
16
+ end
17
+ account.students.create!(name: "Ron Weasley", legacy_id: 457)
18
+ end
19
+
20
+ should "reimport the existing records" do
21
+ import!
22
+ assert_equal "Gryffindor", account.students.find_by_name("Ron Weasley").house,
23
+ "Expected Ron's record to have been replaced with one that has a house"
24
+ end
25
+ end
26
+
27
+
28
+
29
+ end
@@ -1,6 +1,6 @@
1
1
  class MockDataSource
2
-
3
-
2
+
3
+
4
4
  def students
5
5
  Enumerator.new do |e|
6
6
  e.yield id: 456, name: "Harry Potter", pet_type: "Owl", pet_id: 901, house: "Gryffindor"
@@ -8,21 +8,21 @@ class MockDataSource
8
8
  e.yield id: 458, name: "Hermione Granger", pet_type: "Cat", pet_id: 901, house: "Gryffindor"
9
9
  end
10
10
  end
11
-
11
+
12
12
  def parents
13
13
  Enumerator.new do |e|
14
14
  e.yield id: 88, name: "James Potter", student_id: 456
15
15
  e.yield id: 89, name: "Lily Potter", student_id: 456
16
16
  end
17
17
  end
18
-
18
+
19
19
  def locations
20
20
  Enumerator.new do |e|
21
21
  e.yield id: 5, slug: "godric's-hollow" # <-- invalid
22
22
  e.yield id: 6, slug: "azkaban"
23
23
  end
24
24
  end
25
-
25
+
26
26
  def subjects
27
27
  Enumerator.new do |e|
28
28
  e.yield id: 49, name: "Care of Magical Creatures", student_ids: [456]
@@ -32,25 +32,25 @@ class MockDataSource
32
32
  e.yield id: 53, name: "Study of Ancient Runes", student_ids: [458]
33
33
  end
34
34
  end
35
-
35
+
36
36
  def grades
37
37
  Enumerator.new do |e|
38
38
  e.yield id: 500, subject_id: 50, student_id: 457, value: "Acceptable"
39
39
  e.yield id: 501, subject_id: 51, student_id: 457, value: "Troll"
40
40
  end
41
41
  end
42
-
42
+
43
43
  def cats
44
44
  Enumerator.new do |e|
45
45
  e.yield id: 901, name: "Crookshanks"
46
46
  end
47
47
  end
48
-
48
+
49
49
  def owls
50
50
  Enumerator.new do |e|
51
51
  e.yield id: 901, name: "Hedwig"
52
52
  end
53
53
  end
54
-
55
-
54
+
55
+
56
56
  end
@@ -3,7 +3,7 @@ class Student < ActiveRecord::Base
3
3
  has_many :grades
4
4
  has_many :parents
5
5
  belongs_to :pet, polymorphic: true
6
-
6
+
7
7
  def report_card
8
8
  subjects.map do |subject|
9
9
  grade = grades.find_by_subject_id(subject.id)
@@ -1,8 +1,8 @@
1
1
  ActiveRecord::Schema.define(:version => 1) do
2
-
2
+
3
3
  create_table "accounts", :force => true do |t|
4
4
  end
5
-
5
+
6
6
  create_table "students", :force => true do |t|
7
7
  t.integer "account_id"
8
8
  t.integer "legacy_id"
@@ -10,26 +10,27 @@ ActiveRecord::Schema.define(:version => 1) do
10
10
  t.string "house"
11
11
  t.string "pet_type"
12
12
  t.integer "pet_id"
13
+ t.index "name", :unique => true
13
14
  end
14
-
15
+
15
16
  create_table "parents", :force => true do |t|
16
17
  t.integer "account_id"
17
18
  t.integer "student_id"
18
19
  t.integer "legacy_id"
19
20
  t.string "name"
20
21
  end
21
-
22
+
22
23
  create_table "locations", :force => true do |t|
23
24
  t.integer "account_id"
24
25
  t.integer "legacy_id"
25
26
  t.string "slug"
26
27
  end
27
-
28
+
28
29
  create_table "students_subjects", :force => true do |t|
29
30
  t.integer "student_id"
30
31
  t.integer "subject_id"
31
32
  end
32
-
33
+
33
34
  create_table "subjects", :force => true do |t|
34
35
  t.integer "account_id"
35
36
  t.integer "legacy_id"
@@ -34,39 +34,39 @@ $io = ENV['VERBOSE'] ? $stderr : File.open("/dev/null", "w")
34
34
 
35
35
 
36
36
  class ActiveSupport::TestCase
37
-
37
+
38
38
  setup do
39
39
  DatabaseCleaner.start
40
-
40
+
41
41
  @data_source = MockDataSource.new
42
42
  @klass = Class.new(AbstractImporter::Base)
43
43
  @account = Account.create!
44
44
  @options = {}
45
45
  end
46
-
46
+
47
47
  teardown do
48
48
  DatabaseCleaner.clean
49
49
  @importer = nil
50
50
  end
51
-
51
+
52
52
  protected
53
-
53
+
54
54
  attr_reader :account, :results, :data_source, :options
55
-
55
+
56
56
  def plan(&block)
57
57
  @klass.import(&block)
58
58
  end
59
-
59
+
60
60
  def depends_on(*args)
61
61
  @klass.depends_on(*args)
62
62
  end
63
-
63
+
64
64
  def import!
65
65
  @results = importer.perform!
66
66
  end
67
-
67
+
68
68
  def importer
69
69
  @importer ||= @klass.new(@account, @data_source, options.merge(io: $io))
70
70
  end
71
-
71
+
72
72
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abstract_importer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Lail
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-29 00:00:00.000000000 Z
11
+ date: 2015-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '4.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord-insert_many
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.1
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -186,6 +200,7 @@ extensions: []
186
200
  extra_rdoc_files: []
187
201
  files:
188
202
  - ".gitignore"
203
+ - ".ruby-version"
189
204
  - ".travis.yml"
190
205
  - Gemfile
191
206
  - LICENSE.txt
@@ -207,11 +222,14 @@ files:
207
222
  - lib/abstract_importer/strategies.rb
208
223
  - lib/abstract_importer/strategies/base.rb
209
224
  - lib/abstract_importer/strategies/default_strategy.rb
225
+ - lib/abstract_importer/strategies/insert_strategy.rb
210
226
  - lib/abstract_importer/strategies/replace_strategy.rb
211
227
  - lib/abstract_importer/summary.rb
212
228
  - lib/abstract_importer/version.rb
213
229
  - test/callback_test.rb
214
- - test/importer_test.rb
230
+ - test/default_strategy_test.rb
231
+ - test/insert_strategy_test.rb
232
+ - test/replace_strategy_test.rb
215
233
  - test/support/mock_data_source.rb
216
234
  - test/support/mock_objects.rb
217
235
  - test/support/schema.rb
@@ -236,13 +254,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
236
254
  version: '0'
237
255
  requirements: []
238
256
  rubyforge_project:
239
- rubygems_version: 2.2.2
257
+ rubygems_version: 2.4.8
240
258
  signing_key:
241
259
  specification_version: 4
242
260
  summary: Provides services for the mass-import of complex relational data
243
261
  test_files:
244
262
  - test/callback_test.rb
245
- - test/importer_test.rb
263
+ - test/default_strategy_test.rb
264
+ - test/insert_strategy_test.rb
265
+ - test/replace_strategy_test.rb
246
266
  - test/support/mock_data_source.rb
247
267
  - test/support/mock_objects.rb
248
268
  - test/support/schema.rb