activerecord-import 0.10.0 → 1.0.8

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 (118) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +49 -0
  4. data/.rubocop_todo.yml +36 -0
  5. data/.travis.yml +64 -8
  6. data/CHANGELOG.md +475 -0
  7. data/Gemfile +32 -15
  8. data/LICENSE +21 -56
  9. data/README.markdown +564 -35
  10. data/Rakefile +20 -3
  11. data/activerecord-import.gemspec +7 -7
  12. data/benchmarks/README +2 -2
  13. data/benchmarks/benchmark.rb +68 -64
  14. data/benchmarks/lib/base.rb +138 -137
  15. data/benchmarks/lib/cli_parser.rb +107 -103
  16. data/benchmarks/lib/{mysql_benchmark.rb → mysql2_benchmark.rb} +19 -22
  17. data/benchmarks/lib/output_to_csv.rb +5 -4
  18. data/benchmarks/lib/output_to_html.rb +8 -13
  19. data/benchmarks/models/test_innodb.rb +1 -1
  20. data/benchmarks/models/test_memory.rb +1 -1
  21. data/benchmarks/models/test_myisam.rb +1 -1
  22. data/benchmarks/schema/mysql2_schema.rb +16 -0
  23. data/gemfiles/3.2.gemfile +2 -4
  24. data/gemfiles/4.0.gemfile +2 -4
  25. data/gemfiles/4.1.gemfile +2 -4
  26. data/gemfiles/4.2.gemfile +2 -4
  27. data/gemfiles/5.0.gemfile +2 -0
  28. data/gemfiles/5.1.gemfile +2 -0
  29. data/gemfiles/5.2.gemfile +2 -0
  30. data/gemfiles/6.0.gemfile +2 -0
  31. data/gemfiles/6.1.gemfile +1 -0
  32. data/lib/activerecord-import/active_record/adapters/jdbcsqlite3_adapter.rb +6 -0
  33. data/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb +0 -1
  34. data/lib/activerecord-import/adapters/abstract_adapter.rb +23 -17
  35. data/lib/activerecord-import/adapters/mysql_adapter.rb +52 -25
  36. data/lib/activerecord-import/adapters/postgresql_adapter.rb +187 -10
  37. data/lib/activerecord-import/adapters/sqlite3_adapter.rb +148 -17
  38. data/lib/activerecord-import/base.rb +15 -9
  39. data/lib/activerecord-import/import.rb +740 -191
  40. data/lib/activerecord-import/synchronize.rb +21 -21
  41. data/lib/activerecord-import/value_sets_parser.rb +33 -8
  42. data/lib/activerecord-import/version.rb +1 -1
  43. data/lib/activerecord-import.rb +4 -15
  44. data/test/adapters/jdbcsqlite3.rb +1 -0
  45. data/test/adapters/makara_postgis.rb +1 -0
  46. data/test/adapters/mysql2_makara.rb +1 -0
  47. data/test/adapters/mysql2spatial.rb +1 -1
  48. data/test/adapters/postgis.rb +1 -1
  49. data/test/adapters/postgresql.rb +1 -1
  50. data/test/adapters/postgresql_makara.rb +1 -0
  51. data/test/adapters/spatialite.rb +1 -1
  52. data/test/adapters/sqlite3.rb +1 -1
  53. data/test/database.yml.sample +13 -18
  54. data/test/import_test.rb +608 -89
  55. data/test/jdbcmysql/import_test.rb +2 -3
  56. data/test/jdbcpostgresql/import_test.rb +0 -2
  57. data/test/jdbcsqlite3/import_test.rb +4 -0
  58. data/test/makara_postgis/import_test.rb +8 -0
  59. data/test/models/account.rb +3 -0
  60. data/test/models/alarm.rb +2 -0
  61. data/test/models/animal.rb +6 -0
  62. data/test/models/bike_maker.rb +7 -0
  63. data/test/models/book.rb +7 -6
  64. data/test/models/car.rb +3 -0
  65. data/test/models/chapter.rb +2 -2
  66. data/test/models/dictionary.rb +4 -0
  67. data/test/models/discount.rb +3 -0
  68. data/test/models/end_note.rb +2 -2
  69. data/test/models/promotion.rb +3 -0
  70. data/test/models/question.rb +3 -0
  71. data/test/models/rule.rb +3 -0
  72. data/test/models/tag.rb +4 -0
  73. data/test/models/topic.rb +17 -3
  74. data/test/models/user.rb +3 -0
  75. data/test/models/user_token.rb +4 -0
  76. data/test/models/vendor.rb +7 -0
  77. data/test/models/widget.rb +19 -2
  78. data/test/mysql2/import_test.rb +2 -3
  79. data/test/{em_mysql2 → mysql2_makara}/import_test.rb +1 -1
  80. data/test/mysqlspatial2/import_test.rb +2 -2
  81. data/test/postgis/import_test.rb +5 -1
  82. data/test/schema/generic_schema.rb +159 -85
  83. data/test/schema/jdbcpostgresql_schema.rb +1 -0
  84. data/test/schema/mysql2_schema.rb +19 -0
  85. data/test/schema/postgis_schema.rb +1 -0
  86. data/test/schema/postgresql_schema.rb +61 -0
  87. data/test/schema/sqlite3_schema.rb +13 -0
  88. data/test/sqlite3/import_test.rb +2 -50
  89. data/test/support/active_support/test_case_extensions.rb +21 -13
  90. data/test/support/{mysql/assertions.rb → assertions.rb} +20 -2
  91. data/test/support/factories.rb +39 -14
  92. data/test/support/generate.rb +10 -10
  93. data/test/support/mysql/import_examples.rb +49 -98
  94. data/test/support/postgresql/import_examples.rb +535 -57
  95. data/test/support/shared_examples/on_duplicate_key_ignore.rb +43 -0
  96. data/test/support/shared_examples/on_duplicate_key_update.rb +378 -0
  97. data/test/support/shared_examples/recursive_import.rb +225 -0
  98. data/test/support/sqlite3/import_examples.rb +231 -0
  99. data/test/synchronize_test.rb +10 -2
  100. data/test/test_helper.rb +36 -8
  101. data/test/travis/database.yml +26 -17
  102. data/test/value_sets_bytes_parser_test.rb +25 -17
  103. data/test/value_sets_records_parser_test.rb +6 -6
  104. metadata +86 -42
  105. data/benchmarks/boot.rb +0 -18
  106. data/benchmarks/schema/mysql_schema.rb +0 -16
  107. data/gemfiles/3.1.gemfile +0 -4
  108. data/lib/activerecord-import/active_record/adapters/em_mysql2_adapter.rb +0 -8
  109. data/lib/activerecord-import/active_record/adapters/mysql_adapter.rb +0 -6
  110. data/lib/activerecord-import/em_mysql2.rb +0 -7
  111. data/lib/activerecord-import/mysql.rb +0 -7
  112. data/test/adapters/em_mysql2.rb +0 -1
  113. data/test/adapters/mysql.rb +0 -1
  114. data/test/adapters/mysqlspatial.rb +0 -1
  115. data/test/mysql/import_test.rb +0 -6
  116. data/test/mysqlspatial/import_test.rb +0 -6
  117. data/test/schema/mysql_schema.rb +0 -18
  118. data/test/travis/build.sh +0 -30
