activerecord-import 0.19.0 → 1.0.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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +22 -12
  3. data/CHANGELOG.md +166 -0
  4. data/Gemfile +13 -10
  5. data/README.markdown +548 -5
  6. data/Rakefile +2 -1
  7. data/benchmarks/lib/cli_parser.rb +2 -1
  8. data/gemfiles/5.1.gemfile +1 -0
  9. data/gemfiles/5.2.gemfile +2 -0
  10. data/lib/activerecord-import/adapters/abstract_adapter.rb +2 -2
  11. data/lib/activerecord-import/adapters/mysql_adapter.rb +16 -10
  12. data/lib/activerecord-import/adapters/postgresql_adapter.rb +59 -15
  13. data/lib/activerecord-import/adapters/sqlite3_adapter.rb +126 -3
  14. data/lib/activerecord-import/base.rb +4 -6
  15. data/lib/activerecord-import/import.rb +384 -126
  16. data/lib/activerecord-import/synchronize.rb +1 -1
  17. data/lib/activerecord-import/value_sets_parser.rb +14 -0
  18. data/lib/activerecord-import/version.rb +1 -1
  19. data/lib/activerecord-import.rb +2 -15
  20. data/test/adapters/makara_postgis.rb +1 -0
  21. data/test/import_test.rb +148 -14
  22. data/test/makara_postgis/import_test.rb +8 -0
  23. data/test/models/account.rb +3 -0
  24. data/test/models/bike_maker.rb +7 -0
  25. data/test/models/topic.rb +10 -0
  26. data/test/models/user.rb +3 -0
  27. data/test/models/user_token.rb +4 -0
  28. data/test/schema/generic_schema.rb +20 -0
  29. data/test/schema/mysql2_schema.rb +19 -0
  30. data/test/schema/postgresql_schema.rb +1 -0
  31. data/test/schema/sqlite3_schema.rb +13 -0
  32. data/test/support/factories.rb +9 -8
  33. data/test/support/generate.rb +6 -6
  34. data/test/support/mysql/import_examples.rb +14 -2
  35. data/test/support/postgresql/import_examples.rb +142 -0
  36. data/test/support/shared_examples/on_duplicate_key_update.rb +252 -1
  37. data/test/support/shared_examples/recursive_import.rb +41 -11
  38. data/test/support/sqlite3/import_examples.rb +187 -10
  39. data/test/synchronize_test.rb +8 -0
  40. data/test/test_helper.rb +9 -1
  41. data/test/value_sets_bytes_parser_test.rb +13 -2
  42. metadata +20 -5
  43. data/test/schema/mysql_schema.rb +0 -16
@@ -31,7 +31,7 @@ module ActiveRecord # :nodoc:
31
31
 
32
32
  klass = instances.first.class
33
33
 
34
- fresh_instances = klass.where(conditions).order(order)
34
+ fresh_instances = klass.unscoped.where(conditions).order(order)
35
35
  instances.each do |instance|
36
36
  matched_instance = fresh_instances.detect do |fresh_instance|
37
37
  keys.all? { |key| fresh_instance.send(key) == instance.send(key) }
@@ -1,4 +1,12 @@
1
1
  module ActiveRecord::Import
2
+ class ValueSetTooLargeError < StandardError
3
+ attr_reader :size
4
+ def initialize(msg = "Value set exceeds max size", size = 0)
5
+ @size = size
6
+ super(msg)
7
+ end
8
+ end
9
+
2
10
  class ValueSetsBytesParser
3
11
  attr_reader :reserved_bytes, :max_bytes, :values
4
12
 
@@ -18,6 +26,12 @@ module ActiveRecord::Import
18
26
  current_size = 0
19
27
  values.each_with_index do |val, i|
20
28
  comma_bytes = arr.size
29
+ insert_size = reserved_bytes + val.bytesize
30
+
31
+ if insert_size > max_bytes
32
+ raise ValueSetTooLargeError.new("#{insert_size} bytes exceeds the max allowed for an insert [#{@max_bytes}]", insert_size)
33
+ end
34
+
21
35
  bytes_thus_far = reserved_bytes + current_size + val.bytesize + comma_bytes
