bulk-insert-active-record 0.0.2 → 0.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5beeb7910f5ef8e32473555c9751cac42ad66e49
4
- data.tar.gz: 28c6046aea568b83c63b0aebc572b239037e6399
3
+ metadata.gz: 002fae46c420ba556c11d06b5dbd505de1e4ffac
4
+ data.tar.gz: 3564bc97c838fae38bf920b713a10f3f5ac371a7
5
5
  SHA512:
6
- metadata.gz: ba855ac9007b318c731402a5351fbf1d39273b55a248262b55a863558b624096f0133a8c94b44850054934c62e3514944a83ac6501839e2f3cff65ec3a9afbe9
7
- data.tar.gz: 0a3fc69b69e08671eb6b06bf01a19cf37179000bc33b0b6f3578155d14d35853cb7d4ee9a6aa3cdc5e4968562f9934383521c043d86299fa4ce2c867aca3d177
6
+ metadata.gz: df5dce359603164410f145d8a6b661e3b89fcb8ba49dd0ed6c47d0a096b66a7ca5f4aeb71bf92b26ee43079fc4505267c10f8d81c34a7f67ec21ea4baf322ad5
7
+ data.tar.gz: 0b48d16f0e2c49bca418e8a2afcc26d8d016f0ffe3648feaa0eec3b1cc77c710a27f601f21ff066863172d6906769129a1ebfe67cb4dd14d03691f7be673662b
data/.gitignore CHANGED
@@ -1,17 +1,2 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
1
+ /.bundle/
2
+ /pkg/
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ Metrics/AbcSize:
2
+ Max: 20
3
+ Metrics/LineLength:
4
+ Max: 120
5
+ Metrics/MethodLength:
6
+ Max: 15
data/.ruby-gemset CHANGED
@@ -1 +1 @@
1
- bulk-insert-active-record
1
+ bulk-insert-active-record
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
1
  source('https://rubygems.org')
2
2
 
3
- gemspec
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,56 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ bulk-insert-active-record (0.0.4)
5
+ activerecord (>= 3)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (4.2.6)
11
+ activesupport (= 4.2.6)
12
+ builder (~> 3.1)
13
+ activerecord (4.2.6)
14
+ activemodel (= 4.2.6)
15
+ activesupport (= 4.2.6)
16
+ arel (~> 6.0)
17
+ activesupport (4.2.6)
18
+ i18n (~> 0.7)
19
+ json (~> 1.7, >= 1.7.7)
20
+ minitest (~> 5.1)
21
+ thread_safe (~> 0.3, >= 0.3.4)
22
+ tzinfo (~> 1.1)
23
+ arel (6.0.3)
24
+ ast (2.2.0)
25
+ builder (3.2.2)
26
+ i18n (0.7.0)
27
+ json (1.8.3)
28
+ minitest (5.9.0)
29
+ parser (2.3.1.0)
30
+ ast (~> 2.2)
31
+ powerpack (0.1.1)
32
+ rainbow (2.1.0)
33
+ rake (11.1.2)
34
+ rubocop (0.40.0)
35
+ parser (>= 2.3.1.0, < 3.0)
36
+ powerpack (~> 0.1)
37
+ rainbow (>= 1.99.1, < 3.0)
38
+ ruby-progressbar (~> 1.7)
39
+ unicode-display_width (~> 1.0, >= 1.0.1)
40
+ ruby-progressbar (1.8.1)
41
+ thread_safe (0.3.5)
42
+ tzinfo (1.2.2)
43
+ thread_safe (~> 0.1)
44
+ unicode-display_width (1.0.5)
45
+
46
+ PLATFORMS
47
+ ruby
48
+
49
+ DEPENDENCIES
50
+ bulk-insert-active-record!
51
+ bundler (~> 1.12)
52
+ rake
53
+ rubocop
54
+
55
+ BUNDLED WITH
56
+ 1.12.4
data/README.md CHANGED
@@ -1,27 +1,25 @@
1
1
  # Bulk Insert Active Record (for ActiveRecord 3 or higher)
2
2
 
3
- This gem extends Active Record and allows you to insert multiple records in one SQL statement,
4
- dramatically increasing performance.
3
+ This gem extends Active Record and allows you to insert multiple records in one SQL statement, dramatically increasing
4
+ performance.
5
5
 
6
6
  ## Current status
7
7
 