data/Rakefile CHANGED
@@ -11,14 +11,28 @@ namespace :display do
11
11
  puts
12
12
  end
13
13
  end
14
- task :default => ["display:notice"]
14
+ task default: ["display:notice"]
15
15
 
16
- ADAPTERS = %w(mysql mysql2 em_mysql2 jdbcmysql jdbcpostgresql postgresql sqlite3 seamless_database_pool mysqlspatial mysql2spatial spatialite postgis)
16
+ ADAPTERS = %w(
17
+ mysql2
18
+ mysql2_makara
19
+ mysql2spatial
20
+ jdbcmysql
21
+ jdbcsqlite3
22
+ jdbcpostgresql
23
+ postgresql
24
+ postgresql_makara
25
+ postgis
26
+ makara_postgis
27
+ sqlite3
28
+ spatialite
29
+ seamless_database_pool
30
+ ).freeze
17
31
  ADAPTERS.each do |adapter|
18
32
  namespace :test do
19
33
  desc "Runs #{adapter} database tests."
20
34
  Rake::TestTask.new(adapter) do |t|
21
- # FactoryGirl has an issue with warnings, so turn off, so noisy
35
+ # FactoryBot has an issue with warnings, so turn off, so noisy
22
36
  # t.warning = true
23
37
  t.test_files = FileList["test/adapters/#{adapter}.rb", "test/*_test.rb", "test/active_record/*_test.rb", "test/#{adapter}/**/*_test.rb"]