22
36
  if bytes_thus_far <= max_bytes
23
37
  current_size += val.bytesize
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Import
3
- VERSION = "0.19.0".freeze
3
+ VERSION = "1.0.0".freeze
4
4
  end
5
5
  end
@@ -1,19 +1,6 @@
1
1
  # rubocop:disable Style/FileName
2
+ require "active_support/lazy_load_hooks"
2
3
 
3
4
  ActiveSupport.on_load(:active_record) do
4
- class ActiveRecord::Base
5
- class << self
6
- def establish_connection_with_activerecord_import(*args)
7
- conn = establish_connection_without_activerecord_import(*args)
8
- if !ActiveRecord.const_defined?(:Import) || !ActiveRecord::Import.respond_to?(:load_from_connection_pool)
9
- require "activerecord-import/base"
10
- end
11
-
12
- ActiveRecord::Import.load_from_connection_pool connection_pool
13
- conn
14
- end
15
- alias establish_connection_without_activerecord_import establish_connection
16
- alias establish_connection establish_connection_with_activerecord_import
17
- end
18
- end
5
+ require "activerecord-import/base"
19
6
  end
@@ -0,0 +1 @@
1
+ ENV["ARE_DB"] = "postgis"
data/test/import_test.rb CHANGED
@@ -86,6 +86,54 @@ describe "#import" do
86
86
  assert_nil t.author_email_address
87
87
  end
88
88
  end
89
+
90
+ context "with extra keys" do
91
+ let(:values) do
92
+ [
93
+ { title: "LDAP", author_name: "Jerry Carter" },
94
+ { title: "Rails Recipes", author_name: "Chad Fowler", author_email_address: "cfowler@test.com" } # author_email_address is unknown
95
+ ]
96
+ end
97
+
98
+ it "should fail when column names are not specified" do
99
+ err = assert_raises ArgumentError do
100
+ Topic.import values, validate: false
101
+ end
102
+
103
+ assert err.message.include? 'Extra keys: [:author_email_address]'
104
+ end
105
+
106
+ it "should succeed when column names are specified" do
107
+ assert_difference "Topic.count", +2 do
108
+ Topic.import columns, values, validate: false
109
+ end
110
+ end
111
+ end
112
+
113
+ context "with missing keys" do
114
+ let(:values) do
115
+ [
116
+ { title: "LDAP", author_name: "Jerry Carter" },
117
+ { title: "Rails Recipes" } # author_name is missing
118
+ ]
119
+ end
120
+
121
+ it "should fail when column names are not specified" do
122
+ err = assert_raises ArgumentError do
123
+ Topic.import values, validate: false
124
+ end
125
+
126
+ assert err.message.include? 'Missing keys: [:author_name]'
127
+ end
128
+
129
+ it "should fail on missing hash key from specified column names" do
130
+ err = assert_raises ArgumentError do
131
+ Topic.import %i(author_name), values, validate: false
132
+ end
133
+
134
+ assert err.message.include? 'Missing keys: [:author_name]'
135
+ end
136
+ end
89
137
  end
90
138
 
91
139
  unless ENV["SKIP_COMPOSITE_PK"]
@@ -121,12 +169,12 @@ describe "#import" do
121
169
  end
122
170
 
123
171
  context "with :validation option" do
