activerecord-import 1.8.1 → 2.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yaml +18 -4
  3. data/CHANGELOG.md +23 -0
  4. data/Gemfile +5 -11
  5. data/README.markdown +2 -2
  6. data/Rakefile +2 -0
  7. data/benchmarks/benchmark.rb +0 -2
  8. data/benchmarks/lib/base.rb +6 -3
  9. data/benchmarks/lib/cli_parser.rb +7 -5
  10. data/gemfiles/8.0.gemfile +3 -0
  11. data/lib/activerecord-import/base.rb +2 -0
  12. data/lib/activerecord-import/import.rb +4 -7
  13. data/lib/activerecord-import/version.rb +1 -1
  14. data/test/adapters/mysql2_proxy.rb +3 -0
  15. data/test/adapters/postgresql_proxy.rb +3 -0
  16. data/test/adapters/trilogy.rb +2 -0
  17. data/test/database.yml.sample +6 -0
  18. data/test/github/database.yml +8 -2
  19. data/test/import_test.rb +15 -39
  20. data/test/models/author.rb +3 -1
  21. data/test/models/book.rb +6 -2
  22. data/test/models/composite_book.rb +1 -1
  23. data/test/models/composite_chapter.rb +4 -1
  24. data/test/models/customer.rb +1 -1
  25. data/test/models/order.rb +1 -1
  26. data/test/models/tag_alias.rb +1 -1
  27. data/test/models/topic.rb +1 -0
  28. data/test/mysql2_proxy/import_test.rb +6 -0
  29. data/test/postgresql_proxy/import_test.rb +6 -0
  30. data/test/support/active_support/test_case_extensions.rb +1 -5
  31. data/test/support/mysql/import_examples.rb +6 -8
  32. data/test/support/postgresql/import_examples.rb +37 -53
  33. data/test/support/shared_examples/recursive_import.rb +39 -0
  34. data/test/test_helper.rb +9 -20
  35. metadata +15 -12
  36. data/gemfiles/4.2.gemfile +0 -4
  37. data/gemfiles/5.0.gemfile +0 -4
  38. data/gemfiles/5.1.gemfile +0 -4
  39. data/lib/activerecord-import/mysql2.rb +0 -9
  40. data/lib/activerecord-import/postgresql.rb +0 -9
  41. data/lib/activerecord-import/sqlite3.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 021d7d0d5b653ef01a5ab1aa23b72cca6f46abc65040014ad02fa790976f0189
4
- data.tar.gz: a5440146848bc1bfee194681b9bf53f928150936c3c992eaec1299fec2e7c1bb
3
+ metadata.gz: ed6151dcefbe456505980e5f6a89898da893ee6e25ae4aeddc28aa0b1efe0765
4
+ data.tar.gz: 381eb0b7b0910fc6900a73448728644e2e1d996e7744f9c8ff98d65ffefbaaf0
5
5
  SHA512:
6
- metadata.gz: 460961724684bc286a63ff0880ee8279a5a1528cd02ebd28e4694b8d7c39c22f19183f929ecd525de57a5069bf45218428aae47fd96ea5782e7b51a85aee0e1f
7
- data.tar.gz: b864f8eb6fc2a074497761813f29aca981ec23daa7ae12164f1b34a08bbad6175025e6a551575ef2f53f7521f13d15de02eccb24f36c2e18dcdb04fdf77e53a7
6
+ metadata.gz: '08492e9de01d21c6c8b5a12c8cd35c01b92040d148a7abc72a098405b10d0f1ae971ed2eb4185b8a2415a9bdb578452746f90aff5f57f50b4568082227a9dad4'
7
+ data.tar.gz: 297a437db1f4098f716bc55c47b22346634677d3abf3706634ed7c2aecd74d959d356720d353f369e588bcba4b9f0c09db5ce444908b0e75c75353ebc74fa059
@@ -21,6 +21,7 @@ jobs:
21
21
  ports:
22
22
  - 3306:3306
23
23
  env:
24
+ MYSQL_HOST: 127.0.0.1
24
25
  MYSQL_ROOT_PASSWORD: root
25
26
  MYSQL_USER: github
26
27
  MYSQL_PASSWORD: github
@@ -36,6 +37,8 @@ jobs:
36
37
  ruby:
37
38
  - 3.3
38
39
  env:
40
+ - AR_VERSION: '8.0'
41
+ RUBYOPT: --enable-frozen-string-literal
39
42
  - AR_VERSION: '7.2'
40
43
  RUBYOPT: --enable-frozen-string-literal
41
44
  - AR_VERSION: '7.1'
@@ -45,6 +48,9 @@ jobs:
45
48
  - AR_VERSION: 6.1
46
49
  RUBYOPT: --enable-frozen-string-literal
47
50
  include:
51
+ - ruby: 3.2
52
+ env:
53
+ AR_VERSION: '8.0'
48
54
  - ruby: 3.2
49
55
  env:
50
56
  AR_VERSION: '7.2'
@@ -72,7 +78,7 @@ jobs:
72
78
  - ruby: '3.0'
73
79
  env:
74
80
  AR_VERSION: 6.1
75
- - ruby: jruby-9.4.5.0
81
+ - ruby: jruby-9.4.8.0
76
82
  env:
77
83
  AR_VERSION: '7.0'
78
84
  - ruby: 2.7
@@ -84,7 +90,7 @@ jobs:
84
90
  - ruby: 2.7
85
91
  env:
86
92
  AR_VERSION: '6.0'
87
- - ruby: jruby-9.3.10.0
93
+ - ruby: jruby-9.3.15.0
88
94
  env:
89
95
  AR_VERSION: '6.1'
90
96
  - ruby: 2.6
@@ -96,6 +102,10 @@ jobs:
96
102
  DB_DATABASE: activerecord_import_test
97
103
  steps:
