bulk_data_methods 1.0.0 → 1.1.0

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.
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ bundler_args: --without debug
3
+ rvm:
4
+ - 1.9.3
5
+ before_script:
6
+ - cp spec/dummy/config/database-sample.yml spec/dummy/config/database.yml; createdb bulk_data_methods_test
7
+ script: bundle exec rake spec
data/Gemfile CHANGED
@@ -1,4 +1,10 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ # NOTE(ahannon) Travis CI kindly requests that the debugger be split
4
+ # out so that it does not install linecache during "bundle install":
5
+ group :debug do
6
+ gem 'debugger'
7
+ end
8
+
3
9
  # Specify your gem's dependencies in bulk_data_methods.gemspec
4
10
  gemspec
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2012, Fiksu, Inc.
1
+ Copyright (c) 2010-2013, Fiksu, Inc.
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ bulk_data_methods
2
+ ==================
3
+ MixIn used to extend ActiveRecord::Base classes implementing bulk insert and update operations
4
+ through {#create_many} and {#update_many}.
5
+
6
+ Examples
7
+ ========
8
+
9
+ ```ruby
10
+ class Company < ActiveRecord::Base
11
+ extend BulkMethodsMixin
12
+ end
13
+ ```
14
+ __________________________
15
+ BULK creation of many rows:
16
+
17
+ example no options used
18
+
19
+ ```ruby
20
+ rows = [
21
+ { :name => 'Keith', :salary => 1000 },
22
+ { :name => 'Alex', :salary => 2000 }
23
+ ]
24
+ Employee.create_many(rows)
25
+ ```
26
+
27
+ example with :returning option to returns key value
28
+
29
+ ```ruby
30
+ rows = [
31
+ { :name => 'Keith', :salary => 1000 },
32
+ { :name => 'Alex', :salary => 2000 }
33
+ ]
34
+ options = { :returning => [:id] }
35
+ Employee.create_many(rows, options)
36
+ ```
37
+
38
+ example with :slice_size option (will generate two insert queries)
39
+
40
+ ```ruby
41
+ rows = [
42
+ { :name => 'Keith', :salary => 1000 },
43
+ { :name => 'Alex', :salary => 2000 },
44
+ { :name => 'Mark', :salary => 3000 }
45
+ ]
46
+ options = { :slice_size => 2 }
47
+ Employee.create_many(rows, options)
48
+ ```
49
+
50
+ _________________________
51
+ BULK updates of many rows:
52
+
53
+ example using "set_array" to add the value of "salary" to the specific
54
+ employee's salary the default where clause matches IDs so, it works
55
+ here.
56
+
57
+ ```ruby
58
+ rows = [
59
+ { :id => 1, :salary => 1000 },
60
+ { :id => 10, :salary => 2000 },
61
+ { :id => 23, :salary => 2500 }
62
+ ]
63
+ options = { :set_array => '"salary = datatable.salary"' }
64
+ Employee.update_many(rows, options)
65
+ ```
66
+
67
+ example using where clause to only update salaries that haven't already been updated (forced exampled).
68
+
69
+ ```ruby
70
+ rows = [
71
+ { :id => 1, :salary => 1000, :company_id => 10 },
72
+ { :id => 10, :salary => 2000, :company_id => 12 },
73
+ { :id => 23, :salary => 2500, :company_id => 5 }
74
+ ]
75
+ options = {
76
+ :set_array => '"salary = datatable.salary"',
77
+ :where_datatable => '"#{table_name}.salary <> datatable.salary"'
78
+ }
79
+ Employee.update_many(rows, options)
80
+ ```
81
+
82
+ example setting where clause to the KEY of the hash passed in and the set_array is generated from the VALUES
83
+
84
+ ```ruby
85
+ rows = {
86
+ { :id => 1 } => { :salary => 100000, :company_id => 10 },
87
+ { :id => 10 } => { :salary => 110000, :company_id => 12 },
88
+ { :id => 23 } => { :salary => 90000, :company_id => 5 }
89
+ }
90
+ Employee.update_many(rows)
91
+ ```
data/Rakefile CHANGED
@@ -1 +1,10 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec) do |spec|
6
+ spec.pattern = FileList['spec/**/*_spec.rb']
7
+ spec.ruby_opts="-w"
8
+ end
9
+
10
+ task :default => :spec
@@ -5,7 +5,7 @@ Gem::Specification.new do |s|
5
5
  s.name = "bulk_data_methods"