124
- let(:columns) { %w(title author_name) }
125
- let(:valid_values) { [["LDAP", "Jerry Carter"], ["Rails Recipes", "Chad Fowler"]] }
126
- let(:valid_values_with_context) { [[1111, "Jerry Carter"], [2222, "Chad Fowler"]] }
127
- let(:invalid_values) { [["The RSpec Book", ""], ["Agile+UX", ""]] }
128
- let(:valid_models) { valid_values.map { |title, author_name| Topic.new(title: title, author_name: author_name) } }
129
- let(:invalid_models) { invalid_values.map { |title, author_name| Topic.new(title: title, author_name: author_name) } }
172
+ let(:columns) { %w(title author_name content) }
173
+ let(:valid_values) { [["LDAP", "Jerry Carter", "Putting Directories to Work."], ["Rails Recipes", "Chad Fowler", "A trusted collection of solutions."]] }
174
+ let(:valid_values_with_context) { [[1111, "Jerry Carter", "1111"], [2222, "Chad Fowler", "2222"]] }
175
+ let(:invalid_values) { [["The RSpec Book", "David Chelimsky", "..."], ["Agile+UX", "", "All about Agile in UX."]] }
176
+ let(:valid_models) { valid_values.map { |title, author_name, content| Topic.new(title: title, author_name: author_name, content: content) } }
177
+ let(:invalid_models) { invalid_values.map { |title, author_name, content| Topic.new(title: title, author_name: author_name, content: content) } }
130
178
 
131
179
  context "with validation checks turned off" do
132
180
  it "should import valid data" do
@@ -162,9 +210,9 @@ describe "#import" do
162
210
  end
163
211
 
164
212
  it "should ignore uniqueness validators" do
165
- Topic.import columns, valid_values, validate: true
213
+ Topic.import columns, valid_values
166
214
  assert_difference "Topic.count", +2 do
167
- Topic.import columns, valid_values, validate: true
215
+ Topic.import columns, valid_values
168
216
  end
169
217
  end
170
218
 
@@ -200,7 +248,7 @@ describe "#import" do
200
248
  end
201
249
 
202
250
  it "should set ids in valid models if adapter supports setting primary key of imported objects" do
203
- if ActiveRecord::Base.support_setting_primary_key_of_imported_objects?
251
+ if ActiveRecord::Base.supports_setting_primary_key_of_imported_objects?
204
252
  Topic.import (invalid_models + valid_models), validate: true
205
253
  assert_nil invalid_models[0].id
206
254
  assert_nil invalid_models[1].id
@@ -210,7 +258,7 @@ describe "#import" do
210
258
  end
211
259
 
212
260
  it "should set ActiveRecord timestamps in valid models if adapter supports setting primary key of imported objects" do
213
- if ActiveRecord::Base.support_setting_primary_key_of_imported_objects?
261
+ if ActiveRecord::Base.supports_setting_primary_key_of_imported_objects?
214
262
  Timecop.freeze(Time.at(0)) do
215
263
  Topic.import (invalid_models + valid_models), validate: true
216
264
  end
@@ -246,6 +294,36 @@ describe "#import" do
246
294
  end
247
295
  end
248
296
  end
297
+
298
+ context "with uniqueness validators included" do
299
+ it "should not import duplicate records" do
300
+ Topic.import columns, valid_values
301
+ assert_no_difference "Topic.count" do
302
+ Topic.import columns, valid_values, validate_uniqueness: true
303
+ end
304
+ end
305
+ end
306
+
307
+ context "when validatoring presence of belongs_to association" do
308
+ it "should not import records without foreign key" do
309
+ assert_no_difference "UserToken.count" do
310
+ UserToken.import [:token], [['12345abcdef67890']]
311
+ end
312
+ end
313
+
314
+ it "should import records with foreign key" do
315
+ assert_difference "UserToken.count", +1 do
316
+ UserToken.import [:user_name, :token], [%w("Bob", "12345abcdef67890")]
317
+ end
318
+ end
319
+
320
+ it "should not mutate the defined validations" do
321
+ UserToken.import [:user_name, :token], [%w("Bob", "12345abcdef67890")]
322
+ ut = UserToken.new
323
+ ut.valid?
324
+ assert_includes ut.errors.messages, :user
325
+ end
326
+ end
249
327
  end
250
328
 
251
329
  context "without :validation option" do
@@ -320,7 +398,7 @@ describe "#import" do
320
398
 
321
399
  it "doesn't reload any data (doesn't work)" do
