Skip to content

Commit 028e7d8

Browse files
committed
initial commit
0 parents  commit 028e7d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1277
-0
lines changed

.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.bundle/
2+
log/*.log
3+
pkg/
4+
test/dummy/db/*.sqlite3
5+
test/dummy/db/*.sqlite3-journal
6+
test/dummy/log/*.log
7+
test/dummy/tmp/
8+
test/dummy/.sass-cache

Gemfile

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
source 'https://rubygems.org'
2+
3+
# Declare your gem's dependencies in bulk_insert.gemspec.
4+
# Bundler will treat runtime dependencies like base dependencies, and
5+
# development dependencies will be added by default to the :development group.
6+
gemspec
7+
8+
# Declare any dependencies that are still in development here instead of in
9+
# your gemspec. These might include edge Rails or gems from your path or
10+
# Git. Remember to move these dependencies to your gemspec before releasing
11+
# your gem to rubygems.org.
12+
13+
# To use a debugger
14+
# gem 'byebug', group: [:development, :test]
15+

Gemfile.lock

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
PATH
2+
remote: .
3+
specs:
4+
bulk_insert (1.0.0)
5+
activerecord (~> 4.2.2)
6+
7+
GEM
8+
remote: https://rubygems.org/
9+
specs:
10+
actionmailer (4.2.4)
11+
actionpack (= 4.2.4)
12+
actionview (= 4.2.4)
13+
activejob (= 4.2.4)
14+
mail (~> 2.5, >= 2.5.4)
15+
rails-dom-testing (~> 1.0, >= 1.0.5)
16+
actionpack (4.2.4)
17+
actionview (= 4.2.4)
18+
activesupport (= 4.2.4)
19+
rack (~> 1.6)
20+
rack-test (~> 0.6.2)
21+
rails-dom-testing (~> 1.0, >= 1.0.5)
22+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
23+
actionview (4.2.4)
24+
activesupport (= 4.2.4)
25+
builder (~> 3.1)
26+
erubis (~> 2.7.0)
27+
rails-dom-testing (~> 1.0, >= 1.0.5)
28+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
29+
activejob (4.2.4)
30+
activesupport (= 4.2.4)
31+
globalid (>= 0.3.0)
32+
activemodel (4.2.4)
33+
activesupport (= 4.2.4)
34+
builder (~> 3.1)
35+
activerecord (4.2.4)
36+
activemodel (= 4.2.4)
37+
activesupport (= 4.2.4)
38+
arel (~> 6.0)
39+
activesupport (4.2.4)
40+
i18n (~> 0.7)
41+
json (~> 1.7, >= 1.7.7)
42+
minitest (~> 5.1)
43+
thread_safe (~> 0.3, >= 0.3.4)
44+
tzinfo (~> 1.1)
45+
arel (6.0.3)
46+
builder (3.2.2)
47+
erubis (2.7.0)
48+
globalid (0.3.6)
49+
activesupport (>= 4.1.0)
50+
i18n (0.7.0)
51+
json (1.8.3)
52+
loofah (2.0.3)
53+
nokogiri (>= 1.5.9)
54+
mail (2.6.3)
55+
mime-types (>= 1.16, < 3)
56+
mime-types (2.6.2)
57+
mini_portile (0.6.2)
58+
minitest (5.8.1)
59+
nokogiri (1.6.6.2)
60+
mini_portile (~> 0.6.0)
61+
rack (1.6.4)
62+
rack-test (0.6.3)
63+
rack (>= 1.0)
64+
rails (4.2.4)
65+
actionmailer (= 4.2.4)
66+
actionpack (= 4.2.4)
67+
actionview (= 4.2.4)
68+
activejob (= 4.2.4)
69+
activemodel (= 4.2.4)
70+
activerecord (= 4.2.4)
71+
activesupport (= 4.2.4)
72+
bundler (>= 1.3.0, < 2.0)
73+
railties (= 4.2.4)
74+
sprockets-rails
75+
rails-deprecated_sanitizer (1.0.3)
76+
activesupport (>= 4.2.0.alpha)
77+
rails-dom-testing (1.0.7)
78+
activesupport (>= 4.2.0.beta, < 5.0)
79+
nokogiri (~> 1.6.0)
80+
rails-deprecated_sanitizer (>= 1.0.1)
81+
rails-html-sanitizer (1.0.2)
82+
loofah (~> 2.0)
83+
railties (4.2.4)
84+
actionpack (= 4.2.4)
85+
activesupport (= 4.2.4)
86+
rake (>= 0.8.7)
87+
thor (>= 0.18.1, < 2.0)
88+
rake (10.4.2)
89+
sprockets (3.4.0)
90+
rack (> 1, < 3)
91+
sprockets-rails (2.3.3)
92+
actionpack (>= 3.0)
93+
activesupport (>= 3.0)
94+
sprockets (>= 2.8, < 4.0)
95+
sqlite3 (1.3.10)
96+
thor (0.19.1)
97+
thread_safe (0.3.5)
98+
tzinfo (1.2.2)
99+
thread_safe (~> 0.1)
100+
101+
PLATFORMS
102+
ruby
103+
104+
DEPENDENCIES
105+
bulk_insert!
106+
rails (~> 4.2.2)
107+
sqlite3
108+
109+
BUNDLED WITH
110+
1.10.6

MIT-LICENSE

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright 2015 Jamis Buck
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be
12+
included in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# BulkInsert
2+
3+
A little ActiveRecord extension for helping to insert lots of rows in a
4+
single insert statement.
5+
6+
## Installation
7+
8+
Add it to your Gemfile:
9+
10+
gem 'bulk_insert'
11+
12+
## Usage
13+
14+
BulkInsert adds a new class method to your ActiveRecord models:
15+
16+
class Book < ActiveRecord::Base
17+
end
18+
19+
book_attrs = ... # some array of hashes, for instance
20+
Book.bulk_insert do |worker|
21+
book_attrs.each do |attrs|
22+
worker.add(attrs)
23+
end
24+
end
25+
26+
All of those `#add` calls will be accumulated into a single SQL insert
27+
statement, vastly improving the performance of multiple sequential
28+
inserts (think data imports and the like).
29+
30+
By default, the columns to be inserted will be all columns in the table,
31+
minus the `id` column, but if you want, you can explicitly enumerate
32+
the columns:
33+
34+
Book.bulk_insert(:title, :author) do |worker|
35+
# specify a row as an array of values...
36+
worker.add ["Eye of the World", "Robert Jordan"]
37+
38+
# or as a hash
39+
worker.add title: "Lord of Light", author: "Roger Zelazny"
40+
end
41+
42+
It will automatically set created_at/updated_at columns to the current
43+
date, as well.
44+
45+
Book.bulk_insert(:title, :author, :created_at, :updated_at) do |worker|
46+
# specify created_at/updated_at explicitly...
47+
worker.add ["The Chosen", "Chaim Potok", Time.now, Time.now]
48+
49+
# or let BulkInsert set them by default...
50+
worker.add ["Hello Ruby", "Linda Liukas"]
51+
end
52+
53+
By default, the batch is always saved when the block finishes, but you
54+
can explicitly save inside the block whenever you want, by calling
55+
`#save!` on the worker:
56+
57+
Book.bulk_insert do |worker|
58+
worker.add(...)
59+
worker.add(...)
60+
61+
worker.save!
62+
63+
worker.add(...)
64+
#...
65+
end
66+
67+
That will save the batch as it has been defined to that point, and then
68+
empty the batch so that you can add more rows to it if you want.
69+
70+
71+
### Batch Set Size
72+
73+
By default, the size of the insert is limited to 500 rows at a time.
74+
This is called the _set size_. If you add another row that causes the
75+
set to exceed the set size, the insert statement is automatically built
76+
and executed, and the batch is reset.
77+
78+
If you want a larger (or smaller) set size, you can specify it in
79+
two ways:
80+
81+
# specify set_size when initializing the bulk insert...
82+
Book.bulk_insert(set_size: 100) do |worker|
83+
# ...
84+
end
85+
86+
# specify it on the worker directly...
87+
Book.bulk_insert do |worker|
88+
worker.set_size = 100
89+
# ...
90+
end
91+
92+
93+
## License
94+
95+
BulkInsert is released under the MIT license (see MIT-LICENSE) by
96+
Jamis Buck ([email protected]).

Rakefile

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
begin
2+
require 'bundler/setup'
3+
rescue LoadError
4+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5+
end
6+
7+
require 'rdoc/task'
8+
9+
RDoc::Task.new(:rdoc) do |rdoc|
10+
rdoc.rdoc_dir = 'rdoc'
11+
rdoc.title = 'BulkInsert'
12+
rdoc.options << '--line-numbers'
13+
rdoc.rdoc_files.include('README.rdoc')
14+
rdoc.rdoc_files.include('lib/**/*.rb')
15+
end
16+
17+
18+
19+
20+
21+
22+
Bundler::GemHelper.install_tasks
23+
24+
require 'rake/testtask'
25+
26+
Rake::TestTask.new(:test) do |t|
27+
t.libs << 'lib'
28+
t.libs << 'test'
29+
t.pattern = 'test/**/*_test.rb'
30+
t.verbose = false
31+
end
32+
33+
34+
task default: :test