6
6
  s.version = BulkDataMethods::VERSION
7
7
  s.license = 'New BSD License'
8
- s.date = '2012-09-21'
8
+ s.date = '2013-05-30'
9
9
  s.summary = 'MixIn used to extend ActiveRecord::Base classes implementing bulk insert and update operations through {#create_many} and {#update_many}.'
10
10
  s.description = 'MixIn used to extend ActiveRecord::Base classes implementing bulk insert and update operations through {#create_many} and {#update_many}.'
11
11
  s.authors = ["Keith Gabryelski"]
@@ -17,4 +17,4 @@ Gem::Specification.new do |s|
17
17
  s.add_dependency "pg"
18
18
  s.add_dependency "rails", '>= 3.0.0'
19
19
  s.add_dependency 'rspec-rails'
20
- end
20
+ end
@@ -113,12 +113,14 @@ module BulkMethodsMixin
113
113
  # @overload update_many(rows = [], options = {})
114
114
  # @param [Array<Hash>] rows ([]) data to be updated
115
115
  # @option options [String] :set_array (built from first row passed in) the set clause
116
- # @option options [String] :where ('"#{table_name}.id = datatable.id"') the where clause
116
+ # @option options [String] :where_datatable ('"#{table_name}.id = datatable.id"') the where clause specifying how to join the datatable against the real table
117
+ # @option options [String] :where_constraint the rest of the where clause that limits what rows of the table get updated
117
118
  #
118
119
  # @overload update_many(rows = {}, options = {})
119
120
  # @param [Hash<Hash, Hash>] rows ({}) data to be updated
120
121
  # @option options [String] :set_array (built from the values in the first key/value pair of `rows`) the set clause
121
- # @option options [String] :where (built from the keys in the first key/value pair of `rows`) the where clause
122
+ # @option options [String] :where_datatable ('"#{table_name}.id = datatable.id"') the where clause specifying how to join the datatable against the real table
123
+ # @option options [String] :where_constraint the rest of the where clause that limits what rows of the table get updated
122
124
  #
123
125
  # @example using "set_array" to add the value of "salary" to the specific employee's salary the default where clause matches IDs so, it works here.
124
126
  # rows = [
@@ -129,15 +131,27 @@ module BulkMethodsMixin
129
131
  # options = { :set_array => '"salary = datatable.salary"' }
130
132
  # Employee.update_many(rows, options)
131
133
  #
132
- # @example using where clause to match salary.
134
+ # @example using where_datatable clause to match salary.
133
135
  # rows = [
134
136
  # { :id => 1, :salary => 1000, :company_id => 10 },
135
137
  # { :id => 10, :salary => 2000, :company_id => 12 },
136
138
  # { :id => 23, :salary => 2500, :company_id => 5 }
137
139
  # ]
138
140
  # options = {
139
- # :set_array => '"company_id = datatable.company_id"',
140
- # :where => '"#{table_name}.salary = datatable.salary"'
141
+ # :set_array => '"salary = datatable.salary"',
142
+ # :where_constraint => '"#{table_name}.salary <> datatable.salary"'
143
+ # }
144
+ # Employee.update_many(rows, options)
145
+ #
146
+ # @example using where_constraint clause to only update salary for active employees
147
+ # rows = [
148
+ # { :id => 1, :salary => 1000, :company_id => 10 },
149
+ # { :id => 10, :salary => 2000, :company_id => 12 },
150
+ # { :id => 23, :salary => 2500, :company_id => 5 }
151
+ # ]
152
+ # options = {
153
+ # :set_array => '"salary = datatable.salary"',
154
+ # :where_constraint => '"#{table_name}.active = true"'
141
155
  # }