322
400
  Topic.import new_topics, synchronize: new_topics
323
- if Topic.support_setting_primary_key_of_imported_objects?
401
+ if Topic.supports_setting_primary_key_of_imported_objects?
324
402
  assert new_topics.all?(&:persisted?), "Records should have been reloaded"
325
403
  else
326
404
  assert new_topics.all?(&:new_record?), "No record should have been reloaded"
@@ -442,11 +520,11 @@ describe "#import" do
442
520
 
443
521
  context "when the timestamps columns are present" do
444
522
  setup do
445
- @existing_book = Book.create(title: "Fell", author_name: "Curry", publisher: "Bayer", created_at: 2.years.ago.utc, created_on: 2.years.ago.utc)
523
+ @existing_book = Book.create(title: "Fell", author_name: "Curry", publisher: "Bayer", created_at: 2.years.ago.utc, created_on: 2.years.ago.utc, updated_at: 2.years.ago.utc, updated_on: 2.years.ago.utc)
446
524
  ActiveRecord::Base.default_timezone = :utc
447
525
  Timecop.freeze(time) do
448
526
  assert_difference "Book.count", +2 do
449
- Book.import %w(title author_name publisher created_at created_on), [["LDAP", "Big Bird", "Del Rey", nil, nil], [@existing_book.title, @existing_book.author_name, @existing_book.publisher, @existing_book.created_at, @existing_book.created_on]]
527
+ Book.import %w(title author_name publisher created_at created_on updated_at updated_on), [["LDAP", "Big Bird", "Del Rey", nil, nil, nil, nil], [@existing_book.title, @existing_book.author_name, @existing_book.publisher, @existing_book.created_at, @existing_book.created_on, @existing_book.updated_at, @existing_book.updated_on]]
450
528
  end
451
529
  end
452
530
  @new_book, @existing_book = Book.last 2
@@ -475,6 +553,23 @@ describe "#import" do
475
553
  it "should set the updated_on column for new records" do
476
554
  assert_in_delta time.to_i, @new_book.updated_on.to_i, 1.second
477
555
  end
556
+
557
+ it "should not set the updated_at column for existing records" do
558
+ assert_equal 2.years.ago.utc.strftime("%Y:%d"), @existing_book.updated_at.strftime("%Y:%d")
559
+ end
560
+
561
+ it "should not set the updated_on column for existing records" do
562
+ assert_equal 2.years.ago.utc.strftime("%Y:%d"), @existing_book.updated_on.strftime("%Y:%d")
563
+ end
564
+
565
+ it "should not set the updated_at column on models if changed" do
566
+ timestamp = Time.now.utc
567
+ books = [
568
+ Book.new(author_name: "Foo", title: "Baz", created_at: timestamp, updated_at: timestamp)
569
+ ]
570
+ Book.import books
571
+ assert_equal timestamp.strftime("%Y:%d"), Book.last.updated_at.strftime("%Y:%d")
572
+ end
478
573
  end
479
574
 
480
575
  context "when a custom time zone is set" do
@@ -519,7 +614,7 @@ describe "#import" do
519
614
 
520
615
  context "importing through an association scope" do
521
616
  { has_many: :chapters, polymorphic: :discounts }.each do |association_type, association|
522
- book = FactoryGirl.create :book
617
+ book = FactoryBot.create :book
523
618
  scope = book.public_send association
524
619
  klass = { chapters: Chapter, discounts: Discount }[association]
525
620
  column = { chapters: :title, discounts: :amount }[association]
@@ -541,10 +636,35 @@ describe "#import" do
541
636
 
542
637
  assert_equal [val1, val2], scope.map(&column).sort
543
638
  end
639
+
640
+ it "works importing array of hashes" do
641
+ scope.import [{ column => val1 }, { column => val2 }]
642
+
643
+ assert_equal [val1, val2], scope.map(&column).sort
644
+ end
645
+ end
646
+
647
+ it "works with a non-standard association primary key" do
648
+ user = User.create(id: 1, name: 'Solomon')
649
+ user.user_tokens.import [:id, :token], [[5, '12345abcdef67890']]
650
+
651
+ token = UserToken.find(5)
652
+ assert_equal 'Solomon', token.user_name
544
653
  end