24
38
  end
@@ -49,3 +63,6 @@ Rake::RDocTask.new do |rdoc|
49
63
  rdoc.rdoc_files.include('README*')
50
64
  rdoc.rdoc_files.include('lib/**/*.rb')
51
65
  end
66
+
67
+ require 'rubocop/rake_task'
68
+ RuboCop::RakeTask.new
@@ -4,20 +4,20 @@ require File.expand_path('../lib/activerecord-import/version', __FILE__)
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Zach Dennis"]
6
6
  gem.email = ["zach.dennis@gmail.com"]
7
- gem.summary = "Bulk-loading extension for ActiveRecord"
8
- gem.description = "Extraction of the ActiveRecord::Base#import functionality from ar-extensions for Rails 3 and beyond"
9
- gem.homepage = "http://github.com/zdennis/activerecord-import"
10
- gem.license = "Ruby"
7
+ gem.summary = "Bulk insert extension for ActiveRecord"
8
+ gem.description = "A library for bulk inserting data using ActiveRecord."
9
+ gem.homepage = "https://github.com/zdennis/activerecord-import"
10
+ gem.license = "MIT"
11
11
 
12
12
  gem.files = `git ls-files`.split($\)
13
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
14
14
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
15
  gem.name = "activerecord-import"
16
16
  gem.require_paths = ["lib"]
17
17
  gem.version = ActiveRecord::Import::VERSION
18
18
 
19
- gem.required_ruby_version = ">= 1.9.2"
19
+ gem.required_ruby_version = ">= 2.0.0"
20
20
 
21
- gem.add_runtime_dependency "activerecord", ">= 3.0"
21
+ gem.add_runtime_dependency "activerecord", ">= 3.2"
22
22
  gem.add_development_dependency "rake"
23
23
  end
data/benchmarks/README CHANGED
@@ -15,10 +15,10 @@ See "ruby benchmark.rb -h" for the complete listing of options.
15
15
  EXAMPLES
16
16
  --------
17
17
  To output to html format:
18
- ruby benchmark.rb --adapter=mysql --to-html=results.html
18
+ ruby benchmark.rb --adapter=mysql2 --to-html=results.html
19
19
 
20
20
  To output to csv format:
21
- ruby benchmark.rb --adapter=mysql --to-csv=results.csv
21
+ ruby benchmark.rb --adapter=mysql2 --to-csv=results.csv
22
22
 
23
23
  LIMITATIONS
24
24
  -----------