142
156
  # Employee.update_many(rows, options)
143
157
  #
@@ -155,7 +169,7 @@ module BulkMethodsMixin
155
169
  def update_many(rows, options = {})
156
170
  return [] if rows.blank?
157
171
  if rows.is_a?(Hash)
158
- options[:where] = '"' + rows.keys[0].keys.map{|key| '#{table_name}.' + "#{key} = datatable.#{key}"}.join(' and ') + '"'
172
+ options[:where_datatable] = '"' + rows.keys[0].keys.map{|key| '#{table_name}.' + "#{key} = datatable.#{key}"}.join(' and ') + '"'
159
173
  options[:set_array] = '"' + rows.values[0].keys.map{|key| "#{key} = datatable.#{key}"}.join(',') + '"' unless options[:set_array]
160
174
  r = []
161
175
  rows.each do |key,value|
@@ -166,8 +180,8 @@ module BulkMethodsMixin
166
180
  unless options[:set_array]
167
181
  column_names = rows[0].keys
168
182
  columns_to_remove = [:id]
169
- columns_to_remove += [partition_keys].map{|k| k.to_sym} if respond_to?(:partition_keys)
170
- options[:set_array] = '"' + (column_names - columns_to_remove.flatten).map{|cn| "#{cn} = datatable.#{cn}"}.join(',') + '"'
183
+ columns_to_remove += partition_keys.flatten.map{|k| k.to_sym} if respond_to?(:partition_keys)
184
+ options[:set_array] = '"' + (column_names - columns_to_remove).map{|cn| "#{cn} = datatable.#{cn}"}.join(',') + '"'
171
185
  end
172
186
  options[:slice_size] = 1000 unless options[:slice_size]
173
187
  options[:check_consistency] = true unless options.has_key?(:check_consistency)
@@ -180,8 +194,11 @@ module BulkMethodsMixin
180
194
  end
181
195
  returning_clause = "\" returning #{returning_list}\""
182
196
  end
183
- options[:where] = '"#{table_name}.id = datatable.id"' unless options[:where]
184
-
197
+ where_clause = options[:where_datatable] || '"#{table_name}.id = datatable.id"'
198
+ where_constraint = ""
199
+ if options[:where_constraint]
200
+ where_constraint = " AND #{eval(options[:where_constraint])}"
201
+ end
185
202
  returning = []
186
203
 
187
204
  rows.group_by do |row|
@@ -217,7 +234,8 @@ module BulkMethodsMixin
217
234
  #{datatable}
218
235
  ) as datatable
219
236
  where
220
- #{eval(options[:where])}
237
+ #{eval(where_clause)}
238
+ #{where_constraint}
221
239
  #{eval(returning_clause)}
222
240
  SQL
223
241
  returning += find_by_sql(sql_update_string)
@@ -1,3 +1,3 @@
1
1
  module BulkDataMethods
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -346,15 +346,18 @@ describe "BulkMethodsMixin" do
346
346
  end
347
347
  end # when update method with options :set_array equal 'salary = datatable.salary'
348
348
 
349
- context "when update method with options :where" do
349
+ context "when update method with options :where_constraint" do
350
350
  it "updates only name column, where salary equal input values" do
351
351
  Employee.update_many([{ :id => 1, :name => 'Elvis', :salary => 12 },
352
- { :id => 2, :name => 'Freddi',:salary => 22}],
353
- { :where => '"#{table_name}.salary = datatable.salary"' })
352
+ { :id => 2, :name => 'Freddi',:salary => 22},
353
+ { :id => 3, :name => 'Robert', :salary => 13}],
354
+ { :where_constraint => '"#{table_name}.salary = datatable.salary AND datatable.salary < 13"' })
354
355
  Employee.find(1).name.should_not == "Elvis"
355
356
  Employee.find(1).salary.should == 3
356
357
  Employee.find(2).name.should_not == "Freddi"
