bulk-insert-active-record 0.0.2 → 0.0.4

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