@@ -1,64 +1,68 @@
1
- require "pathname"
2
- this_dir = Pathname.new File.dirname(__FILE__)
3
- require this_dir.join('boot')
4
-
5
- # Parse the options passed in via the command line
6
- options = BenchmarkOptionParser.parse( ARGV )
7
-
8
- # The support directory where we use to load our connections and models for the
9
- # benchmarks.
10
- SUPPORT_DIR = this_dir.join('../test')
11
-
12
- # Load the database adapter
13
- adapter = options.adapter
14
-
15
- # load the library
16
- LIB_DIR = this_dir.join("../lib")
17
- require LIB_DIR.join("activerecord-import/#{adapter}")
18
-
19
- ActiveRecord::Base.logger = Logger.new("log/test.log")
20
- ActiveRecord::Base.logger.level = Logger::DEBUG
21
- ActiveRecord::Base.configurations["test"] = YAML.load(SUPPORT_DIR.join("database.yml").open)[adapter]
22
- ActiveRecord::Base.establish_connection "test"
23
-
24
- ActiveSupport::Notifications.subscribe(/active_record.sql/) do |event, _, _, _, hsh|
25
- ActiveRecord::Base.logger.info hsh[:sql]
26
- end
27
-
28
- adapter_schema = SUPPORT_DIR.join("schema/#{adapter}_schema.rb")
29
- require adapter_schema if File.exists?(adapter_schema)
30
- Dir[this_dir.join("models/*.rb")].each{ |file| require file }
31
-
32
- # Load databse specific benchmarks
33
- require File.join( File.dirname( __FILE__ ), 'lib', "#{adapter}_benchmark" )
34
-
35
- # TODO implement method/table-type selection
36
- table_types = nil
37
- if options.benchmark_all_types
38
- table_types = [ "all" ]
39
- else
40
- table_types = options.table_types.keys
41
- end
42
- puts
43
-
44
- letter = options.adapter[0].chr
45
- clazz_str = letter.upcase + options.adapter[1..-1].downcase
46
- clazz = Object.const_get( clazz_str + "Benchmark" )
47
-
48
- benchmarks = []
49
- options.number_of_objects.each do |num|
50
- benchmarks << (benchmark = clazz.new)
51
- benchmark.send( "benchmark", table_types, num )
52
- end
53
-
54
- options.outputs.each do |output|
55
- format = output.format.downcase
56
- output_module = Object.const_get( "OutputTo#{format.upcase}" )
57
- benchmarks.each do |benchmark|
58
- output_module.output_results( output.filename, benchmark.results )
59
- end
60
- end
61
-
62
- puts
63
- puts "Done with benchmark!"
64
-
1
+ require 'pathname'
2
+ require "fileutils"
3
+ require "active_record"
4
+ require "active_record/base"
5
+
6
+ benchmark_dir = File.dirname(__FILE__)
7
+
8
+ $LOAD_PATH.unshift('.')
9
+
10
+ # Get the gem into the load path
11
+ $LOAD_PATH.unshift(File.join(benchmark_dir, '..', 'lib'))
12
+
13
+ # Load the benchmark files
14
+ Dir[File.join( benchmark_dir, 'lib', '*.rb' )].sort.each { |f| require f }
15
+
16
+ # Parse the options passed in via the command line
17
+ options = BenchmarkOptionParser.parse( ARGV )
18
+
19
+ FileUtils.mkdir_p 'log'
20
+ ActiveRecord::Base.configurations["test"] = YAML.load_file(File.join(benchmark_dir, "../test/database.yml"))[options.adapter]
21
+ ActiveRecord::Base.logger = Logger.new("log/test.log")
22
+ ActiveRecord::Base.logger.level = Logger::DEBUG
23
+ ActiveRecord::Base.default_timezone = :utc
24
+
25
+ require "activerecord-import"
26
+ ActiveRecord::Base.establish_connection(:test)
27
+
28
+ ActiveSupport::Notifications.subscribe(/active_record.sql/) do |_, _, _, _, hsh|
29
+ ActiveRecord::Base.logger.info hsh[:sql]
30
+ end
31
+
32
+ # Load base/generic schema
33
+ require File.join(benchmark_dir, "../test/schema/version")
34
+ require File.join(benchmark_dir, "../test/schema/generic_schema")
35
+ adapter_schema = File.join(benchmark_dir, "schema/#{options.adapter}_schema.rb")
36
+ require adapter_schema if File.exist?(adapter_schema)
37
+
38
+ Dir[File.dirname(__FILE__) + "/models/*.rb"].each { |file| require file }
39
+
40
+ require File.join( benchmark_dir, 'lib', "#{options.adapter}_benchmark" )
41
+
42
+ table_types = nil
43
+ table_types = if options.benchmark_all_types
44
+ ["all"]
45
+ else
46
+ options.table_types.keys
47
+ end
48
+
49
+ letter = options.adapter[0].chr
50
+ clazz_str = letter.upcase + options.adapter[1..-1].downcase
51
+ clazz = Object.const_get( clazz_str + "Benchmark" )
52
+
53
+ benchmarks = []
54
+ options.number_of_objects.each do |num|
55
+ benchmarks << (benchmark = clazz.new)
56
+ benchmark.send( "benchmark", table_types, num )
57
+ end
58
+
59
+ options.outputs.each do |output|
60
+ format = output.format.downcase
61
+ output_module = Object.const_get( "OutputTo#{format.upcase}" )
62
+ benchmarks.each do |benchmark|
63
+ output_module.output_results( output.filename, benchmark.results )
64
+ end
65
+ end
66
+
67
+ puts
68
+ puts "Done with benchmark!"
@@ -1,137 +1,138 @@
1
- class BenchmarkBase
2
-
3
- attr_reader :results
4
-
5
- # The main benchmark method dispatcher. This dispatches the benchmarks
6
- # to actual benchmark_xxxx methods.
7
- #
8
- # == PARAMETERS
9
- # * table_types - an array of table types to benchmark
10
- # * num - the number of record insertions to test
11
- def benchmark( table_types, num )
12
- array_of_cols_and_vals = build_array_of_cols_and_vals( num )
13
- table_types.each do |table_type|
14
- self.send( "benchmark_#{table_type}", array_of_cols_and_vals )
15
- end
16
- end
17
-
18
- # Returns an OpenStruct which contains two attritues, +description+ and +tms+ after performing an
19
- # actual benchmark.
20
- #
21
- # == PARAMETERS
22
- # * description - the description of the block that is getting benchmarked
23
- # * blk - the block of code to benchmark
24
- #
25
- # == RETURNS
26
- # An OpenStruct object with the following attributes:
27
- # * description - the description of the benchmark ran
28
- # * tms - a Benchmark::Tms containing the results of the benchmark
29
- def bm( description, &blk )
30
- tms = nil
31
- puts "Benchmarking #{description}"
32
-
33
- Benchmark.bm { |x| tms = x.report { blk.call } }
34
- delete_all
35
- failed = false
36
-
37
- OpenStruct.new :description=>description, :tms=>tms, :failed=>failed
38
- end
39
-
40
- # Given a model class (ie: Topic), and an array of columns and value sets
41
- # this will perform all of the benchmarks necessary for this library.
42
- #
43
- # == PARAMETERS
44
- # * model_clazz - the model class to benchmark (ie: Topic)
45
- # * array_of_cols_and_vals - an array of column identifiers and value sets
46
- #
47
- # == RETURNS
48
- # returns true
49
- def bm_model( model_clazz, array_of_cols_and_vals )
50
- puts
51
- puts "------ Benchmarking #{model_clazz.name} -------"
52
-
53
- cols,vals = array_of_cols_and_vals
54
- num_inserts = vals.size
55
-
56
- # add a new result group for this particular benchmark
57
- group = []
58
- @results << group
59
-
60
- description = "#{model_clazz.name}.create (#{num_inserts} records)"
61
- group << bm( description ) {
62
- vals.each do |values|
63
- model_clazz.create create_hash_for_cols_and_vals( cols, values )
64
- end }
65
-
66
- description = "#{model_clazz.name}.import(column, values) for #{num_inserts} records with validations"
67
- group << bm( description ) { model_clazz.import cols, vals, :validate=>true }
68
-
69
- description = "#{model_clazz.name}.import(columns, values) for #{num_inserts} records without validations"
70
- group << bm( description ) { model_clazz.import cols, vals, :validate=>false }
71
-
72
- models = []
73
- array_of_attrs = []
74
-
75
- vals.each do |arr|
76
- array_of_attrs << (attrs={})
77
- arr.each_with_index { |value, i| attrs[cols[i]] = value }
78
- end
79
- array_of_attrs.each{ |attrs| models << model_clazz.new(attrs) }
80
-
81
- description = "#{model_clazz.name}.import(models) for #{num_inserts} records with validations"
82
- group << bm( description ) { model_clazz.import models, :validate=>true }
83
-
84
- description = "#{model_clazz.name}.import(models) for #{num_inserts} records without validations"
85
- group << bm( description ) { model_clazz.import models, :validate=>false }
86
-
87
- true
88
- end
89
-
90
- # Returns a two element array composing of an array of columns and an array of
91
- # value sets given the passed +num+.
92
- #
93
- # === What is a value set?
94
- # A value set is an array of arrays. Each child array represents an array of value sets
95
- # for a given row of data.
96
- #
97
- # For example, say we wanted to represent an insertion of two records:
98
- # column_names = [ 'id', 'name', 'description' ]
99
- # record1 = [ 1, 'John Doe', 'A plumber' ]
100
- # record2 = [ 2, 'John Smith', 'A painter' ]
101
- # value_set [ record1, record2 ]
102
- #
103
- # == PARAMETER
104
- # * num - the number of records to create
105
- def build_array_of_cols_and_vals( num )
106
- cols = [ :my_name, :description ]
107
- value_sets = []
108
- num.times { |i| value_sets << [ "My Name #{i}", "My Description #{i}" ] }
109
- [ cols, value_sets ]
110
- end
111
-
112
- # Returns a hash of column identifier to value mappings giving the passed in
113
- # value array.
114
- #
115
- # Example:
116
- # cols = [ 'id', 'name', 'description' ]
117
- # values = [ 1, 'John Doe', 'A plumber' ]
118
- # hsh = create_hash_for_cols_and_vals( cols, values )
119
- # # hsh => { 'id'=>1, 'name'=>'John Doe', 'description'=>'A plumber' }
120
- def create_hash_for_cols_and_vals( cols, vals )
121
- h = {}
122
- cols.zip( vals ){ |col,val| h[col] = val }
123
- h
124
- end
125
-
126
- # Deletes all records from all ActiveRecord subclasses
127
- def delete_all
128
- ActiveRecord::Base.send( :subclasses ).each do |subclass|
129
- subclass.delete_all if subclass.respond_to? :delete_all
130
- end
131
- end
132
-
133
- def initialize # :nodoc:
134
- @results = []
135
- end
136
-
137
- end
1
+ class BenchmarkBase
2
+ attr_reader :results
3
+
4
+ # The main benchmark method dispatcher. This dispatches the benchmarks
5
+ # to actual benchmark_xxxx methods.
6
+ #
7
+ # == PARAMETERS
8
+ # * table_types - an array of table types to benchmark
9
+ # * num - the number of record insertions to test
10
+ def benchmark( table_types, num )
11
+ array_of_cols_and_vals = build_array_of_cols_and_vals( num )
12
+ table_types.each do |table_type|
13
+ send( "benchmark_#{table_type}", array_of_cols_and_vals )
14
+ end
15
+ end
16
+
17
+ # Returns an OpenStruct which contains two attritues, +description+ and +tms+ after performing an
18
+ # actual benchmark.
19
+ #
20
+ # == PARAMETERS
21
+ # * description - the description of the block that is getting benchmarked
22
+ # * blk - the block of code to benchmark
23
+ #
24
+ # == RETURNS
25
+ # An OpenStruct object with the following attributes:
26
+ # * description - the description of the benchmark ran
27
+ # * tms - a Benchmark::Tms containing the results of the benchmark
28
+ def bm( description )
29
+ tms = nil
30
+ puts "Benchmarking #{description}"
31
+
32
+ Benchmark.bm { |x| tms = x.report { yield } }
33
+ delete_all
34
+ failed = false
35
+
36
+ OpenStruct.new description: description, tms: tms, failed: failed
37
+ end
38
+
39
+ # Given a model class (ie: Topic), and an array of columns and value sets
40
+ # this will perform all of the benchmarks necessary for this library.
41
+ #
42
+ # == PARAMETERS
43
+ # * model_clazz - the model class to benchmark (ie: Topic)
44
+ # * array_of_cols_and_vals - an array of column identifiers and value sets
45
+ #
46
+ # == RETURNS
47
+ # returns true
48
+ def bm_model( model_clazz, array_of_cols_and_vals )
49
+ puts
50
+ puts "------ Benchmarking #{model_clazz.name} -------"
51
+
52
+ cols, vals = array_of_cols_and_vals
53
+ num_inserts = vals.size
54
+
55
+ # add a new result group for this particular benchmark
56
+ group = []
57
+ @results << group
58
+
59
+ description = "#{model_clazz.name}.create (#{num_inserts} records)"
60
+ group << bm( description ) do
61
+ vals.each do |values|
62
+ model_clazz.create create_hash_for_cols_and_vals( cols, values )
63
+ end
64
+ end
65
+
66
+ description = "#{model_clazz.name}.import(column, values) for #{num_inserts} records with validations"
67
+ group << bm( description ) { model_clazz.import cols, vals, validate: true }
68
+
69
+ description = "#{model_clazz.name}.import(columns, values) for #{num_inserts} records without validations"
70
+ group << bm( description ) { model_clazz.import cols, vals, validate: false }
71
+
72
+ models = []
73
+ array_of_attrs = []
74
+
75
+ vals.each do |arr|
76
+ array_of_attrs << (attrs = {})
77
+ arr.each_with_index { |value, i| attrs[cols[i]] = value }
78
+ end
79
+ array_of_attrs.each { |attrs| models << model_clazz.new(attrs) }
80
+
81
+ description = "#{model_clazz.name}.import(models) for #{num_inserts} records with validations"
82
+ group << bm( description ) { model_clazz.import models, validate: true }
83
+
84
+ description = "#{model_clazz.name}.import(models) for #{num_inserts} records without validations"
85
+ group << bm( description ) { model_clazz.import models, validate: false }
86
+
87
+ true
88
+ end
89
+
90
+ # Returns a two element array composing of an array of columns and an array of
91
+ # value sets given the passed +num+.
92
+ #
93
+ # === What is a value set?
94
+ # A value set is an array of arrays. Each child array represents an array of value sets
95
+ # for a given row of data.
96
+ #
97
+ # For example, say we wanted to represent an insertion of two records:
98
+ # column_names = [ 'id', 'name', 'description' ]
99
+ # record1 = [ 1, 'John Doe', 'A plumber' ]
100
+ # record2 = [ 2, 'John Smith', 'A painter' ]
101
+ # value_set [ record1, record2 ]
102
+ #
103
+ # == PARAMETER
104
+ # * num - the number of records to create
105
+ def build_array_of_cols_and_vals( num )
106
+ cols = [:my_name, :description]
107
+ value_sets = []
108
+ num.times { |i| value_sets << ["My Name #{i}", "My Description #{i}"] }
109
+ [cols, value_sets]
110
+ end
111
+
112
+ # Returns a hash of column identifier to value mappings giving the passed in
113
+ # value array.
114
+ #
115
+ # Example:
116
+ # cols = [ 'id', 'name', 'description' ]
117
+ # values = [ 1, 'John Doe', 'A plumber' ]
118
+ # hsh = create_hash_for_cols_and_vals( cols, values )
119
+ # # hsh => { 'id'=>1, 'name'=>'John Doe', 'description'=>'A plumber' }
120
+ def create_hash_for_cols_and_vals( cols, vals )
121
+ h = {}
122
+ cols.zip( vals ) { |col, val| h[col] = val }
123
+ h
124
+ end
125
+
126
+ # Deletes all records from all ActiveRecord subclasses
127
+ def delete_all
128
+ ActiveRecord::Base.send( :subclasses ).each do |subclass|
129
+ if subclass.table_exists? && subclass.respond_to?(:delete_all)
130
+ subclass.delete_all
131
+ end
132
+ end
133
+ end
134
+
135
+ def initialize # :nodoc:
136
+ @results = []
137
+ end
138
+ end