bulk_insert.gemspec

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
$:.push File.expand_path("../lib", __FILE__)
2+
3+
# Maintain your gem's version:
4+
require "bulk_insert/version"
5+
6+
# Describe your gem and declare its dependencies:
7+
Gem::Specification.new do |s|
8+
s.name = "bulk_insert"
9+
s.version = BulkInsert::VERSION
10+
s.authors = ["Jamis Buck"]
11+
s.email = ["[email protected]"]
12+
s.homepage = "http://github.com/jamis/bulk_insert"
13+
s.summary = "An helper for doing batch (single-statement) inserts in ActiveRecord"
14+
s.description = "Faster inserts! Insert N records in a single statement."
15+
s.license = "MIT"
16+
17+
s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
18+
s.test_files = Dir["test/**/*"]
19+
20+
s.add_dependency "activerecord", "~> 4.2.2"
21+
22+
s.add_development_dependency "sqlite3"
23+
s.add_development_dependency "rails", "~> 4.2.2"
24+
end

lib/bulk_insert.rb

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
require 'bulk_insert/worker'
2+
3+
module BulkInsert
4+
extend ActiveSupport::Concern
5+
6+
class_methods do
7+
def bulk_insert(*columns, set_size:500)
8+
columns = self.column_names - %w(id) if columns.empty?
9+
worker = BulkInsert::Worker.new(connection, table_name, columns, set_size)
10+
11+
if block_given?
12+
transaction do
13+
yield worker
14+
worker.save!
15+
end
16+
self
17+
else
18+
worker
19+
end
20+
end
21+
end
22+
end
23+
24+
ActiveRecord::Base.send :include, BulkInsert

lib/bulk_insert/version.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module BulkInsert
2+
MAJOR = 1
3+
MINOR = 0
4+
TINY = 0
5+
6+
VERSION = [MAJOR, MINOR, TINY].join(".")
7+
end

0 commit comments

Comments
 (0)