545
654
  end
546
655
  end
547
656
 
657
+ context "importing model with polymorphic belongs_to" do
658
+ it "works without error" do
659
+ book = FactoryBot.create :book
660
+ discount = Discount.new(discountable: book)
661
+
662
+ Discount.import([discount])
663
+
664
+ assert_equal 1, Discount.count
665
+ end
666
+ end
667
+
548
668
  context 'When importing models with Enum fields' do
549
669
  it 'should be able to import enum fields' do
550
670
  Book.delete_all if Book.count > 0
@@ -760,5 +880,19 @@ describe "#import" do
760
880
  end
761
881
  end
762
882
  end
883
+
884
+ context "with objects that respond to .to_sql as values" do
885
+ let(:columns) { %w(title author_name) }
886
+ let(:valid_values) { [["LDAP", Book.select("'Jerry Carter'").limit(1)], ["Rails Recipes", Book.select("'Chad Fowler'").limit(1)]] }
887
+
888
+ it "should import data" do
889
+ assert_difference "Topic.count", +2 do
890
+ Topic.import! columns, valid_values
891
+ topics = Topic.all
892
+ assert_equal "Jerry Carter", topics.first.author_name
893
+ assert_equal "Chad Fowler", topics.last.author_name
894
+ end
895
+ end
896
+ end
763
897
  end
764
898
  end
@@ -0,0 +1,8 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../support/postgresql/import_examples')
3
+
4
+ should_support_postgresql_import_functionality
5
+
6
+ if ActiveRecord::Base.connection.supports_on_duplicate_key_update?
7
+ should_support_postgresql_upsert_functionality
8
+ end
@@ -0,0 +1,3 @@
1
+ class Account < ActiveRecord::Base
2
+ self.locking_column = :lock
3
+ end
@@ -0,0 +1,7 @@
1
+ module Bike
2
+ def self.table_name_prefix
3
+ 'bike_'
4
+ end
5
+ class Maker < ActiveRecord::Base
6
+ end
7
+ end
data/test/models/topic.rb CHANGED
@@ -2,6 +2,8 @@ class Topic < ActiveRecord::Base
2
2
  validates_presence_of :author_name
3
3
  validates :title, numericality: { only_integer: true }, on: :context_test
4
4
  validates :title, uniqueness: true
5
+ validates :content, uniqueness: true
6
+ validates :word_count, numericality: { greater_than: 0 }, if: :content?
5
7
 
6
8
  validate -> { errors.add(:title, :validate_failed) if title == 'validate_failed' }
7
9
  before_validation -> { errors.add(:title, :invalid) if title == 'invalid' }
@@ -10,4 +12,12 @@ class Topic < ActiveRecord::Base
10
12
  belongs_to :parent, class_name: "Topic"
11
13
 
12
14
  composed_of :description, mapping: [%w(title title), %w(author_name author_name)], allow_nil: true, class_name: "TopicDescription"
15
+
16
+ default_scope { where(approved: true) }
17
+
18
+ private
19
+
20
+ def word_count
21
+ @word_count ||= content.to_s.scan(/\w+/).count
22
+ end
13
23
  end
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ has_many :user_tokens, primary_key: :name, foreign_key: :user_name
3
+ end
@@ -0,0 +1,4 @@
1
+ class UserToken < ActiveRecord::Base
2
+ belongs_to :user, primary_key: :name, foreign_key: :user_name
3
+ validates :user, presence: true
4
+ end
@@ -159,6 +159,26 @@ ActiveRecord::Schema.define do
159
159
  t.string :Features
160
160
  end
161
161
 