98
104
  - uses: actions/checkout@v4
105
+ - name: Install SQLite3 Development Library
106
+ run: |
107
+ sudo apt-get update
108
+ sudo apt-get install libsqlite3-dev
99
109
  - uses: ruby/setup-ruby@v1
100
110
  with:
101
111
  ruby-version: ${{ matrix.ruby }}
@@ -103,8 +113,6 @@ jobs:
103
113
  rubygems: latest
104
114
  - name: Set up databases
105
115
  run: |
106
- sudo /etc/init.d/mysql start
107
- mysql -e 'CREATE DATABASE ${{ env.DB_DATABASE }} CHARACTER SET utf8 COLLATE utf8_general_ci;' -u root -proot
108
116
  psql -h localhost -U postgres -c 'create database ${{ env.DB_DATABASE }};'
109
117
  psql -h localhost -U postgres -d ${{ env.DB_DATABASE }} -c 'create extension if not exists hstore;'
110
118
  psql -h localhost -U postgres -c 'create extension if not exists postgis;'
@@ -117,11 +125,13 @@ jobs:
117
125
  bundle exec rake test:mysql2
118
126
  bundle exec rake test:mysql2_makara
119
127
  bundle exec rake test:mysql2spatial
128
+ bundle exec rake test:mysql2_proxy
120
129
  - name: Run tests with postgresql
121
130
  run: |
122
131
  bundle exec rake test:postgis
123
132
  bundle exec rake test:postgresql
124
133
  bundle exec rake test:postgresql_makara
134
+ bundle exec rake test:postgresql_proxy
125
135
  - name: Run tests with seamless_database_pool
126
136
  run: |
127
137
  bundle exec rake test:seamless_database_pool
@@ -139,6 +149,10 @@ jobs:
139
149
  AR_VERSION: '7.0'
140
150
  steps:
141
151
  - uses: actions/checkout@v4
152
+ - name: Install SQLite3 Development Library
153
+ run: |
154
+ sudo apt-get update
155
+ sudo apt-get install libsqlite3-dev
142
156
  - uses: ruby/setup-ruby@v1
143
157
  with:
144
158
  ruby-version: 3.0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,26 @@
