abstract_importer 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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