162
+ create_table :users, force: :cascade do |t|
163
+ t.string :name, null: false
164
+ t.integer :lock_version, null: false, default: 0
165
+ end
166
+
167
+ create_table :user_tokens, force: :cascade do |t|
168
+ t.string :user_name, null: false
169
+ t.string :token, null: false
170
+ end
171
+
172
+ create_table :accounts, force: :cascade do |t|
173
+ t.string :name, null: false
174
+ t.integer :lock, null: false, default: 0
175
+ end
176
+
177
+ create_table :bike_makers, force: :cascade do |t|
178
+ t.string :name, null: false
179
+ t.integer :lock_version, null: false, default: 0
180
+ end
181
+
162
182
  add_index :cars, :Name, unique: true
163
183
 
164
184
  unless ENV["SKIP_COMPOSITE_PK"]
@@ -0,0 +1,19 @@
1
+ ActiveRecord::Schema.define do
2
+ create_table :books, force: :cascade do |t|
3
+ t.string :title, null: false
4
+ t.virtual :upper_title, type: :string, as: "upper(`title`)" if t.respond_to?(:virtual)
5
+ t.string :publisher, null: false, default: 'Default Publisher'
6
+ t.string :author_name, null: false
7
+ t.datetime :created_at
8
+ t.datetime :created_on
9
+ t.datetime :updated_at
10
+ t.datetime :updated_on
11
+ t.date :publish_date
12
+ t.integer :topic_id
13
+ t.integer :tag_id
14
+ t.integer :publisher_id
15
+ t.boolean :for_sale, default: true
16
+ t.integer :status, default: 0
17
+ t.string :type
18
+ end
19
+ end
@@ -36,6 +36,7 @@ ActiveRecord::Schema.define do
36
36
  t.column :alarm_type, :integer, null: false
37
37
  t.column :status, :integer, null: false
38
38
  t.column :metadata, :text
39
+ t.column :secret_key, :binary
39
40
  t.datetime :created_at
40
41
  t.datetime :updated_at
41
42
  end
@@ -0,0 +1,13 @@
1
+ ActiveRecord::Schema.define do
2
+ create_table :alarms, force: true do |t|
3
+ t.column :device_id, :integer, null: false
4
+ t.column :alarm_type, :integer, null: false
5
+ t.column :status, :integer, null: false
6
+ t.column :metadata, :text
7
+ t.column :secret_key, :binary
8
+ t.datetime :created_at
9
+ t.datetime :updated_at
10
+ end
11
+
12
+ add_index :alarms, [:device_id, :alarm_type], unique: true, where: 'status <> 0'
13
+ end
@@ -1,4 +1,4 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  sequence(:book_title) { |n| "Book #{n}" }
3
3
  sequence(:chapter_title) { |n| "Chapter #{n}" }
4
4
  sequence(:end_note) { |n| "Endnote #{n}" }
@@ -9,12 +9,13 @@ FactoryGirl.define do
9
9
 
10
10
  factory :invalid_topic, class: "Topic" do
11
11
  sequence(:title) { |n| "Title #{n}" }
12
- author_name nil
12
+ author_name { nil }
13
13
  end
14
14
 
15
15
  factory :topic do
16
16
  sequence(:title) { |n| "Title #{n}" }
17
17
  sequence(:author_name) { |n| "Author #{n}" }
18
+ sequence(:content) { |n| "Content #{n}" }
18
19
  end
19
20
 
20
21
  factory :widget do
@@ -26,7 +27,7 @@ FactoryGirl.define do
26
27
 
27
28
  trait :with_rule do
28
29
  after(:build) do |question|
29
- question.build_rule(FactoryGirl.attributes_for(:rule))
30
+ question.build_rule(FactoryBot.attributes_for(:rule))
30
31
  end
31
32
  end
32
33
  end
@@ -39,21 +40,21 @@ FactoryGirl.define do
39
40
  factory :topic_with_book, parent: :topic do
40
41
  after(:build) do |topic|
41
42
  2.times do
42
- book = topic.books.build(title: FactoryGirl.generate(:book_title), author_name: 'Stephen King')
43
+ book = topic.books.build(title: FactoryBot.generate(:book_title), author_name: 'Stephen King')
43
44
  3.times do