1
+ ## Changes in 2.1.0
2
+
3
+ ### New Features
4
+
5
+ * Add Support for `active_record_proxy_adapters` gem thanks to @stingrayzboy via #\867.
6
+ Since Rails 7.1 makara no longer works and it is not currently maintained. The @nasdaq team
7
+ have written a gem called [active_record_proxy_adapters](https://rubygems.org/gems/active_record_proxy_adapters)
8
+ that implements some makara functionality.
9
+
10
+ ## Changes in 2.0.0
11
+
12
+ ### Breaking Changes
13
+
14
+ * Fix `recursive_on_duplicate_key_update` doesn't work with non-standard
15
+ association name. Thanks to @jacob-carlborg-apoex via \#852. The documentation for the
16
+ `:recursive_on_duplicate_key_update` option specifies that the hash key is
17
+ the association name. But previously the name of associated table was used to
18
+ look up the options. Now the behavior matches the documentation and the name
19
+ of the association is used instead. This only affects associations that uses
20
+ a name that doesn't follow the ActiveRecord naming conventions of
21
+ associations and class names, i.e. when the `class_name:` option is used on
22
+ an association.
23
+
1
24
  ## Changes in 1.8.1
2
25
 
3
26
  ### Fixes
data/Gemfile CHANGED
@@ -6,13 +6,15 @@ gemspec
6
6
 
7
7
  version = ENV['AR_VERSION'].to_f
8
8
 
9
- mysql2_version = '0.3.0'
10
- mysql2_version = '0.4.0' if version >= 4.2
9
+ mysql2_version = '0.4.0'
11
10
  mysql2_version = '0.5.0' if version >= 6.1
11
+ mysql2_version = '0.5.6' if version >= 8.0
12
12
  sqlite3_version = '1.3.0'
13
13
  sqlite3_version = '1.4.0' if version >= 6.0
14
+ sqlite3_version = '2.2.0' if version >= 8.0
14
15
  pg_version = '0.9'
15
16
  pg_version = '1.1' if version >= 6.1
17
+ pg_version = '1.5' if version >= 8.0
16
18
 
17
19
  group :development, :test do
18
20
  gem 'rubocop'
@@ -51,19 +53,11 @@ gem "chronic"
51
53
  gem "mocha", "~> 2.1.0"
52
54
 
53
55
  # Debugging
54
- platforms :jruby do
55
- gem "ruby-debug", "= 0.10.4"
56
- end
57
-
58
56
  platforms :ruby do
59
57
  gem "pry-byebug"
60
58
  gem "pry", "~> 0.14.0"
61
59
  end
62
60
 
63
- if version >= 4.0
64
- gem "minitest"
65
- else
66
- gem "test-unit"
67
- end
61
+ gem "minitest"
68
62
 
69
63
  eval_gemfile File.expand_path("../gemfiles/#{version}.gemfile", __FILE__)
data/README.markdown CHANGED
@@ -569,11 +569,11 @@ require 'activerecord-import'
569
569
  ### Load Path Setup
570
570
  To understand how rubygems loads code you can reference the following:
571
571
 
572
- http://guides.rubygems.org/patterns/#loading-code
572
+ https://guides.rubygems.org/patterns/#loading-code
573
573
 
574
574
  And an example of how active_record dynamically load adapters:
575
575
 
576
- https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/connection_specification.rb
576
+ https://github.com/rails/rails/blob/main/activerecord/lib/active_record/connection_adapters.rb
577
577
 
578
578
  In summary, when a gem is loaded rubygems adds the `lib` folder of the gem to the global load path `$LOAD_PATH` so that all `require` lookups will not propagate through all of the folders on the load path. When a `require` is issued each folder on the `$LOAD_PATH` is checked for the file and/or folder referenced. This allows a gem (like activerecord-import) to define push the activerecord-import folder (or namespace) on the `$LOAD_PATH` and any adapters provided by activerecord-import will be found by rubygems when the require is issued.
579
579
 
data/Rakefile CHANGED
@@ -19,11 +19,13 @@ ADAPTERS = %w(
19
19
  mysql2
20
20
  mysql2_makara
21
21
  mysql2spatial
22
+ mysql2_proxy
22
23
  jdbcmysql
23
24
  jdbcsqlite3
24
25
  jdbcpostgresql
25
26
  postgresql
26
27
  postgresql_makara
28
+ postgresql_proxy
27
29
  postgis
28
30
  makara_postgis
29
31
  sqlite3
@@ -44,8 +44,6 @@ require adapter_schema if File.exist?(adapter_schema)
44
44
  Dir["#{File.dirname(__FILE__)}/models/*.rb"].sort.each { |file| require file }
45
45
 
46
46
  require File.join( benchmark_dir, 'lib', "#{options.adapter}_benchmark" )
47
-
48
- table_types = nil
49
47
  table_types = if options.benchmark_all_types
50
48
  ["all"]
51
49
  else
@@ -16,7 +16,7 @@ class BenchmarkBase
16
16
  end
17
17
  end
18
18
 
19
- # Returns an OpenStruct which contains two attritues, +description+ and +tms+ after performing an
19
+ # Returns a struct which contains two attritues, +description+ and +tms+ after performing an
20
20
  # actual benchmark.
21
21
  #
22
22
  # == PARAMETERS
@@ -24,9 +24,12 @@ class BenchmarkBase
24
24
  # * blk - the block of code to benchmark
25
25
  #
26
26
  # == RETURNS
27
- # An OpenStruct object with the following attributes:
27
+ # A struct object with the following attributes:
28
28
  # * description - the description of the benchmark ran
29
29
  # * tms - a Benchmark::Tms containing the results of the benchmark
30
+
31
+ BmStruct = Struct.new( :description, :tms, :failed, keyword_init: true )
32
+
30
33
  def bm( description, &block )
31
34
  tms = nil
32
35
  puts "Benchmarking #{description}"
@@ -35,7 +38,7 @@ class BenchmarkBase
35
38
  delete_all
36
39
  failed = false
37
40
 
38
- OpenStruct.new description: description, tms: tms, failed: failed
41
+ BmStruct.new( description: description, tms: tms, failed: failed )
39
42
  end
40
43
 
41
44
  # Given a model class (ie: Topic), and an array of columns and value sets
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'optparse'
4
- require 'ostruct'
5
4
 
6
5
  #
7
6
  # == PARAMETERS
@@ -38,8 +37,11 @@ module BenchmarkOptionParser
38
37
  end
39
38
  end
40
39
 
40
+ OptionsStruct = Struct.new( :adapter, :table_types, :delete_on_finish, :number_of_objects, :outputs,
41
+ :benchmark_all_types, keyword_init: true )
42
+ OutputStruct = Struct.new( :format, :filename, keyword_init: true )
41
43
  def self.parse( args )
42
- options = OpenStruct.new(
44
+ options = OptionsStruct.new(
43
45
  adapter: 'mysql2',
44
46
  table_types: {},
45
47
  delete_on_finish: true,
@@ -81,12 +83,12 @@ module BenchmarkOptionParser
81
83
 
82
84
  # print results in CSV format
83
85
  opts.on( "--to-csv [String]", "Print results in a CSV file format" ) do |filename|
84
- options.outputs << OpenStruct.new( format: 'csv', filename: filename)
86
+ options.outputs << OutputStruct.new( format: 'csv', filename: filename)
85
87
  end
86
88
 
87
89
  # print results in HTML format
88
90
  opts.on( "--to-html [String]", "Print results in HTML format" ) do |filename|
89
- options.outputs << OpenStruct.new( format: 'html', filename: filename )
91
+ options.outputs << OutputStruct.new( format: 'html', filename: filename )
90
92
  end
91
93
  end # end opt.parse!
92
94
 
@@ -100,7 +102,7 @@ module BenchmarkOptionParser
100
102
  end
101
103
 
102
104
  options.number_of_objects = [1000] if options.number_of_objects.empty?
103
- options.outputs = [OpenStruct.new( format: 'html', filename: 'benchmark.html')] if options.outputs.empty?
105
+ options.outputs = [OutputStruct.new( format: 'html', filename: 'benchmark.html')] if options.outputs.empty?
104
106
 
105
107
  print_options( options )
106
108
 
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem 'activerecord', '~> 8.0.0'
@@ -11,8 +11,10 @@ module ActiveRecord::Import
11
11
  case adapter
12
12
  when 'mysql2_makara' then 'mysql2'
13
13
  when 'mysql2spatial' then 'mysql2'
14
+ when 'mysql2_proxy' then 'mysql2'
14
15
  when 'spatialite' then 'sqlite3'
15
16
  when 'postgresql_makara' then 'postgresql'
17
+ when 'postgresql_proxy' then 'postgresql'
16
18
  when 'makara_postgis' then 'postgresql'
17
19
  when 'postgis' then 'postgresql'
18
20
  when 'cockroachdb' then 'postgresql'
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "ostruct"
4
-
5
3
  module ActiveRecord::Import::ConnectionAdapters; end
6
4
 
7
5
  module ActiveRecord::Import # :nodoc:
@@ -859,12 +857,11 @@ class ActiveRecord::Base
859
857
 
860
858
  private
861
859
 
862
- def associated_options(options, associated_class)
860
+ def associated_options(options, association)
863
861
  return options unless options.key?(:recursive_on_duplicate_key_update)
864
862
 
865
- table_name = associated_class.arel_table.name.to_sym
866
863
  options.merge(
867
- on_duplicate_key_update: options[:recursive_on_duplicate_key_update][table_name]
864
+ on_duplicate_key_update: options[:recursive_on_duplicate_key_update][association]
868
865
  )
869
866
  end
870
867
 
@@ -973,12 +970,12 @@ class ActiveRecord::Base
973
970
  options.delete(:returning)
974
971
 
975
972
  associated_objects_by_class.each_value do |associations|
976
- associations.each_value do |associated_records|
973
+ associations.each do |association, associated_records|
977
974
  next if associated_records.empty?
978
975
 
979
976
  associated_class = associated_records.first.class
980
977
  associated_class.bulk_import(associated_records,
981
- associated_options(options, associated_class))
978
+ associated_options(options, association))
982
979
  end
983
980
  end
984
981
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module Import
5
- VERSION = "1.8.1"
5
+ VERSION = "2.1.0"
6
6
  end
7
7
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV["ARE_DB"] = "mysql2"
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV["ARE_DB"] = "postgresql"
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'logger'
4
+
3
5
  ENV["ARE_DB"] = "trilogy"
4
6
 
5
7
  if ENV['AR_VERSION'].to_f <= 7.0
@@ -16,6 +16,9 @@ mysql2spatial:
16
16
  mysql2_makara:
17
17
  <<: *mysql2
18
18
 
19
+ mysql2_proxy:
20
+ <<: *mysql2
21
+
19
22
  postgresql: &postgresql
20
23
  <<: *common
21
24
  username: postgres
@@ -26,6 +29,9 @@ postgresql: &postgresql
26
29
  postresql_makara:
27
30
  <<: *postgresql
28
31
 
32
+ postresql_proxy:
33
+ <<: *postgresql
34
+
29
35
  postgis:
30
36
  <<: *postgresql
31
37
 
@@ -3,7 +3,7 @@ common: &common
3
3
  password: root
4
4
  encoding: utf8
5
5
  collation: utf8_general_ci
6
- host: localhost
6
+ host: 127.0.0.1
7
7
  database: activerecord_import_test
8
8
 
9
9
  jdbcpostgresql: &postgresql
@@ -30,6 +30,9 @@ mysql2spatial:
30
30
  mysql2_makara:
31
31
  <<: *mysql2
32
32
 
33
+ mysql2_proxy:
34
+ <<: *mysql2
35
+
33
36
  oracle:
34
37
  <<: *common
35
38
  adapter: oracle
@@ -45,6 +48,9 @@ postgresql: &postgresql
45
48
  postresql_makara:
46
49
  <<: *postgresql
47
50
 
51
+ postresql_proxy:
52
+ <<: *postgresql
53
+
48
54
  postgis:
49
55
  <<: *postgresql
50
56
 
@@ -54,7 +60,7 @@ seamless_database_pool:
54
60
  pool_adapter: mysql2
55
61
  prepared_statements: false
56
62
  master:
57
- host: localhost
63
+ host: 127.0.0.1
58
64
 
59
65
  sqlite:
60
66
  adapter: sqlite
data/test/import_test.rb CHANGED
@@ -741,14 +741,8 @@ describe "#import" do
741
741
  ]
742
742
  Book.import books
743
743
  assert_equal 2, Book.count
744
-
745
- if ENV['AR_VERSION'].to_i >= 5.0
746
- assert_equal 'draft', Book.first.read_attribute('status')
747
- assert_equal 'published', Book.last.read_attribute('status')
748
- else
749
- assert_equal 0, Book.first.read_attribute('status')
750
- assert_equal 1, Book.last.read_attribute('status')
751
- end
744
+ assert_equal 'draft', Book.first.read_attribute('status')
745
+ assert_equal 'published', Book.last.read_attribute('status')
752
746
  end
753
747
 
754
748
  it 'should be able to import enum fields with default value' do
@@ -758,32 +752,19 @@ describe "#import" do
758
752
  ]
759
753
  Book.import books
760
754
  assert_equal 1, Book.count
761
-
762
- if ENV['AR_VERSION'].to_i >= 5.0
763
- assert_equal 'draft', Book.first.read_attribute('status')
764
- else
765
- assert_equal 0, Book.first.read_attribute('status')
766
- end
755
+ assert_equal 'draft', Book.first.read_attribute('status')
767
756
  end
768
757
 
769
- if ENV['AR_VERSION'].to_f > 4.1
770
- it 'should be able to import enum fields by name' do
771
- Book.delete_all if Book.count > 0
772
- books = [
773
- Book.new(author_name: "Foo", title: "Baz", status: :draft),
774
- Book.new(author_name: "Foo2", title: "Baz2", status: :published),
775
- ]
776
- Book.import books
777
- assert_equal 2, Book.count
778
-
779
- if ENV['AR_VERSION'].to_i >= 5.0
780
- assert_equal 'draft', Book.first.read_attribute('status')
781
- assert_equal 'published', Book.last.read_attribute('status')
782
- else
783
- assert_equal 0, Book.first.read_attribute('status')
784
- assert_equal 1, Book.last.read_attribute('status')
785
- end
786
- end
758
+ it 'should be able to import enum fields by name' do
759
+ Book.delete_all if Book.count > 0
760
+ books = [
761
+ Book.new(author_name: "Foo", title: "Baz", status: :draft),
762
+ Book.new(author_name: "Foo2", title: "Baz2", status: :published),
763
+ ]
764
+ Book.import books
765
+ assert_equal 2, Book.count
766
+ assert_equal 'draft', Book.first.read_attribute('status')
767
+ assert_equal 'published', Book.last.read_attribute('status')
787
768
  end
788
769
  end
789
770
 
@@ -796,13 +777,8 @@ describe "#import" do
796
777
  Book.import columns, values
797
778
  assert_equal 2, Book.count
798
779
 
799
- if ENV['AR_VERSION'].to_i >= 5.0
800
- assert_equal 'draft', Book.first.read_attribute('status')
801
- assert_equal 'published', Book.last.read_attribute('status')
802
- else
803
- assert_equal 0, Book.first.read_attribute('status')
804
- assert_equal 1, Book.last.read_attribute('status')
805
- end
780
+ assert_equal 'draft', Book.first.read_attribute('status')
781
+ assert_equal 'published', Book.last.read_attribute('status')
806
782
  end
807
783
  end
808
784
 
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Author < ActiveRecord::Base
4
- if ENV['AR_VERSION'].to_f >= 7.1
4
+ if ENV['AR_VERSION'].to_f >= 8.0
5
+ has_many :composite_books, foreign_key: [:id, :author_id], inverse_of: :author
6
+ elsif ENV['AR_VERSION'].to_f >= 7.1
5
7
  has_many :composite_books, query_constraints: [:id, :author_id], inverse_of: :author
6
8
  end
7
9
  end
data/test/models/book.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  class Book < ActiveRecord::Base
4
4
  belongs_to :topic, inverse_of: :books
5
- if ENV['AR_VERSION'].to_f <= 7.0
5
+ if ENV['AR_VERSION'].to_f <= 7.0 || ENV['AR_VERSION'].to_f >= 8.0
6
6
  belongs_to :tag, foreign_key: [:tag_id, :parent_id] unless ENV["SKIP_COMPOSITE_PK"]
7
7
  else
8
8
  belongs_to :tag, query_constraints: [:tag_id, :parent_id] unless ENV["SKIP_COMPOSITE_PK"]
@@ -10,5 +10,9 @@ class Book < ActiveRecord::Base
10
10
  has_many :chapters, inverse_of: :book
11
11
  has_many :discounts, as: :discountable
12
12
  has_many :end_notes, inverse_of: :book
13
- enum status: [:draft, :published] if ENV['AR_VERSION'].to_f >= 4.1
13
+ if ENV['AR_VERSION'].to_f >= 8.0
14
+ enum :status, [:draft, :published]
15
+ else
16
+ enum status: [:draft, :published]
17
+ end
14
18
  end
@@ -3,7 +3,7 @@
3
3
  class CompositeBook < ActiveRecord::Base
4
4
  self.primary_key = %i[id author_id]
5
5
  belongs_to :author
6
- if ENV['AR_VERSION'].to_f <= 7.0
6
+ if ENV['AR_VERSION'].to_f <= 7.0 || ENV['AR_VERSION'].to_f >= 8.0
7
7
  unless ENV["SKIP_COMPOSITE_PK"]
8
8
  has_many :composite_chapters, inverse_of: :composite_book,
9
9
  foreign_key: [:id, :author_id]
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class CompositeChapter < ActiveRecord::Base
4
- if ENV['AR_VERSION'].to_f >= 7.1
4
+ if ENV['AR_VERSION'].to_f >= 8.0
5
+ belongs_to :composite_book, inverse_of: :composite_chapters,
6
+ foreign_key: [:composite_book_id, :author_id]
7
+ elsif ENV['AR_VERSION'].to_f >= 7.1
5
8
  belongs_to :composite_book, inverse_of: :composite_chapters,
6
9
  query_constraints: [:composite_book_id, :author_id]
7
10
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  class Customer < ActiveRecord::Base
4
4
  unless ENV["SKIP_COMPOSITE_PK"]
5
- if ENV['AR_VERSION'].to_f <= 7.0
5
+ if ENV['AR_VERSION'].to_f <= 7.0 || ENV['AR_VERSION'].to_f >= 8.0
6
6
  has_many :orders,
7
7
  inverse_of: :customer,
8
8
  primary_key: %i(account_id id),
data/test/models/order.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  class Order < ActiveRecord::Base
4
4
  unless ENV["SKIP_COMPOSITE_PK"]
5
- if ENV['AR_VERSION'].to_f <= 7.0
5
+ if ENV['AR_VERSION'].to_f <= 7.0 || ENV['AR_VERSION'].to_f >= 8.0
6
6
  belongs_to :customer,
7
7
  inverse_of: :orders,
8
8
  primary_key: %i(account_id id),
@@ -2,7 +2,7 @@
2
2
 
3
3
  class TagAlias < ActiveRecord::Base
4
4
  unless ENV["SKIP_COMPOSITE_PK"]
5
- if ENV['AR_VERSION'].to_f <= 7.0
5
+ if ENV['AR_VERSION'].to_f <= 7.0 || ENV['AR_VERSION'].to_f >= 8.0
6
6
  belongs_to :tag, foreign_key: [:tag_id, :parent_id], required: true
7
7
  else
8
8
  belongs_to :tag, query_constraints: [:tag_id, :parent_id], required: true
data/test/models/topic.rb CHANGED
@@ -16,6 +16,7 @@ class Topic < ActiveRecord::Base
16
16
  before_validation -> { errors.add(:title, :invalid) if title == 'invalid' }
17
17
 
18
18
  has_many :books, inverse_of: :topic
19
+ has_many :novels, inverse_of: :topic, class_name: "Book"
19
20
  belongs_to :parent, class_name: "Topic"
20
21
 
21
22
  composed_of :description, mapping: [%w(title title), %w(author_name author_name)], allow_nil: true, class_name: "TopicDescription"
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
4
+ require File.expand_path("#{File.dirname(__FILE__)}/../support/mysql/import_examples")
5
+
6
+ should_support_mysql_import_functionality
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
4
+ require File.expand_path("#{File.dirname(__FILE__)}/../support/postgresql/import_examples")
5
+
6
+ should_support_postgresql_import_functionality
@@ -3,11 +3,7 @@
3
3
  class ActiveSupport::TestCase
4
4
  include ActiveRecord::TestFixtures
5
5
 
6
- if ENV['AR_VERSION'].to_f >= 5.0
7
- self.use_transactional_tests = true
8
- else
9
- self.use_transactional_fixtures = true
10
- end
6
+ self.use_transactional_tests = true
11
7
 
12
8
  class << self
13
9
  def requires_active_record_version(version_string, &blk)
@@ -84,14 +84,12 @@ def should_support_mysql_import_functionality
84
84
  end
85
85
  end
86
86
 
87
- if ENV['AR_VERSION'].to_f >= 5.1
88
- context "with virtual columns" do
89
- let(:books) { [Book.new(author_name: "foo", title: "bar")] }
90
-
91
- it "ignores virtual columns and creates record" do
92
- assert_difference "Book.count", +1 do
93
- Book.import books
94
- end
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
95
93
  end
96
94
  end
97
95
  end
@@ -38,10 +38,8 @@ def should_support_postgresql_import_functionality
38
38
  assert !topic.changed?
39
39
  end
40
40
 
41
- if ENV['AR_VERSION'].to_f > 4.1
42
- it "moves the dirty changes to previous_changes" do
43
- assert topic.previous_changes.present?
44
- end
41
+ it "moves the dirty changes to previous_changes" do
42
+ assert topic.previous_changes.present?
45
43
  end
46
44
 
47
45
  it "marks models as persisted" do
@@ -96,15 +94,9 @@ def should_support_postgresql_import_functionality
96
94
  describe "returning" do
97
95
  let(:books) { [Book.new(author_name: "King", title: "It")] }
98
96
  let(:result) { Book.import(books, returning: %w(author_name title)) }
99
- let(:book_id) do
100
- if RUBY_PLATFORM == 'java' || ENV['AR_VERSION'].to_i >= 5.0
101
- books.first.id
102
- else
103
- books.first.id.to_s
104
- end
105
- end
106
- let(:true_returning_value) { ENV['AR_VERSION'].to_f >= 5.0 ? true : 't' }
107
- let(:false_returning_value) { ENV['AR_VERSION'].to_f >= 5.0 ? false : 'f' }
97
+ let(:book_id) { books.first.id }
98
+ let(:true_returning_value) { true }
99
+ let(:false_returning_value) { false }
108
100
 
109
101
  it "creates records" do
110
102
  assert_difference("Book.count", +1) { result }
@@ -222,23 +214,21 @@ def should_support_postgresql_import_functionality
222
214
  end
223
215
  end
224
216
 
225
- if ENV['AR_VERSION'].to_f >= 4.0
226
- describe "with a uuid primary key" do
227
- let(:vendor) { Vendor.new(name: "foo") }
228
- let(:vendors) { [vendor] }
217
+ describe "with a uuid primary key" do
218
+ let(:vendor) { Vendor.new(name: "foo") }
219
+ let(:vendors) { [vendor] }
229
220
 
230
- it "creates records" do
231
- assert_difference "Vendor.count", +1 do
232
- Vendor.import vendors
233
- end
234
- end
235
-
236
- it "assigns an id to the model objects" do
221
+ it "creates records" do
222
+ assert_difference "Vendor.count", +1 do
237
223
  Vendor.import vendors
238
- assert_not_nil vendor.id
239
224
  end
240
225
  end
241
226
 
227
+ it "assigns an id to the model objects" do
228
+ Vendor.import vendors
229
+ assert_not_nil vendor.id
230
+ end
231
+
242
232
  describe "with an assigned uuid primary key" do
243
233
  let(:id) { SecureRandom.uuid }
244
234
  let(:vendor) { Vendor.new(id: id, name: "foo") }
@@ -254,44 +244,38 @@ def should_support_postgresql_import_functionality
254
244
  end
255
245
 
256
246
  describe "with store accessor fields" do
257
- if ENV['AR_VERSION'].to_f >= 4.0
258
- it "imports values for json fields" do
259
- vendors = [Vendor.new(name: 'Vendor 1', size: 100)]
260
- assert_difference "Vendor.count", +1 do
261
- Vendor.import vendors
262
- end
263
- assert_equal(100, Vendor.first.size)
247
+ it "imports values for json fields" do
248
+ vendors = [Vendor.new(name: 'Vendor 1', size: 100)]
249
+ assert_difference "Vendor.count", +1 do
250
+ Vendor.import vendors
264
251
  end
252
+ assert_equal(100, Vendor.first.size)
253
+ end
265
254
 
266
- it "imports values for hstore fields" do
267
- vendors = [Vendor.new(name: 'Vendor 1', contact: 'John Smith')]
268
- assert_difference "Vendor.count", +1 do
269
- Vendor.import vendors
270
- end
271
- assert_equal('John Smith', Vendor.first.contact)
255
+ it "imports values for hstore fields" do
256
+ vendors = [Vendor.new(name: 'Vendor 1', contact: 'John Smith')]
257
+ assert_difference "Vendor.count", +1 do
258
+ Vendor.import vendors
272
259
  end
260
+ assert_equal('John Smith', Vendor.first.contact)
273
261
  end
274
262
 
275
- if ENV['AR_VERSION'].to_f >= 4.2
276
- it "imports values for jsonb fields" do
277
- vendors = [Vendor.new(name: 'Vendor 1', charge_code: '12345')]
278
- assert_difference "Vendor.count", +1 do
279
- Vendor.import vendors
280
- end
281
- assert_equal('12345', Vendor.first.charge_code)
263
+ it "imports values for jsonb fields" do
264
+ vendors = [Vendor.new(name: 'Vendor 1', charge_code: '12345')]
265
+ assert_difference "Vendor.count", +1 do
266
+ Vendor.import vendors
282
267
  end
268
+ assert_equal('12345', Vendor.first.charge_code)
283
269
  end
284
270
  end
285
271
 
286
- if ENV['AR_VERSION'].to_f >= 4.2
287
- describe "with serializable fields" do
288
- it "imports default values as correct data type" do
289
- vendors = [Vendor.new(name: 'Vendor 1')]
290
- assert_difference "Vendor.count", +1 do
291
- Vendor.import vendors
292
- end
293
- assert_equal({}, Vendor.first.json_data)
272
+ describe "with serializable fields" do
273
+ it "imports default values as correct data type" do
274
+ vendors = [Vendor.new(name: 'Vendor 1')]
275
+ assert_difference "Vendor.count", +1 do
276
+ Vendor.import vendors
294
277
  end
278
+ assert_equal({}, Vendor.first.json_data)
295
279
  end
296
280
 
297
281
  %w(json jsonb).each do |json_type|
@@ -278,6 +278,45 @@ def should_support_recursive_import
278
278
  end
279
279
  assert_equal new_chapter_title, Chapter.find(example_chapter.id).title
280
280
  end
281
+
282
+ context "when a non-standard association name is used" do
283
+ let(:new_topics) do
284
+ topic = Build(:topic)
285
+
286
+ 2.times do
287
+ novel = topic.novels.build(title: FactoryBot.generate(:book_title), author_name: 'Stephen King')
288
+ 3.times do
289
+ novel.chapters.build(title: FactoryBot.generate(:chapter_title))
290
+ end
291
+
292
+ 4.times do
293
+ novel.end_notes.build(note: FactoryBot.generate(:end_note))
294
+ end
295
+ end
296
+
297
+ [topic]
298
+ end
299
+
300
+ it "updates nested associated objects" do
301
+ new_chapter_title = 'The Final Chapter'
302
+ novel = new_topics.first.novels.first
303
+ novel.author_name = 'Richard Bachman'
304
+
305
+ example_chapter = novel.chapters.first
306
+ example_chapter.title = new_chapter_title
307
+
308
+ assert_nothing_raised do
309
+ Topic.import new_topics,
310
+ recursive: true,
311
+ on_duplicate_key_update: [:id],
312
+ recursive_on_duplicate_key_update: {
313
+ novels: { conflict_target: [:id], columns: [:author_name] },
314
+ chapters: { conflict_target: [:id], columns: [:title] }
315
+ }
316
+ end
317
+ assert_equal new_chapter_title, Chapter.find(example_chapter.id).title
318
+ end
319
+ end
281
320
  end
282
321
  end
283
322
 
data/test/test_helper.rb CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'pathname'
4
4
  require 'rake'
5
+ require 'logger'
6
+
5
7
  test_dir = Pathname.new File.dirname(__FILE__)
6
8
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
9
  $LOAD_PATH.unshift(File.dirname(__FILE__))
@@ -13,19 +15,16 @@ ENV["RAILS_ENV"] = "test"
13
15
  require "bundler"
14
16
  Bundler.setup
15
17
 
16
- require 'pry' unless RbConfig::CONFIG["RUBY_INSTALL_NAME"] =~ /jruby/
18
+ unless RbConfig::CONFIG["RUBY_INSTALL_NAME"] =~ /jruby/
19
+ require 'pry'
20
+ require 'pry-byebug'
21
+ end
17
22
 
18
23
  require "active_record"
19
24
  require "active_record/fixtures"
20
25
  require "active_support/test_case"
21
-
22
- if ActiveSupport::VERSION::STRING < "4.0"
23
- require 'test/unit'
24
- require 'mocha/test_unit'
25
- else
26
- require 'active_support/testing/autorun'
27
- require "mocha/minitest"
28
- end
26
+ require 'active_support/testing/autorun'
27
+ require "mocha/minitest"
29
28
 
30
29
  require 'timecop'
31
30
  require 'chronic'
@@ -38,16 +37,6 @@ rescue LoadError
38
37
  end
39
38
  end
40
39
 
41
- # Support MySQL 5.7
42
- if ActiveSupport::VERSION::STRING < "4.1"
43
- require "active_record/connection_adapters/mysql2_adapter"
44
- class ActiveRecord::ConnectionAdapters::Mysql2Adapter
45
- NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
46
- end
47
- end
48
-
49
- require "ruby-debug" if RUBY_VERSION.to_f < 1.9
50
-
51
40
  adapter = ENV["ARE_DB"] || "sqlite3"
52
41
 
53
42
  FileUtils.mkdir_p 'log'
@@ -99,4 +88,4 @@ Dir["#{File.dirname(__FILE__)}/models/*.rb"].sort.each { |file| require file }
99
88
  # Prevent this deprecation warning from breaking the tests.
100
89
  Rake::FileList.send(:remove_method, :import)
101
90
 
102
- ActiveSupport::TestCase.test_order = :random if ENV['AR_VERSION'].to_f >= 4.2
91
+ ActiveSupport::TestCase.test_order = :random
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-import
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zach Dennis
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-06 00:00:00.000000000 Z
11
+ date: 2025-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -70,15 +70,13 @@ files:
70
70
  - benchmarks/models/test_myisam.rb
71
71
  - benchmarks/schema/mysql2_schema.rb
72
72
  - docker-compose.yml
73
- - gemfiles/4.2.gemfile
74
- - gemfiles/5.0.gemfile
75
- - gemfiles/5.1.gemfile
76
73
  - gemfiles/5.2.gemfile
77
74
  - gemfiles/6.0.gemfile
78
75
  - gemfiles/6.1.gemfile
79
76
  - gemfiles/7.0.gemfile
80
77
  - gemfiles/7.1.gemfile
81
78
  - gemfiles/7.2.gemfile
79
+ - gemfiles/8.0.gemfile
82
80
  - lib/activerecord-import.rb
83
81
  - lib/activerecord-import/active_record/adapters/abstract_adapter.rb
84
82
  - lib/activerecord-import/active_record/adapters/jdbcmysql_adapter.rb
@@ -98,9 +96,6 @@ files:
98
96
  - lib/activerecord-import/adapters/trilogy_adapter.rb
99
97
  - lib/activerecord-import/base.rb
100
98
  - lib/activerecord-import/import.rb
101
- - lib/activerecord-import/mysql2.rb
102
- - lib/activerecord-import/postgresql.rb
103
- - lib/activerecord-import/sqlite3.rb
104
99
  - lib/activerecord-import/synchronize.rb
105
100
  - lib/activerecord-import/value_sets_parser.rb
106
101
  - lib/activerecord-import/version.rb
@@ -110,10 +105,12 @@ files:
110
105
  - test/adapters/makara_postgis.rb
111
106
  - test/adapters/mysql2.rb
112
107
  - test/adapters/mysql2_makara.rb
108
+ - test/adapters/mysql2_proxy.rb
113
109
  - test/adapters/mysql2spatial.rb
114
110
  - test/adapters/postgis.rb
115
111
  - test/adapters/postgresql.rb
116
112
  - test/adapters/postgresql_makara.rb
113
+ - test/adapters/postgresql_proxy.rb
117
114
  - test/adapters/seamless_database_pool.rb
118
115
  - test/adapters/spatialite.rb
119
116
  - test/adapters/sqlite3.rb
@@ -156,9 +153,11 @@ files:
156
153
  - test/models/widget.rb
157
154
  - test/mysql2/import_test.rb
158
155
  - test/mysql2_makara/import_test.rb
156
+ - test/mysql2_proxy/import_test.rb
159
157
  - test/mysqlspatial2/import_test.rb
160
158
  - test/postgis/import_test.rb
161
159
  - test/postgresql/import_test.rb
160
+ - test/postgresql_proxy/import_test.rb
162
161
  - test/schema/generic_schema.rb
163
162
  - test/schema/jdbcpostgresql_schema.rb
164
163
  - test/schema/mysql2_schema.rb
@@ -187,7 +186,7 @@ licenses:
187
186
  - MIT
188
187
  metadata:
189
188
  changelog_uri: https://github.com/zdennis/activerecord-import/blob/master/CHANGELOG.md
190
- post_install_message:
189
+ post_install_message:
191
190
  rdoc_options: []
192
191
  require_paths:
193
192
  - lib
@@ -202,8 +201,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
202
201
  - !ruby/object:Gem::Version
203
202
  version: '0'
204
203
  requirements: []
205
- rubygems_version: 3.3.9
206
- signing_key:
204
+ rubygems_version: 3.0.3.1
205
+ signing_key:
207
206
  specification_version: 4
208
207
  summary: Bulk insert extension for ActiveRecord
209
208
  test_files:
@@ -213,10 +212,12 @@ test_files:
213
212
  - test/adapters/makara_postgis.rb
214
213
  - test/adapters/mysql2.rb
215
214
  - test/adapters/mysql2_makara.rb
215
+ - test/adapters/mysql2_proxy.rb
216
216
  - test/adapters/mysql2spatial.rb
217
217
  - test/adapters/postgis.rb
218
218
  - test/adapters/postgresql.rb
219
219
  - test/adapters/postgresql_makara.rb
220
+ - test/adapters/postgresql_proxy.rb
220
221
  - test/adapters/seamless_database_pool.rb
221
222
  - test/adapters/spatialite.rb
222
223
  - test/adapters/sqlite3.rb
@@ -259,9 +260,11 @@ test_files:
259
260
  - test/models/widget.rb
260
261
  - test/mysql2/import_test.rb
261
262
  - test/mysql2_makara/import_test.rb
263
+ - test/mysql2_proxy/import_test.rb
262
264
  - test/mysqlspatial2/import_test.rb
263
265
  - test/postgis/import_test.rb
264
266
  - test/postgresql/import_test.rb
267
+ - test/postgresql_proxy/import_test.rb
265
268
  - test/schema/generic_schema.rb
266
269
  - test/schema/jdbcpostgresql_schema.rb
267
270
  - test/schema/mysql2_schema.rb
data/gemfiles/4.2.gemfile DELETED
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- gem 'activerecord', '~> 4.2.0'
4
- gem 'composite_primary_keys', '~> 8.0'
data/gemfiles/5.0.gemfile DELETED
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- gem 'activerecord', '~> 5.0.0'
4
- gem 'composite_primary_keys', '~> 9.0'
data/gemfiles/5.1.gemfile DELETED
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- gem 'activerecord', '~> 5.1.0'
4
- gem 'composite_primary_keys', '~> 10.0'
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- warn <<-MSG
4
- [DEPRECATION] loading activerecord-import via 'require "activerecord-import/<adapter-name>"'
5
- is deprecated. Update to autorequire using 'require "activerecord-import"'. See
6
- http://github.com/zdennis/activerecord-import/wiki/Requiring for more information
7
- MSG
8
-
9
- require "activerecord-import"
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- warn <<-MSG
4
- [DEPRECATION] loading activerecord-import via 'require "activerecord-import/<adapter-name>"'
5
- is deprecated. Update to autorequire using 'require "activerecord-import"'. See
6
- http://github.com/zdennis/activerecord-import/wiki/Requiring for more information
7
- MSG
8
-
9
- require "activerecord-import"
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- warn <<-MSG
4
- [DEPRECATION] loading activerecord-import via 'require "activerecord-import/<adapter-name>"'
5
- is deprecated. Update to autorequire using 'require "activerecord-import"'. See
6
- http://github.com/zdennis/activerecord-import/wiki/Requiring for more information
7
- MSG
8
-
9
- require "activerecord-import"