357
358
  Employee.find(2).salary.should == 3
359
+ Employee.find(3).name.should_not == "Robert"
360
+ Employee.find(3).salary.should == 3
358
361
  end
359
362
  end # when update method with options :where
360
363
 
@@ -433,4 +436,4 @@ describe "BulkMethodsMixin" do
433
436
 
434
437
  end # update_many
435
438
 
436
- end # BulkMethodsMixin
439
+ end # BulkMethodsMixin
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bulk_data_methods
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-21 00:00:00.000000000 Z
12
+ date: 2013-05-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pg
@@ -68,10 +68,10 @@ extra_rdoc_files: []
68
68
  files:
69
69
  - .gitignore
70
70
  - .rspec
71
+ - .travis.yml
71
72
  - Gemfile
72
- - Gemfile.lock
73
73
  - LICENSE
74
- - README
74
+ - README.md
75
75
  - Rakefile
76
76
  - bulk_data_methods.gemspec
77
77
  - lib/bulk_data_methods.rb
@@ -132,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
132
  version: '0'
133
133
  requirements: []
134
134
  rubyforge_project:
135
- rubygems_version: 1.8.24
135
+ rubygems_version: 1.8.25
136
136
  signing_key:
137
137
  specification_version: 3
138
138
  summary: MixIn used to extend ActiveRecord::Base classes implementing bulk insert
