bulk_data_methods 1.0.0 → 1.1.0

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