8
- This gem is currently actively in development, but because it's already useful, I've decided to
9
- publish it in its premature state. Right now it has been manually tested with MySQL and SQL Server
10
- via JDBC.
8
+ This gem is currently actively in development, but because it's already useful, I've decided to publish it in its
9
+ premature state. Right now it has been manually tested with MySQL and SQL Server via JDBC.
11
10
 
12
11
  ## Usage
13
12
 
14
- Installation is done by adding the gem your *Gemfile* and running Bundler. After loading Active
15
- Record an extra class method is available for your models.
13
+ Installation is done by adding the gem your *Gemfile* and running Bundler. After loading Active Record an extra class
14
+ method is available for your models.
16
15
 
17
16
  ## Examples
18
17
 
19
- Suppose you want to insert multiple Post records in the database. This can be done in different
20
- ways:
18
+ Suppose you want to insert multiple Post records in the database. This can be done in different ways:
21
19
 
22
20
  # suppose it has 3 columns (`id`, `author` and `text`)
23
21
  class Post < ActiveRecord::Base
24
- end
22
+ end
25
23
 
26
24
  # create an array of arrays
27
25
  posts = [
@@ -36,4 +34,4 @@ ways:
36
34
 
37
35
  # Copyright
38
36
 
39
- &copy; 2014 Walter Horstman, [IT on Rails](http://itonrails.com)
37
+ &copy; 2016 Walter Horstman, [IT on Rails](http://itonrails.com)
data/Rakefile CHANGED
@@ -1 +1 @@
1
- require "bundler/gem_tasks"
1
+ require('bundler/gem_tasks')
@@ -1,22 +1,23 @@
1
- # coding: utf-8
1
+ # encoding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = 'bulk-insert-active-record'
7
- spec.summary = 'Lightweight bulk insert mechanism for ActiveRecord 3 or higher'
8
- spec.description = 'This gem allows you to insert multiple rows as once, dramatically increasing performance.'
9
- spec.version = '0.0.2'
10
- spec.required_ruby_version = '>= 1.9.2'
6
+ spec.name = 'bulk-insert-active-record'
7
+ spec.version = '0.0.4'
8
+ spec.author = ['Walter Horstman']
9
+ spec.email = ['walter.horstman@itonrails.com']
11
10
 
12
- spec.author = 'Walter Horstman'
13
- spec.email = 'walter.horstman@itonrails.com'
14
- spec.homepage = 'https://github.com/walterhorstman/bulk-insert-active-record'
11
+ spec.summary = 'Lightweight bulk insert mechanism for ActiveRecord 3 or higher'
12
+ spec.description = 'This gem allows you to insert multiple rows as once, dramatically increasing performance.'
13
+ spec.homepage = 'https://github.com/walterhorstman/bulk-insert-active-record'
15
14
 
16
- spec.files = `git ls-files -z`.split("\x0")
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_path = 'lib'
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.require_paths = ['lib']
20
18
 
21
19
  spec.add_dependency('activerecord', '>= 3')
22
- end
20
+ spec.add_development_dependency('bundler', '~> 1.12')
21
+ spec.add_development_dependency('rake')
22
+ spec.add_development_dependency('rubocop')
23
+ end
@@ -1,32 +1,30 @@
1
+ # rubocop:disable Style/FileName
1
2
  require_relative('inserters')
2
3
 
4
+ # Extends the given base class (a subclass of ActiveRecord::Base) with a bulk_insert() class method.
3
5
  module BulkInsertActiveRecord
4
-
6
+ # rubocop:disable Metrics/MethodLength
5
7
  def self.included(base)
6
8
  base.class_eval do
9
+ def self.bulk_insert(records, columns = column_names)
10
+ raise('No connection with the database') unless connection.active?
7
11
 
8
- def self.bulk_insert(records, column_names = self.column_names)
9
- fail('No connection with the database') unless self.connection.active?
10
-
11
- inserter = Inserters::factory(self)
12
- self.transaction do
12
+ inserter = Inserters.factory(self)
13
+ transaction do
13
14
  if inserter.nil?
14
- self.insert_one_by_one(records, column_names)
15
+ insert_one_by_one(records, columns)
15
16
  else
16
- sql = inserter.statement(records, column_names)
17
- self.connection.insert(sql)
17
+ inserter.execute(records, columns)
18
18
  end
19
19
  end
20
20
  end
21
21
 
22
- private
23
-
24
22
  def self.insert_one_by_one(records, column_names)
25
23
  records.each do |record|
26
24
  if record.is_a?(self)
27
25
  record.save
28
26
  else
29
- item = self.new
27
+ item = new
30
28
  column_names.each_with_index do |column_name, index|
31
29
  item[column_name] = record[index]
32
30
  end
@@ -36,8 +34,9 @@ module BulkInsertActiveRecord
36
34
  end
37
35
  end
38
36
  end
37
+ # rubocop:enable Metrics/MethodLength
39
38
  end
40
39
 
41
40
  ActiveSupport.on_load(:active_record) do
42
41
  include(BulkInsertActiveRecord)
43
- end
42
+ end
data/lib/inserters.rb CHANGED
@@ -1,17 +1,15 @@
1
1
  Dir[File.expand_path('../inserters/*.rb', __FILE__)].each { |file_name| require(file_name) }
2
2
 
3
3
  module BulkInsertActiveRecord
4
+ # Inserters module
4
5
  module Inserters
5
-
6
- def self.factory(active_record_class, options = {})
6
+ def self.factory(active_record_class)
7
7
  inserter_class = case active_record_class.connection.adapter_name.downcase
8
8
  when 'mssql', 'mysql', 'sqlserver' then Base
9
- # FIXME: as soon as we know which SQL statement to use, enable the next line
10
- # when 'oracle' then Oracle
11
- else nil
9
+ when 'oracle' then Oracle
12
10
  end
13
11
 
14
- inserter_class.nil? ? nil : inserter_class.new(active_record_class, options)
12
+ inserter_class.nil? ? nil : inserter_class.new(active_record_class)
15
13
  end
16
14
  end
17
- end
15
+ end
@@ -1,36 +1,23 @@
1
- # This base implementation works for MySQL and SQLServer
2
1
  module BulkInsertActiveRecord
3
2
  module Inserters
3
+ # This base implementation works for MySQL and SQLServer
4
4
  class Base
5
-
6
- def initialize(active_record_class, options = {})
5
+ def initialize(active_record_class)
7
6
  @connection = active_record_class.connection
8
7
  @quoted_table_name = active_record_class.quoted_table_name
9
-
10
- # basic bulk insert statement
11
- @statement = options[:statement] || 'INSERT INTO %{table_name}(%{columns_clause}) VALUES %{values_clause}'
12
- # character(s) used to separate columns in the columns_clause of the statement
13
- @column_separator = options[:column_separator] || ','
14
- # character(s) used to separate records in the values_clause of the statement
15
- @record_separator = options[:record_separator] || ','
16
- # sql fragment for individual records in the values_clause of the statement
17
- @record_statement = options[:record_statement] || '(%{value_clause})'
18
- # character(s) used to separate values in the value_clause of the record statement
19
- @value_separator = options[:value_separator] || ','
20
8
  end
21
9
 
22
- # returns bulk insert statement
23
- def statement(records, column_names)
24
- @statement % {
25
- table_name: @quoted_table_name,
26
- columns_clause: column_names.map { |column_name| @connection.quote_column_name(column_name) }.join(@column_separator),
27
- values_clause: records.map do |record|
28
- @record_statement % {
29
- value_clause: record.map { |value| @connection.quote(value) }.join(@value_separator)
30
- }
31
- end.join(@record_separator)
32
- }
10
+ def execute(records, column_names)
11
+ statement = 'INSERT INTO %{table_name}(%{columns_clause}) VALUES(%{values_clause})'
12
+ @connection.insert(format(statement, table_name: @quoted_table_name,
13
+ columns_clause: column_names.map do |column_name|
14
+ @connection.quote_column_name(column_name)
15
+ end.join(','),
16
+ values_clause: records.map do |record|
17
+ value_clause = record.map { |value| @connection.quote(value) }.join(',')
18
+ "(#{value_clause})"
19
+ end.join(',')))
33
20
  end
34
21
  end
35
22
  end
36
- end
23
+ end
@@ -1,17 +1,18 @@
1
- require_relative('sequenced')
2
-
3
1
  module BulkInsertActiveRecord
4
2
  module Inserters
5
- class Oracle < Sequenced
6
-
7
- def initialize(active_record_class, options = {})
8
- super(active_record_class, {
9
- statement: 'INSERT INTO %{table_name}(%{columns_clause}) %{values_clause}',
10
- record_statement: 'SELECT %{value_clause} FROM dual',
11
- sequence_statement: "#{active_record_class.sequence_name}.NEXTVAL",
12
- record_separator: ' UNION '
13
- }.merge(options))
3
+ # Implementation specific for Oracle
4
+ class Oracle < Base
5
+ def execute(records, column_names) # override
6
+ statement = 'BEGIN INSERT INTO %{table_name}(%{columns_clause}) VALUES(%{values_clause}); END;'
7
+ @connection.execute(format(statement, table_name: @quoted_table_name,
8
+ columns_clause: column_names.map do |column_name|
9
+ @connection.quote_column_name(column_name)
10
+ end.join(','),
11
+ values_clause: records.map do |record|
12
+ value_clause = record.map { |value| @connection.quote(value) }.join(',')
13
+ "SELECT #{value_clause} FROM dual"
14
+ end.join(' UNION ')))
14
15
  end
15
16
  end
16
17
  end
17
- end
18
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bulk-insert-active-record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Walter Horstman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-07 00:00:00.000000000 Z
11
+ date: 2016-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -24,16 +24,61 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
27
69
  description: This gem allows you to insert multiple rows as once, dramatically increasing
28
70
  performance.
29
- email: walter.horstman@itonrails.com
71
+ email:
72
+ - walter.horstman@itonrails.com
30
73
  executables: []
31
74
  extensions: []
32
75
  extra_rdoc_files: []
33
76
  files:
34
77
  - ".gitignore"
78
+ - ".rubocop.yml"
35
79
  - ".ruby-gemset"
36
80
  - Gemfile
81
+ - Gemfile.lock
37
82
  - README.md
38
83
  - Rakefile
39
84
  - bulk-insert-active-record.gemspec
@@ -41,7 +86,6 @@ files:
41
86
  - lib/inserters.rb
42
87
  - lib/inserters/base.rb
43
88
  - lib/inserters/oracle.rb
44
- - lib/inserters/sequenced.rb
45
89
  homepage: https://github.com/walterhorstman/bulk-insert-active-record
46
90
  licenses: []
47
91
  metadata: {}
@@ -53,7 +97,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
53
97
  requirements:
54
98
  - - ">="
55
99
  - !ruby/object:Gem::Version
56
- version: 1.9.2
100
+ version: '0'
57
101
  required_rubygems_version: !ruby/object:Gem::Requirement
58
102
  requirements:
59
103
  - - ">="
@@ -61,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
105
  version: '0'
62
106
  requirements: []
63
107
  rubyforge_project:
64
- rubygems_version: 2.2.2
108
+ rubygems_version: 2.5.1
65
109
  signing_key:
66
110
  specification_version: 4
67
111
  summary: Lightweight bulk insert mechanism for ActiveRecord 3 or higher
@@ -1,42 +0,0 @@
1
- require_relative('base')
2
-
3
- module BulkInsertActiveRecord
4
- module Inserters
5
- class Sequenced < Base
6
-
7
- def initialize(active_record_class, options = {})
8
- @primary_key_name = active_record_class.primary_key
9
- # SQL fragment defining how a sequenced value should be constructed
10
- @sequence_statement = options[:sequence_statement]
11
- super(active_record_class, options)
12
- end
13
-
14
- # returns bulk insert statement
15
- def statement(records, column_names)
16
- column_names.map!(&:to_s)
17
- # if a primary key column wasn't specified, add it manually
18
- add_primary_key = column_names.exclude?(@primary_key_name)
19
- column_names << @primary_key_name if add_primary_key
20
- # save position within each row array of the primary key
21
- primary_key_index = column_names.index(@primary_key_name)
22
-
23
- @statement % {
24
- table_name: @quoted_table_name,
25
- columns_clause: column_names.map { |column_name| @connection.quote_column_name(column_name) }.join(@column_separator),
26
- values_clause: records.map do |record|
27
- # if we need to manually added the primary key, add it to the end of the row array
28
- if add_primary_key
29
- record << @sequence_statement
30
- else
31
- record[primary_key_index] = (record[primary_key_index] == nil) ? @sequence_statement : @connection.quote(record[primary_key_index])
32
- end
33
-
34
- @record_statement % {
35
- value_clause: record.map.with_index { |value, index| (index == primary_key_index) ? value : @connection.quote(value) }.join(@value_separator)
36
- }
37
- end.join(@record_separator)
38
- }
39
- end
40
- end
41
- end
42
- end