data/Gemfile.lock DELETED
@@ -1,108 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- bulk_data_methods (1.0.0)
5
- pg
6
- rails (>= 3.0.0)
7
- rspec-rails
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- actionmailer (3.2.8)
13
- actionpack (= 3.2.8)
14
- mail (~> 2.4.4)
15
- actionpack (3.2.8)
16
- activemodel (= 3.2.8)
17
- activesupport (= 3.2.8)
18
- builder (~> 3.0.0)
19
- erubis (~> 2.7.0)
20
- journey (~> 1.0.4)
21
- rack (~> 1.4.0)
22
- rack-cache (~> 1.2)
23
- rack-test (~> 0.6.1)
24
- sprockets (~> 2.1.3)
25
- activemodel (3.2.8)
26
- activesupport (= 3.2.8)
27
- builder (~> 3.0.0)
28
- activerecord (3.2.8)
29
- activemodel (= 3.2.8)
30
- activesupport (= 3.2.8)
31
- arel (~> 3.0.2)
32
- tzinfo (~> 0.3.29)
33
- activeresource (3.2.8)
34
- activemodel (= 3.2.8)
35
- activesupport (= 3.2.8)
36
- activesupport (3.2.8)
37
- i18n (~> 0.6)
38
- multi_json (~> 1.0)
39
- arel (3.0.2)
40
- builder (3.0.3)
41
- diff-lcs (1.1.3)
42
- erubis (2.7.0)
43
- hike (1.2.1)
44
- i18n (0.6.1)
45
- journey (1.0.4)
46
- json (1.7.5)
47
- mail (2.4.4)
48
- i18n (>= 0.4.0)
49
- mime-types (~> 1.16)
50
- treetop (~> 1.4.8)
51
- mime-types (1.19)
52
- multi_json (1.3.6)
53
- pg (0.14.1)
54
- polyglot (0.3.3)
55
- rack (1.4.1)
56
- rack-cache (1.2)
57
- rack (>= 0.4)
58
- rack-ssl (1.3.2)
59
- rack
60
- rack-test (0.6.1)
61
- rack (>= 1.0)
62
- rails (3.2.8)
63
- actionmailer (= 3.2.8)
64
- actionpack (= 3.2.8)
65
- activerecord (= 3.2.8)
66
- activeresource (= 3.2.8)
67
- activesupport (= 3.2.8)
68
- bundler (~> 1.0)
69
- railties (= 3.2.8)
70
- railties (3.2.8)
71
- actionpack (= 3.2.8)
72
- activesupport (= 3.2.8)
73
- rack-ssl (~> 1.3.2)
74
- rake (>= 0.8.7)
75
- rdoc (~> 3.4)
76
- thor (>= 0.14.6, < 2.0)
77
- rake (0.9.2.2)
78
- rdoc (3.12)
79
- json (~> 1.4)
80
- rspec (2.11.0)
81
- rspec-core (~> 2.11.0)
82
- rspec-expectations (~> 2.11.0)
83
- rspec-mocks (~> 2.11.0)
84
- rspec-core (2.11.1)
85
- rspec-expectations (2.11.3)
86
- diff-lcs (~> 1.1.3)
87
- rspec-mocks (2.11.3)
88
- rspec-rails (2.11.0)
89
- actionpack (>= 3.0)
90
- activesupport (>= 3.0)
91
- railties (>= 3.0)
92
- rspec (~> 2.11.0)
93
- sprockets (2.1.3)
94
- hike (~> 1.2)
95
- rack (~> 1.0)
96
- tilt (~> 1.1, != 1.3.0)
97
- thor (0.16.0)
98
- tilt (1.3.3)
99
- treetop (1.4.10)
100
- polyglot
101
- polyglot (>= 0.3.1)
102
- tzinfo (0.3.33)
103
-
104
- PLATFORMS
105
- ruby
106
-
107
- DEPENDENCIES
108
- bulk_data_methods!
data/README DELETED
@@ -1,68 +0,0 @@
1
- bulk_data_methods
2
- ==================
3
- MixIn used to extend ActiveRecord::Base classes implementing bulk insert and update operations
4
- through {#create_many} and {#update_many}.
5
-
6
- Examples
7
- ========
8
-
9
- class Company < ActiveRecord::Base
10
- extend BulkMethodsMixin
11
- end
12
- __________________________
13
- BULK creation of many rows:
14
-
15
- example no options used
16
- rows = [
17
- { :name => 'Keith', :salary => 1000 },
18
- { :name => 'Alex', :salary => 2000 }
19
- ]
20
- Employee.create_many(rows)
21
-
22
- example with :returning option to returns key value
23
- rows = [
24
- { :name => 'Keith', :salary => 1000 },
25
- { :name => 'Alex', :salary => 2000 }
26
- ]
27
- options = { :returning => [:id] }
28
- Employee.create_many(rows, options)
29
-
30
- example with :slice_size option (will generate two insert queries)
31
- rows = [
32
- { :name => 'Keith', :salary => 1000 },
33
- { :name => 'Alex', :salary => 2000 },
34
- { :name => 'Mark', :salary => 3000 }
35
- ]
36
- options = { :slice_size => 2 }
37
- Employee.create_many(rows, options)
38
- _________________________
39
- BULK updates of many rows:
40
-
41
- example using "set_array" to add the value of "salary" to the specific employee's salary the default where clause matches IDs so, it works here.
42
- rows = [
43
- { :id => 1, :salary => 1000 },
44
- { :id => 10, :salary => 2000 },
45
- { :id => 23, :salary => 2500 }
46
- ]
47
- options = { :set_array => '"salary = datatable.salary"' }
48
- Employee.update_many(rows, options)
49
-
50
- example using where clause to match salary.
51
- rows = [
52
- { :id => 1, :salary => 1000, :company_id => 10 },
53
- { :id => 10, :salary => 2000, :company_id => 12 },
54
- { :id => 23, :salary => 2500, :company_id => 5 }
55
- ]
56
- options = {
57
- :set_array => '"company_id = datatable.company_id"',
58
- :where => '"#{table_name}.salary = datatable.salary"'
59
- }
60
- Employee.update_many(rows, options)
61
-
62
- example setting where clause to the KEY of the hash passed in and the set_array is generated from the VALUES
63
- rows = {
64
- { :id => 1 } => { :salary => 100000, :company_id => 10 },
65
- { :id => 10 } => { :salary => 110000, :company_id => 12 },
66
- { :id => 23 } => { :salary => 90000, :company_id => 5 }
67
- }
68
- Employee.update_many(rows)