44
- book.chapters.build(title: FactoryGirl.generate(:chapter_title))
45
+ book.chapters.build(title: FactoryBot.generate(:chapter_title))
45
46
  end
46
47
 
47
48
  4.times do
48
- book.end_notes.build(note: FactoryGirl.generate(:end_note))
49
+ book.end_notes.build(note: FactoryBot.generate(:end_note))
49
50
  end
50
51
  end
51
52
  end
52
53
  end
53
54
 
54
55
  factory :book do
55
- title 'Tortilla Flat'
56
- author_name 'John Steinbeck'
56
+ title { 'Tortilla Flat' }
57
+ author_name { 'John Steinbeck' }
57
58
  end
58
59
 
59
60
  factory :car do
@@ -2,28 +2,28 @@ class ActiveSupport::TestCase
2
2
  def Build(*args) # rubocop:disable Style/MethodName
3
3
  n = args.shift if args.first.is_a?(Numeric)
4
4
  factory = args.shift
5
- factory_girl_args = args.shift || {}
5
+ factory_bot_args = args.shift || {}
6
6
 
7
7
  if n
8
8
  [].tap do |collection|
9
- n.times.each { collection << FactoryGirl.build(factory.to_s.singularize.to_sym, factory_girl_args) }
9
+ n.times.each { collection << FactoryBot.build(factory.to_s.singularize.to_sym, factory_bot_args) }
10
10
  end
11
11
  else
12
- FactoryGirl.build(factory.to_s.singularize.to_sym, factory_girl_args)
12
+ FactoryBot.build(factory.to_s.singularize.to_sym, factory_bot_args)
13
13
  end
14
14
  end
15
15
 
16
16
  def Generate(*args) # rubocop:disable Style/MethodName
17
17
  n = args.shift if args.first.is_a?(Numeric)
18
18
  factory = args.shift
19
- factory_girl_args = args.shift || {}
19
+ factory_bot_args = args.shift || {}
20
20
 
21
21
  if n
22
22
  [].tap do |collection|
23
- n.times.each { collection << FactoryGirl.create(factory.to_s.singularize.to_sym, factory_girl_args) }
23
+ n.times.each { collection << FactoryBot.create(factory.to_s.singularize.to_sym, factory_bot_args) }
24
24
  end
25
25
  else
26
- FactoryGirl.create(factory.to_s.singularize.to_sym, factory_girl_args)
26
+ FactoryBot.create(factory.to_s.singularize.to_sym, factory_bot_args)
27
27
  end
28
28
  end
29
29
  end
@@ -64,8 +64,8 @@ def should_support_mysql_import_functionality
64
64
  let(:columns) { %w(id author_name title) }
65
65
 
66
66
  setup do
67
- topics << Topic.create!(title: "LDAP", author_name: "Big Bird")
68
- topics << Topic.create!(title: "Rails Recipes", author_name: "Elmo")
67
+ topics << Topic.create!(title: "LDAP", author_name: "Big Bird", content: "Putting Directories to Work.")
68
+ topics << Topic.create!(title: "Rails Recipes", author_name: "Elmo", content: "A trusted collection of solutions.")
69
69
  end
70
70
 
71
71
  it "synchronizes passed in ActiveRecord model instances with the data just imported" do
@@ -82,5 +82,17 @@ def should_support_mysql_import_functionality
82
82
  assert_equal "Chad Fowler", topics.last.author_name, "wrong author!"
83
83
  end
84
84
  end
85
+
86
+ if ENV['AR_VERSION'].to_f >= 5.1
87
+ context "with virtual columns" do
88
+ let(:books) { [Book.new(author_name: "foo", title: "bar")] }
89
+
90
+ it "ignores virtual columns and creates record" do
91
+ assert_difference "Book.count", +1 do
92
+ Book.import books
93
+ end
94
+ end
95
+ end
96
+ end
85
97
  end
86
98
  end