bulk_update 1.1.4 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +1 -0
- data/lib/bulk_update/active_record_inflections.rb +72 -65
- data/lib/bulk_update/version.rb +1 -1
- data/spec/bulk_update_spec.rb +34 -0
- metadata +20 -34
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 67b504f96d894fd77d2298b021c3176c7ba46fc0
|
4
|
+
data.tar.gz: 5eb6122b5aed465c5765a5f3438a6d9e84e829b2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 42e704fca218625c5f77d3c479e6b678fb42cf9f6e4e1e1d6b0a498125cbdae7cef9ee9a6bbdd51393f988b20cb15ee72b4d73df5a156210626c3f98ece93469
|
7
|
+
data.tar.gz: 7aeb01c91beea5431af17d81795ee3329c1760ee83a0e5562a281b18a99421f46472ca3e7b265e928df89d9e4943103cf90c127756eae62a0ef81c25f772d14c
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# BulkUpdate
|
2
|
+
[![Code Climate](https://codeclimate.com/github/InWork/bulk_update.png)](https://codeclimate.com/github/InWork/bulk_update)
|
2
3
|
|
3
4
|
Updates a large amount of Records in a highliy efficient way.
|
4
5
|
Enhances Active Record with a method for bulk inserts and a method for bulk updates. Both methods are used for inserting or updating large amount of Records.
|
@@ -2,7 +2,7 @@ module BulkUpdate
|
|
2
2
|
module ActiveRecordInflections
|
3
3
|
#
|
4
4
|
# Clone the database structure of a table
|
5
|
-
def clone_table
|
5
|
+
def clone_table(args = {})
|
6
6
|
if args[:to]
|
7
7
|
case ActiveRecord::Base.connection_config[:adapter]
|
8
8
|
when 'sqlite3'
|
@@ -17,7 +17,7 @@ module BulkUpdate
|
|
17
17
|
end
|
18
18
|
|
19
19
|
|
20
|
-
def insert_str
|
20
|
+
def insert_str(element)
|
21
21
|
if element.class == Fixnum || element.class == Float
|
22
22
|
element
|
23
23
|
elsif element.class == NilClass
|
@@ -34,15 +34,15 @@ module BulkUpdate
|
|
34
34
|
|
35
35
|
#
|
36
36
|
# Bulk insert records
|
37
|
-
def bulk_insert
|
37
|
+
def bulk_insert(columns, values, args = {})
|
38
38
|
# Limit inserts
|
39
39
|
max_records_per_insert = args[:max_records_per_insert] || 100
|
40
|
-
table
|
41
|
-
columns
|
40
|
+
table = args[:into] || table_name
|
41
|
+
columns = columns.clone
|
42
42
|
|
43
43
|
# Add timestamp
|
44
|
-
timestamp
|
45
|
-
add_timestamp
|
44
|
+
timestamp = Time.now.to_s(:db)
|
45
|
+
add_timestamp = false
|
46
46
|
add_updated_at = false
|
47
47
|
unless columns.map(&:to_sym).include?(:created_at)
|
48
48
|
columns << :created_at
|
@@ -84,14 +84,14 @@ module BulkUpdate
|
|
84
84
|
#
|
85
85
|
# Create, update and delete Records according to a set of new values through ActiveRecord but optimized for performance by
|
86
86
|
# finding all diferences by SQL.
|
87
|
-
def bulk_update
|
88
|
-
temp_table
|
89
|
-
key
|
90
|
-
condition
|
87
|
+
def bulk_update(columns, values, args = {})
|
88
|
+
temp_table = "#{table_name}_temp_table_#{$$}"
|
89
|
+
key = args[:key] || args[:keys] || 'id'
|
90
|
+
condition = args[:condition]
|
91
91
|
exclude_fields = args[:exclude_fields]
|
92
|
-
insert
|
93
|
-
update
|
94
|
-
remove
|
92
|
+
insert = args[:insert].nil? ? true : args[:insert]
|
93
|
+
update = args[:update].nil? ? true : args[:update]
|
94
|
+
remove = args[:remove].nil? ? true : args[:remove]
|
95
95
|
|
96
96
|
# Clone temp-table and load it
|
97
97
|
clone_table to: temp_table
|
@@ -115,23 +115,30 @@ module BulkUpdate
|
|
115
115
|
#
|
116
116
|
# Exclude List
|
117
117
|
def default_exclude
|
118
|
-
['id', '
|
118
|
+
@default_exclude ||= ['id', 'created_at', 'updated_at']
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
#
|
123
|
+
# Exclude List
|
124
|
+
def default_exclude=(excludes)
|
125
|
+
@default_exclude = excludes
|
119
126
|
end
|
120
127
|
|
121
128
|
|
122
129
|
#
|
123
130
|
# Compare Table of args[:model] with its temporary table args[:compare_with] and return all new records as a Array of Hashes
|
124
|
-
def get_new_records
|
125
|
-
model
|
126
|
-
compare_table =
|
127
|
-
keys
|
128
|
-
exclude
|
129
|
-
exclude
|
131
|
+
def get_new_records(args = {})
|
132
|
+
model = args[:for] || self
|
133
|
+
compare_table = args[:compare_with]
|
134
|
+
keys = args[:on] || 'id'
|
135
|
+
exclude = args[:exclude_fields] || []
|
136
|
+
exclude |= default_exclude - %w(created_at updated_at)
|
130
137
|
|
131
138
|
# Generate conditions for query and sub-query
|
132
|
-
conditions
|
133
|
-
conditions2 =
|
134
|
-
conditions
|
139
|
+
conditions = []
|
140
|
+
conditions2 = []
|
141
|
+
conditions << "#{args[:condition].gsub('--tt--', compare_table)}" if args[:condition]
|
135
142
|
conditions2 << "#{args[:condition].gsub('--tt--', model.table_name)}" if args[:condition]
|
136
143
|
if keys.class == String || keys.class == Symbol
|
137
144
|
key = keys.to_s
|
@@ -141,7 +148,7 @@ module BulkUpdate
|
|
141
148
|
end
|
142
149
|
|
143
150
|
# Generate and execute SQL-Statement
|
144
|
-
condition
|
151
|
+
condition = conditions.join(' AND ')
|
145
152
|
condition2 = conditions2.join(' AND ')
|
146
153
|
sql = "SELECT * FROM #{compare_table} WHERE #{condition} #{'AND' unless conditions.blank?} #{compare_table}.#{key} NOT IN " +
|
147
154
|
"(SELECT #{key} FROM #{model.table_name} #{'WHERE' unless conditions2.blank?} #{condition2})"
|
@@ -163,26 +170,26 @@ module BulkUpdate
|
|
163
170
|
#
|
164
171
|
# Compare Table of args[:model] with its temporary table args[:compare_with] and return all updated records as a Hash of Hashes whose
|
165
172
|
# key is the ID of the changed record
|
166
|
-
def get_updated_records
|
167
|
-
model
|
168
|
-
compare_table
|
169
|
-
keys
|
170
|
-
exclude
|
171
|
-
exclude
|
172
|
-
exclude_virtual =
|
173
|
+
def get_updated_records(args = {})
|
174
|
+
model = args[:for] || self
|
175
|
+
compare_table = args[:compare_with]
|
176
|
+
keys = args[:on] || 'id'
|
177
|
+
exclude = args[:exclude_fields] || []
|
178
|
+
exclude |= default_exclude
|
179
|
+
exclude_virtual = args[:exclude_virtual].nil? ? false : args[:exclude_virtual]
|
173
180
|
|
174
181
|
# Generate conditions for query and sub-query
|
175
|
-
conditions
|
182
|
+
conditions = []
|
176
183
|
conditions2 = []
|
177
184
|
conditions << "NOT #{model.table_name}.virtual" if exclude_virtual
|
178
185
|
if keys.class == String || keys.class == Symbol
|
179
|
-
key
|
186
|
+
key = keys.to_s
|
180
187
|
conditions << "#{model.table_name}.#{key} = #{compare_table}.#{key}"
|
181
|
-
exclude
|
188
|
+
exclude |= [keys.to_s]
|
182
189
|
else
|
183
|
-
key
|
190
|
+
key = keys[0].to_s
|
184
191
|
conditions |= keys.map{|k| "#{model.table_name}.#{k.to_s} = #{compare_table}.#{k.to_s}" }
|
185
|
-
exclude
|
192
|
+
exclude |= keys.map(&:to_s)
|
186
193
|
end
|
187
194
|
conditions << "#{args[:condition].gsub('--tt--', model.table_name)} AND #{args[:condition].gsub('--tt--', compare_table)}" if args[:condition]
|
188
195
|
model.attribute_names.each do |an|
|
@@ -199,20 +206,20 @@ module BulkUpdate
|
|
199
206
|
end
|
200
207
|
|
201
208
|
# Generate and execute SQL-Statement
|
202
|
-
condition
|
203
|
-
condition
|
204
|
-
compare_columns =
|
205
|
-
sql
|
206
|
-
results
|
209
|
+
condition = conditions.join(' AND ')
|
210
|
+
condition += " AND (#{conditions2.join(' OR ')})" unless conditions2.blank?
|
211
|
+
compare_columns = attribute_names.select { |e| e != 'id' }.map { |e| "#{compare_table}.#{e}" }.join(', ')
|
212
|
+
sql = "SELECT #{model.table_name}.id, #{compare_columns} FROM #{model.table_name}, #{compare_table} WHERE #{condition}"
|
213
|
+
results = ActiveRecord::Base.connection.execute sql
|
207
214
|
|
208
215
|
# Generate Hash with id as the key and values as a Hashes of all changed records
|
209
216
|
results_hash = {}
|
210
|
-
keys_to_log
|
217
|
+
keys_to_log = []
|
211
218
|
results.each do |attributes|
|
212
|
-
attributes
|
213
|
-
id
|
214
|
-
results_hash[id] =
|
215
|
-
keys_to_log
|
219
|
+
attributes = attributes2array(attributes)
|
220
|
+
id = attributes[0]
|
221
|
+
results_hash[id] = result2hash attributes, exclude - %w(updated_at)
|
222
|
+
keys_to_log << (args[:debug] ? model.find(id).send(key) : id)
|
216
223
|
end
|
217
224
|
args[:logger].info "Change Records for Model #{model.to_s}: #{keys_to_log.join(', ')}" unless keys_to_log.blank? || args[:logger].blank?
|
218
225
|
|
@@ -222,18 +229,18 @@ module BulkUpdate
|
|
222
229
|
|
223
230
|
#
|
224
231
|
# Compare Table of args[:model] with its temporary table args[:compare_with] and return all deleted records as a Array of IDs
|
225
|
-
def get_deleted_records
|
226
|
-
model
|
227
|
-
compare_table
|
228
|
-
keys
|
232
|
+
def get_deleted_records(args = {})
|
233
|
+
model = args[:for] || self
|
234
|
+
compare_table = args[:compare_with]
|
235
|
+
keys = args[:on] || 'id'
|
229
236
|
exclude_virtual = args[:exclude_virtual].nil? ? false : args[:exclude_virtual]
|
230
237
|
|
231
238
|
# Generate conditions for query and sub-query
|
232
|
-
conditions
|
233
|
-
conditions2
|
234
|
-
conditions
|
235
|
-
conditions
|
236
|
-
conditions2
|
239
|
+
conditions = []
|
240
|
+
conditions2 = []
|
241
|
+
conditions << "NOT #{model.table_name}.virtual" if exclude_virtual
|
242
|
+
conditions << "#{args[:condition].gsub('--tt--', model.table_name)}" if args[:condition]
|
243
|
+
conditions2 << "#{args[:condition].gsub('--tt--', compare_table)}" if args[:condition]
|
237
244
|
if keys.class == String || keys.class == Symbol
|
238
245
|
key = keys.to_s
|
239
246
|
else
|
@@ -242,19 +249,19 @@ module BulkUpdate
|
|
242
249
|
end
|
243
250
|
|
244
251
|
# Generate and execute SQL-Statement
|
245
|
-
condition
|
252
|
+
condition = conditions.join(' AND ')
|
246
253
|
condition2 = conditions2.join(' AND ')
|
247
|
-
sql
|
248
|
-
|
249
|
-
results
|
254
|
+
sql = "SELECT id, #{key} FROM #{model.table_name} WHERE #{condition} #{'AND' unless conditions.blank?} #{model.table_name}.#{key} NOT IN " +
|
255
|
+
"(SELECT #{key} FROM #{compare_table} #{'WHERE' unless conditions2.blank?} #{condition2})"
|
256
|
+
results = ActiveRecord::Base.connection.execute sql
|
250
257
|
|
251
258
|
# Generate Array with ids of all deleted records
|
252
259
|
deleted_records = []
|
253
|
-
keys_to_log
|
260
|
+
keys_to_log = []
|
254
261
|
results.each do |attributes|
|
255
|
-
attributes
|
262
|
+
attributes = attributes2array(attributes)
|
256
263
|
deleted_records << attributes[0]
|
257
|
-
keys_to_log
|
264
|
+
keys_to_log << attributes[1]
|
258
265
|
end
|
259
266
|
args[:logger].info "Deleting Records from Model #{model.to_s}: #{keys_to_log.join(', ')}" unless keys_to_log.blank? || args[:logger].blank?
|
260
267
|
deleted_records
|
@@ -267,8 +274,8 @@ module BulkUpdate
|
|
267
274
|
def result2hash(attributes, exclude, attribute_nr = 0)
|
268
275
|
hash = {}
|
269
276
|
attribute_names.each do |an|
|
270
|
-
hash[an.to_sym] =
|
271
|
-
attribute_nr
|
277
|
+
hash[an.to_sym] = attributes[attribute_nr] unless exclude.include?(an)
|
278
|
+
attribute_nr += 1
|
272
279
|
end
|
273
280
|
hash
|
274
281
|
end
|
data/lib/bulk_update/version.rb
CHANGED
data/spec/bulk_update_spec.rb
CHANGED
@@ -7,6 +7,7 @@ describe BulkUpdate do
|
|
7
7
|
@columns = [:name, :value]
|
8
8
|
@values = [['test1', 'value1'], ['test2', 'value2'], ['test3', 'value3'], ['test4', 'value4']]
|
9
9
|
MyHash.bulk_insert @columns, @values
|
10
|
+
@ts = MyHash.first.created_at
|
10
11
|
end
|
11
12
|
|
12
13
|
|
@@ -20,10 +21,43 @@ describe BulkUpdate do
|
|
20
21
|
MyHash.bulk_update @columns, @values, key: 'name'
|
21
22
|
MyHash.count.should be 4
|
22
23
|
MyHash.where(name: 'test1').first.value.should eq 'value1.1'
|
24
|
+
MyHash.where(name: 'test1').first.created_at.to_i.should eq @ts.to_i
|
25
|
+
MyHash.where(name: 'test1').first.updated_at.to_i.should eq @ts.to_i
|
23
26
|
MyHash.where(name: 'test2').first.value.should eq 'value2'
|
27
|
+
MyHash.where(name: 'test2').first.created_at.to_i.should eq @ts.to_i
|
28
|
+
MyHash.where(name: 'test2').first.updated_at.to_i.should eq @ts.to_i
|
24
29
|
MyHash.where(name: 'test3').first.should be nil
|
25
30
|
MyHash.where(name: 'test4').first.value.should eq 'value4.4'
|
31
|
+
MyHash.where(name: 'test4').first.created_at.to_i.should eq @ts.to_i
|
32
|
+
MyHash.where(name: 'test4').first.updated_at.to_i.should eq @ts.to_i
|
26
33
|
MyHash.where(name: 'test5').first.value.should eq 'value5.5'
|
34
|
+
MyHash.where(name: 'test5').first.created_at.to_i.should eq @ts.to_i
|
35
|
+
MyHash.where(name: 'test5').first.updated_at.to_i.should eq @ts.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
it 'should update the created_at and updated_at timestamps if specified' do
|
40
|
+
columns = [:name, :value, :updated_at, :created_at]
|
41
|
+
ts_1 = 1.hour.ago
|
42
|
+
ts_2 = 2.hour.ago
|
43
|
+
ts_1_s = ts_1.to_s(:db)
|
44
|
+
ts_2_s = ts_2.to_s(:db)
|
45
|
+
values = [['test1', 'value1.1', ts_1_s, ts_2_s], ['test2', 'value2', ts_1_s, ts_2_s], ['test4', 'value4.4', ts_1_s, ts_2_s], ['test5', 'value5.5', ts_1_s, ts_2_s]]
|
46
|
+
MyHash.bulk_update columns, values, key: 'name'
|
47
|
+
MyHash.count.should be 4
|
48
|
+
MyHash.where(name: 'test1').first.value.should eq 'value1.1'
|
49
|
+
MyHash.where(name: 'test1').first.created_at.to_i.should eq @ts.to_i
|
50
|
+
MyHash.where(name: 'test1').first.updated_at.to_i.should eq ts_1.to_i
|
51
|
+
MyHash.where(name: 'test2').first.value.should eq 'value2'
|
52
|
+
MyHash.where(name: 'test2').first.created_at.to_i.should eq @ts.to_i
|
53
|
+
MyHash.where(name: 'test2').first.updated_at.to_i.should eq @ts.to_i
|
54
|
+
MyHash.where(name: 'test3').first.should be nil
|
55
|
+
MyHash.where(name: 'test4').first.value.should eq 'value4.4'
|
56
|
+
MyHash.where(name: 'test4').first.created_at.to_i.should eq @ts.to_i
|
57
|
+
MyHash.where(name: 'test4').first.updated_at.to_i.should eq ts_1.to_i
|
58
|
+
MyHash.where(name: 'test5').first.value.should eq 'value5.5'
|
59
|
+
MyHash.where(name: 'test5').first.created_at.to_i.should eq ts_2.to_i
|
60
|
+
MyHash.where(name: 'test5').first.updated_at.to_i.should eq ts_1.to_i
|
27
61
|
end
|
28
62
|
|
29
63
|
end
|
metadata
CHANGED
@@ -1,110 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bulk_update
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Philip Kurmann
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2015-01-26 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: activerecord
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rspec
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: sqlite3
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: pg
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - ">="
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - ">="
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: mysql2
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - ">="
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - ">="
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: pry
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - ">="
|
100
88
|
- !ruby/object:Gem::Version
|
101
89
|
version: '0'
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - ">="
|
108
95
|
- !ruby/object:Gem::Version
|
109
96
|
version: '0'
|
110
97
|
description: Updates a large amount of Records in a highly efficient way
|
@@ -114,7 +101,7 @@ executables: []
|
|
114
101
|
extensions: []
|
115
102
|
extra_rdoc_files: []
|
116
103
|
files:
|
117
|
-
- .gitignore
|
104
|
+
- ".gitignore"
|
118
105
|
- Gemfile
|
119
106
|
- LICENSE
|
120
107
|
- README.md
|
@@ -130,27 +117,26 @@ files:
|
|
130
117
|
- spec/support/schema.rb
|
131
118
|
homepage: ''
|
132
119
|
licenses: []
|
120
|
+
metadata: {}
|
133
121
|
post_install_message:
|
134
122
|
rdoc_options: []
|
135
123
|
require_paths:
|
136
124
|
- lib
|
137
125
|
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
-
none: false
|
139
126
|
requirements:
|
140
|
-
- -
|
127
|
+
- - ">="
|
141
128
|
- !ruby/object:Gem::Version
|
142
129
|
version: '0'
|
143
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
-
none: false
|
145
131
|
requirements:
|
146
|
-
- -
|
132
|
+
- - ">="
|
147
133
|
- !ruby/object:Gem::Version
|
148
134
|
version: '0'
|
149
135
|
requirements: []
|
150
136
|
rubyforge_project:
|
151
|
-
rubygems_version:
|
137
|
+
rubygems_version: 2.2.2
|
152
138
|
signing_key:
|
153
|
-
specification_version:
|
139
|
+
specification_version: 4
|
154
140
|
summary: Enhances Active Record with a method for bulk inserts and a method for bulk
|
155
141
|
updates. Both merthods are used for inserting or updating large amount of Records.
|
156
142
|
test_files:
|