Empact-activerecord-import 0.3.5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  activerecord-import is a library for bulk inserting data using ActiveRecord.
4
4
 
5
- For more information on activerecord-import please see its wiki: http://wiki.github.com/zdennis/activerecord-import/
5
+ For more information on activerecord-import please see its wiki: https://github.com/zdennis/activerecord-import/wiki
6
6
 
7
7
  # License
8
8
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.5
1
+ 0.4.0
@@ -2,15 +2,15 @@ class ActiveRecord::Base
2
2
  class << self
3
3
  def establish_connection_with_activerecord_import(*args)
4
4
  establish_connection_without_activerecord_import(*args)
5
- ActiveSupport.run_load_hooks(:active_record_connection_established, connection)
5
+ ActiveSupport.run_load_hooks(:active_record_connection_established, connection_pool)
6
6
  end
7
7
  alias_method_chain :establish_connection, :activerecord_import
8
8
  end
9
9
  end
10
10
 
11
- ActiveSupport.on_load(:active_record_connection_established) do |connection|
12
- if !ActiveRecord.const_defined?(:Import) || !ActiveRecord::Import.respond_to?(:load_from_connection)
11
+ ActiveSupport.on_load(:active_record_connection_established) do |connection_pool|
12
+ if !ActiveRecord.const_defined?(:Import) || !ActiveRecord::Import.respond_to?(:load_from_connection_pool)
13
13
  require File.join File.dirname(__FILE__), "activerecord-import/base"
14
14
  end
15
- ActiveRecord::Import.load_from_connection connection
15
+ ActiveRecord::Import.require_adapter connection_pool.spec.config[:adapter]
16
16
  end
@@ -2,5 +2,5 @@ require "active_record/connection_adapters/mysql2_adapter"
2
2
  require "activerecord-import/adapters/mysql_adapter"
3
3
 
4
4
  class ActiveRecord::ConnectionAdapters::Mysql2Adapter
5
- include ActiveRecord::Import::MysqlAdapter::InstanceMethods
6
- end
5
+ include ActiveRecord::Import::MysqlAdapter
6
+ end
@@ -2,5 +2,5 @@ require "active_record/connection_adapters/mysql_adapter"
2
2
  require "activerecord-import/adapters/mysql_adapter"
3
3
 
4
4
  class ActiveRecord::ConnectionAdapters::MysqlAdapter
5
- include ActiveRecord::Import::MysqlAdapter::InstanceMethods
6
- end
5
+ include ActiveRecord::Import::MysqlAdapter
6
+ end
@@ -2,6 +2,6 @@ require "active_record/connection_adapters/postgresql_adapter"
2
2
  require "activerecord-import/adapters/postgresql_adapter"
3
3
 
4
4
  class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
5
- include ActiveRecord::Import::PostgreSQLAdapter::InstanceMethods
5
+ include ActiveRecord::Import::PostgreSQLAdapter
6
6
  end
7
7
 
@@ -2,6 +2,6 @@ require "active_record/connection_adapters/sqlite3_adapter"
2
2
  require "activerecord-import/adapters/sqlite3_adapter"
3
3
 
4
4
  class ActiveRecord::ConnectionAdapters::Sqlite3Adapter
5
- include ActiveRecord::Import::Sqlite3Adapter::InstanceMethods
5
+ include ActiveRecord::Import::Sqlite3Adapter
6
6
  end
7
7
 
@@ -45,7 +45,7 @@ module ActiveRecord::Import::AbstractAdapter
45
45
  sql_size = QUERY_OVERHEAD + base_sql.size + post_sql.size
46
46
 
47
47
  # the number of bytes the requested insert statement values will take up
48
- values_in_bytes = values.sum {|value| value.size }
48
+ values_in_bytes = values.sum {|value| value.bytesize }
49
49
 
50
50
  # the number of bytes (commas) it will take to comma separate our values
51
51
  comma_separated_bytes = values.size-1
@@ -1,59 +1,53 @@
1
1
  module ActiveRecord::Import::MysqlAdapter
2
- module InstanceMethods
3
- def self.included(klass)
4
- klass.instance_eval do
5
- include ActiveRecord::Import::ImportSupport
6
- include ActiveRecord::Import::OnDuplicateKeyUpdateSupport
7
- end
8
- end
9
-
10
- # Returns the maximum number of bytes that the server will allow
11
- # in a single packet
12
- def max_allowed_packet # :nodoc:
13
- result = execute( "SHOW VARIABLES like 'max_allowed_packet';" )
14
- # original Mysql gem responds to #fetch_row while Mysql2 responds to #first
15
- val = result.respond_to?(:fetch_row) ? result.fetch_row[1] : result.first[1]
16
- val.to_i
17
- end
18
-
19
- # Returns a generated ON DUPLICATE KEY UPDATE statement given the passed
20
- # in +args+.
21
- def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc:
22
- sql = ' ON DUPLICATE KEY UPDATE '
23
- arg = args.first
24
- if arg.is_a?( Array )
25
- sql << sql_for_on_duplicate_key_update_as_array( table_name, arg )
26
- elsif arg.is_a?( Hash )
27
- sql << sql_for_on_duplicate_key_update_as_hash( table_name, arg )
28
- elsif arg.is_a?( String )
29
- sql << arg
30
- else
31
- raise ArgumentError.new( "Expected Array or Hash" )
32
- end
33
- sql
34
- end
2
+ include ActiveRecord::Import::ImportSupport
3
+ include ActiveRecord::Import::OnDuplicateKeyUpdateSupport
4
+
5
+ # Returns the maximum number of bytes that the server will allow
6
+ # in a single packet
7
+ def max_allowed_packet # :nodoc:
8
+ result = execute( "SHOW VARIABLES like 'max_allowed_packet';" )
9
+ # original Mysql gem responds to #fetch_row while Mysql2 responds to #first
10
+ val = result.respond_to?(:fetch_row) ? result.fetch_row[1] : result.first[1]
11
+ val.to_i
12
+ end
35
13
 
36
- def sql_for_on_duplicate_key_update_as_array( table_name, arr ) # :nodoc:
37
- results = arr.map do |column|
38
- qc = quote_column_name( column )
39
- "#{table_name}.#{qc}=VALUES(#{qc})"
40
- end
41
- results.join( ',' )
14
+ # Returns a generated ON DUPLICATE KEY UPDATE statement given the passed
15
+ # in +args+.
16
+ def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc:
17
+ sql = ' ON DUPLICATE KEY UPDATE '
18
+ arg = args.first
19
+ if arg.is_a?( Array )
20
+ sql << sql_for_on_duplicate_key_update_as_array( table_name, arg )
21
+ elsif arg.is_a?( Hash )
22
+ sql << sql_for_on_duplicate_key_update_as_hash( table_name, arg )
23
+ elsif arg.is_a?( String )
24
+ sql << arg
25
+ else
26
+ raise ArgumentError.new( "Expected Array or Hash" )
42
27
  end
43
-
44
- def sql_for_on_duplicate_key_update_as_hash( table_name, hsh ) # :nodoc:
45
- sql = ' ON DUPLICATE KEY UPDATE '
46
- results = hsh.map do |column1, column2|
47
- qc1 = quote_column_name( column1 )
48
- qc2 = quote_column_name( column2 )
49
- "#{table_name}.#{qc1}=VALUES( #{qc2} )"
50
- end
51
- results.join( ',')
28
+ sql
29
+ end
30
+
31
+ def sql_for_on_duplicate_key_update_as_array( table_name, arr ) # :nodoc:
32
+ results = arr.map do |column|
33
+ qc = quote_column_name( column )
34
+ "#{table_name}.#{qc}=VALUES(#{qc})"
52
35
  end
36
+ results.join( ',' )
37
+ end
53
38
 
54
- #return true if the statement is a duplicate key record error
55
- def duplicate_key_update_error?(exception)# :nodoc:
56
- exception.is_a?(ActiveRecord::StatementInvalid) && exception.to_s.include?('Duplicate entry')
39
+ def sql_for_on_duplicate_key_update_as_hash( table_name, hsh ) # :nodoc:
40
+ sql = ' ON DUPLICATE KEY UPDATE '
41
+ results = hsh.map do |column1, column2|
42
+ qc1 = quote_column_name( column1 )
43
+ qc2 = quote_column_name( column2 )
44
+ "#{table_name}.#{qc1}=VALUES( #{qc2} )"
57
45
  end
46
+ results.join( ',')
47
+ end
48
+
49
+ #return true if the statement is a duplicate key record error
50
+ def duplicate_key_update_error?(exception)# :nodoc:
51
+ exception.is_a?(ActiveRecord::StatementInvalid) && exception.to_s.include?('Duplicate entry')
58
52
  end
59
- end
53
+ end
@@ -1,13 +1,7 @@
1
1
  module ActiveRecord::Import::PostgreSQLAdapter
2
- module InstanceMethods
3
- def self.included(klass)
4
- klass.instance_eval do
5
- include ActiveRecord::Import::ImportSupport
6
- end
7
- end
2
+ include ActiveRecord::Import::ImportSupport
8
3
 
9
- def next_value_for_sequence(sequence_name)
10
- %{nextval('#{sequence_name}')}
11
- end
4
+ def next_value_for_sequence(sequence_name)
5
+ %{nextval('#{sequence_name}')}
12
6
  end
13
7
  end
@@ -1,7 +1,5 @@
1
1
  module ActiveRecord::Import::Sqlite3Adapter
2
- module InstanceMethods
3
- def next_value_for_sequence(sequence_name)
4
- %{nextval('#{sequence_name}')}
5
- end
2
+ def next_value_for_sequence(sequence_name)
3
+ %{nextval('#{sequence_name}')}
6
4
  end
7
5
  end
@@ -1,28 +1,24 @@
1
- require "pathname"
2
- require "active_record"
3
- require "active_record/version"
4
-
5
1
  module ActiveRecord::Import
6
- AdapterPath = File.join File.expand_path(File.dirname(__FILE__)), "/active_record/adapters"
2
+ AdapterPath = File.join File.expand_path(File.dirname(__FILE__)), "active_record/adapters"
7
3
 
8
- # Loads the import functionality for a specific database adapter
9
- def self.require_adapter(adapter)
10
- require File.join(AdapterPath,"/abstract_adapter")
11
- require File.join(AdapterPath,"/#{adapter}_adapter")
4
+ def self.base_adapter(adapter)
5
+ case adapter
6
+ when 'mysqlspatial' then 'mysql'
7
+ when 'spatialite' then 'sqlite3'
8
+ when 'postgis' then 'postgresql'
9
+ else adapter
10
+ end
12
11
  end
13
12
 
14
- # Loads the import functionality for the passed in ActiveRecord connection
15
- def self.load_from_connection(connection)
16
- import_adapter = "ActiveRecord::Import::#{connection.class.name.demodulize}::InstanceMethods"
17
- unless connection.class.ancestors.map(&:name).include?(import_adapter)
18
- config = connection.instance_variable_get :@config
19
- require_adapter config[:adapter]
20
- end
13
+ # Loads the import functionality for a specific database adapter
14
+ def self.require_adapter(adapter)
15
+ require File.join(AdapterPath, "abstract_adapter")
16
+ require File.join(AdapterPath, "#{base_adapter(adapter)}_adapter")
21
17
  end
22
18
  end
23
19
 
24
20
 
25
- this_dir = Pathname.new File.dirname(__FILE__)
26
- require this_dir.join("import").to_s
27
- require this_dir.join("active_record/adapters/abstract_adapter").to_s
28
- require this_dir.join("synchronize").to_s
21
+ this_dir = File.dirname(__FILE__)
22
+ require File.join(this_dir, "import")
23
+ require File.join(this_dir, "active_record/adapters/abstract_adapter")
24
+ require File.join(this_dir, "synchronize")
@@ -1,17 +1,28 @@
1
- require "ostruct"
2
-
3
1
  module ActiveRecord::Import::ConnectionAdapters ; end
4
2
 
5
3
  module ActiveRecord::Import #:nodoc:
6
4
  class Result < Struct.new(:failed_instances, :num_inserts)
7
5
  end
8
6
 
7
+ # use tz as set in ActiveRecord::Base
8
+ tproc = lambda do
9
+ ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now
10
+ end
11
+
12
+ TIME_COLUMNS = {
13
+ :create => { "created_on" => tproc ,
14
+ "created_at" => tproc },
15
+ :update => { "updated_on" => tproc ,
16
+ "updated_at" => tproc }
17
+ }
18
+ TIME_COLUMN_NAMES = TIME_COLUMNS[:create].keys + TIME_COLUMNS[:update].keys
19
+
9
20
  module ImportSupport #:nodoc:
10
21
  def supports_import? #:nodoc:
11
22
  true
12
23
  end
13
24
  end
14
-
25
+
15
26
  module OnDuplicateKeyUpdateSupport #:nodoc:
16
27
  def supports_on_duplicate_key_update? #:nodoc:
17
28
  true
@@ -21,44 +32,28 @@ end
21
32
 
22
33
  class ActiveRecord::Base
23
34
  class << self
24
-
25
- # use tz as set in ActiveRecord::Base
26
- tproc = lambda do
27
- ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now
28
- end
29
-
30
- AREXT_RAILS_COLUMNS = {
31
- :create => { "created_on" => tproc ,
32
- "created_at" => tproc },
33
- :update => { "updated_on" => tproc ,
34
- "updated_at" => tproc }
35
- }
36
- AREXT_RAILS_COLUMN_NAMES = AREXT_RAILS_COLUMNS[:create].keys + AREXT_RAILS_COLUMNS[:update].keys
37
-
38
35
  # Returns true if the current database connection adapter
39
36
  # supports import functionality, otherwise returns false.
40
37
  def supports_import?
41
- connection.supports_import?
42
- rescue NoMethodError
43
- false
38
+ connection.respond_to?(:supports_import?) \
39
+ && connection.supports_import?
44
40
  end
45
41
 
46
42
  # Returns true if the current database connection adapter
47
43
  # supports on duplicate key update functionality, otherwise
48
44
  # returns false.
49
45
  def supports_on_duplicate_key_update?
50
- connection.supports_on_duplicate_key_update?
51
- rescue NoMethodError
52
- false
46
+ connection.respond_to?(:supports_on_duplicate_key_update?) \
47
+ && connection.supports_on_duplicate_key_update?
53
48
  end
54
-
55
- # Imports a collection of values to the database.
49
+
50
+ # Imports a collection of values to the database.
56
51
  #
57
52
  # This is more efficient than using ActiveRecord::Base#create or
58
53
  # ActiveRecord::Base#save multiple times. This method works well if
59
54
  # you want to create more than one record at a time and do not care
60
55
  # about having ActiveRecord objects returned for each record
61
- # inserted.
56
+ # inserted.
62
57
  #
63
58
  # This can be used with or without validations. It does not utilize
64
59
  # the ActiveRecord::Callbacks during creation/modification while
@@ -68,9 +63,9 @@ class ActiveRecord::Base
68
63
  # Model.import array_of_models
69
64
  # Model.import column_names, array_of_values
70
65
  # Model.import column_names, array_of_values, options
71
- #
66
+ #
72
67
  # ==== Model.import array_of_models
73
- #
68
+ #
74
69
  # With this form you can call _import_ passing in an array of model
75
70
  # objects that you want updated.
76
71
  #
@@ -102,9 +97,9 @@ class ActiveRecord::Base
102
97
  # * +timestamps+ - true|false, tells import to not add timestamps \
103
98
  # (if false) even if record timestamps is disabled in ActiveRecord::Base
104
99
  #
105
- # == Examples
100
+ # == Examples
106
101
  # class BlogPost < ActiveRecord::Base ; end
107
- #
102
+ #
108
103
  # # Example using array of model objects
109
104
  # posts = [ BlogPost.new :author_name=>'Zach Dennis', :title=>'AREXT',
110
105
  # BlogPost.new :author_name=>'Zach Dennis', :title=>'AREXT2',
@@ -114,7 +109,7 @@ class ActiveRecord::Base
114
109
  # # Example using column_names and array_of_values
115
110
  # columns = [ :author_name, :title ]
116
111
  # values = [ [ 'zdennis', 'test post' ], [ 'jdoe', 'another test post' ] ]
117
- # BlogPost.import columns, values
112
+ # BlogPost.import columns, values
118
113
  #
119
114
  # # Example using column_names, array_of_value and options
120
115
  # columns = [ :author_name, :title ]
@@ -136,8 +131,8 @@ class ActiveRecord::Base
136
131
  #
137
132
  # == On Duplicate Key Update (MySQL only)
138
133
  #
139
- # The :on_duplicate_key_update option can be either an Array or a Hash.
140
- #
134
+ # The :on_duplicate_key_update option can be either an Array or a Hash.
135
+ #
141
136
  # ==== Using an Array
142
137
  #
143
138
  # The :on_duplicate_key_update option can be an array of column
@@ -152,9 +147,9 @@ class ActiveRecord::Base
152
147
  # to model attribute name mappings. This gives you finer grained
153
148
  # control over what fields are updated with what attributes on your
154
149
  # model. Below is an example:
155
- #
156
- # BlogPost.import columns, attributes, :on_duplicate_key_update=>{ :title => :title }
157
- #
150
+ #
151
+ # BlogPost.import columns, attributes, :on_duplicate_key_update=>{ :title => :title }
152
+ #
158
153
  # = Returns
159
154
  # This returns an object which responds to +failed_instances+ and +num_inserts+.
160
155
  # * failed_instances - an array of objects that fails validation and were not committed to the database. An empty array if no validation is performed.
@@ -167,14 +162,9 @@ class ActiveRecord::Base
167
162
 
168
163
  # assume array of model objects
169
164
  if args.last.is_a?( Array ) and args.last.first.is_a? ActiveRecord::Base
170
- if args.length == 2
171
- models = args.last
172
- column_names = args.first
173
- else
174
- models = args.first
175
- column_names = self.column_names.dup
176
- end
177
-
165
+ models = args.pop
166
+ column_names = args.first || self.column_names.dup
167
+
178
168
  array_of_attributes = models.map do |model|
179
169
  # this next line breaks sqlite.so with a segmentation fault
180
170
  # if model.new_record? || options[:on_duplicate_key_update]
@@ -221,26 +211,27 @@ class ActiveRecord::Base
221
211
  synchronize( options[:synchronize], sync_keys)
222
212
  end
223
213
 
224
- return_obj.num_inserts = 0 if return_obj.num_inserts.nil?
214
+ return_obj.num_inserts ||= 0
225
215
  return_obj
226
216
  end
227
-
228
- # TODO import_from_table needs to be implemented.
217
+
218
+ # TODO import_from_table needs to be implemented.
229
219
  def import_from_table( options ) # :nodoc:
220
+ raise NotImplementedError, 'import_from_table needs to be implemented'
230
221
  end
231
-
222
+
232
223
  # Imports the passed in +column_names+ and +array_of_attributes+
233
224
  # given the passed in +options+ Hash with validations. Returns an
234
- # object with the methods +failed_instances+ and +num_inserts+.
235
- # +failed_instances+ is an array of instances that failed validations.
225
+ # object with the methods +failed_instances+ and +num_inserts+.
226
+ # +failed_instances+ is an array of instances that failed validations.
236
227
  # +num_inserts+ is the number of inserts it took to import the data. See
237
228
  # ActiveRecord::Base.import for more information on
238
229
  # +column_names+, +array_of_attributes+ and +options+.
239
230
  def import_with_validations( column_names, array_of_attributes, options={} )
240
231
  failed_instances = []
241
-
232
+
242
233
  # create instances for each of our column/value sets
243
- arr = validations_array_for_column_names_and_attributes( column_names, array_of_attributes )
234
+ arr = validations_array_for_column_names_and_attributes( column_names, array_of_attributes )
244
235
 
245
236
  # keep track of the instance and the position it is currently at. if this fails
246
237
  # validation we'll use the index to remove it from the array_of_attributes
@@ -251,14 +242,14 @@ class ActiveRecord::Base
251
242
  if not instance.valid?
252
243
  array_of_attributes[ i ] = nil
253
244
  failed_instances << instance
254
- end
245
+ end
255
246
  end
256
247
  array_of_attributes.compact!
257
-
248
+
258
249
  num_inserts = array_of_attributes.empty? ? 0 : import_without_validations_or_callbacks( column_names, array_of_attributes, options )
259
250
  ActiveRecord::Import::Result.new(failed_instances, num_inserts)
260
251
  end
261
-
252
+
262
253
  # Imports the passed in +column_names+ and +array_of_attributes+
263
254
  # given the passed in +options+ Hash. This will return the number
264
255
  # of insert operations it took to create these records without
@@ -280,11 +271,13 @@ class ActiveRecord::Base
280
271
  else
281
272
  # generate the sql
282
273
  post_sql_statements = connection.post_sql_statements( quoted_table_name, options )
283
-
274
+
284
275
  # perform the inserts
285
- number_inserted = connection.insert_many( [ insert_sql, post_sql_statements ].flatten,
286
- values_sql,
287
- "#{self.class.name} Create Many Without Validations Or Callbacks" )
276
+ number_inserted = connection.insert_many(
277
+ [ insert_sql, post_sql_statements ].flatten,
278
+ values_sql,
279
+ "#{self.class.name} Create Many Without Validations Or Callbacks"
280
+ )
288
281
  end
289
282
  number_inserted
290
283
  end
@@ -294,13 +287,17 @@ class ActiveRecord::Base
294
287
  # Returns SQL the VALUES for an INSERT statement given the passed in +columns+
295
288
  # and +array_of_attributes+.
296
289
  def values_sql_for_columns_and_attributes(columns, array_of_attributes) # :nodoc:
290
+ # connection gets called a *lot* in this high intensity loop.
291
+ # Reuse the same one w/in the loop, otherwise it would keep being re-retreived (= lots of time for large imports)
292
+ connection_memo = connection
297
293
  array_of_attributes.map do |arr|
298
294
  my_values = arr.each_with_index.map do |val,j|
299
295
  column = columns[j]
300
- if !sequence_name.blank? && column.name == primary_key && val.nil?
301
- connection.next_value_for_sequence(sequence_name)
296
+ # be sure to query sequence_name *last*, only if cheaper tests fail, because it's costly
297
+ if val.nil? && column.name == primary_key && !sequence_name.blank?
298
+ connection_memo.next_value_for_sequence(sequence_name)
302
299
  else
303
- connection.quote(column.type_cast(val), column)
300
+ connection_memo.quote(val, column) # no need for column.type_cast(val) - quote already does type casting
304
301
  end
305
302
  end
306
303
  "(#{my_values.join(',')})"
@@ -308,7 +305,7 @@ class ActiveRecord::Base
308
305
  end
309
306
 
310
307
  def add_special_rails_stamps( column_names, array_of_attributes, options )
311
- AREXT_RAILS_COLUMNS[:create].each_pair do |key, blk|
308
+ ActiveRecord::Import::TIME_COLUMNS[:create].each_pair do |key, blk|
312
309
  if self.column_names.include?(key)
313
310
  value = blk.call
314
311
  if index=column_names.index(key)
@@ -321,7 +318,7 @@ class ActiveRecord::Base
321
318
  end
322
319
  end
323
320
 
324
- AREXT_RAILS_COLUMNS[:update].each_pair do |key, blk|
321
+ ActiveRecord::Import::TIME_COLUMNS[:update].each_pair do |key, blk|
325
322
  if self.column_names.include?(key)
326
323
  value = blk.call
327
324
  if index=column_names.index(key)
@@ -331,11 +328,13 @@ class ActiveRecord::Base
331
328
  column_names << key
332
329
  array_of_attributes.each { |arr| arr << value }
333
330
  end
334
-
331
+
335
332
  if supports_on_duplicate_key_update?
336
- if options[:on_duplicate_key_update]
337
- options[:on_duplicate_key_update] << key.to_sym if options[:on_duplicate_key_update].is_a?(Array)
338
- options[:on_duplicate_key_update][key.to_sym] = key.to_sym if options[:on_duplicate_key_update].is_a?(Hash)
333
+ case options[:on_duplicate_key_update]
334
+ when Array
335
+ options[:on_duplicate_key_update] << key.to_sym
336
+ when Hash
337
+ options[:on_duplicate_key_update][key.to_sym] = key.to_sym
339
338
  else
340
339
  options[:on_duplicate_key_update] = [ key.to_sym ]
341
340
  end
@@ -343,13 +342,13 @@ class ActiveRecord::Base
343
342
  end
344
343
  end
345
344
  end
346
-
345
+
347
346
  # Returns an Array of Hashes for the passed in +column_names+ and +array_of_attributes+.
348
347
  def validations_array_for_column_names_and_attributes( column_names, array_of_attributes ) # :nodoc:
349
348
  array_of_attributes.map do |attributes|
350
349
  Hash[attributes.each_with_index.map {|attr, c| [column_names[c], attr] }]
351
350
  end
352
351
  end
353
-
352
+
354
353
  end
355
354
  end
@@ -1,10 +1,10 @@
1
1
  module ActiveRecord # :nodoc:
2
2
  class Base # :nodoc:
3
-
3
+
4
4
  # Synchronizes the passed in ActiveRecord instances with data
5
5
  # from the database. This is like calling reload on an individual
6
- # ActiveRecord instance but it is intended for use on multiple instances.
7
- #
6
+ # ActiveRecord instance but it is intended for use on multiple instances.
7
+ #
8
8
  # This uses one query for all instance updates and then updates existing
9
9
  # instances rather sending one query for each instance
10
10
  #
@@ -14,7 +14,7 @@ module ActiveRecord # :nodoc:
14
14
  # <.. out of system changes occur to change author name from Zach to Zachary..>
15
15
  # Post.synchronize posts
16
16
  # posts.first.author # => "Zachary" instead of Zach
17
- #
17
+ #
18
18
  # # Synchronizing using custom key fields
19
19
  # posts = Post.find_by_author("Zach")
20
20
  # <.. out of system changes occur to change the address of author 'Zach' to 1245 Foo Ln ..>
@@ -26,11 +26,11 @@ module ActiveRecord # :nodoc:
26
26
 
27
27
  conditions = {}
28
28
  order = ""
29
-
29
+
30
30
  key_values = keys.map { |key| instances.map(&"#{key}".to_sym) }
31
31
  keys.zip(key_values).each { |key, values| conditions[key] = values }
32
32
  order = keys.map{ |key| "#{key} ASC" }.join(",")
33
-
33
+
34
34
  klass = instances.first.class
35
35
 
36
36
  fresh_instances = klass.find( :all, :conditions=>conditions, :order=>order )
@@ -38,7 +38,7 @@ module ActiveRecord # :nodoc:
38
38
  matched_instance = fresh_instances.detect do |fresh_instance|
39
39
  keys.all?{ |key| fresh_instance.send(key) == instance.send(key) }
40
40
  end
41
-
41
+
42
42
  if matched_instance
43
43
  instance.clear_aggregation_cache
44
44
  instance.clear_association_cache
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Empact-activerecord-import
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,22 +10,22 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-11-26 00:00:00.000000000Z
13
+ date: 2012-05-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
17
- requirement: &2151988300 !ruby/object:Gem::Requirement
17
+ requirement: &70265403670100 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
- - - ! '>='
20
+ - - ~>
21
21
  - !ruby/object:Gem::Version
22
- version: 3.0.0
22
+ version: '3.0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *2151988300
25
+ version_requirements: *70265403670100
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: rake
28
- requirement: &2151971820 !ruby/object:Gem::Requirement
28
+ requirement: &70265403669060 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *2151971820
36
+ version_requirements: *70265403669060
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: jeweler
39
- requirement: &2151967900 !ruby/object:Gem::Requirement
39
+ requirement: &70265403667660 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,18 +44,18 @@ dependencies:
44
44
  version: 1.4.0
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *2151967900
47
+ version_requirements: *70265403667660
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: activerecord
50
- requirement: &2151962680 !ruby/object:Gem::Requirement
50
+ requirement: &70265403666900 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
- - - ! '>='
53
+ - - ~>
54
54
  - !ruby/object:Gem::Version
55
- version: 3.0.0
55
+ version: '3.0'
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *2151962680
58
+ version_requirements: *70265403666900
59
59
  description: Extraction of the ActiveRecord::Base#import functionality from ar-extensions
60
60
  for Rails 3 and beyond
61
61
  email: ben.woosley@gmail.com
@@ -95,7 +95,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
95
95
  version: '0'
96
96
  segments:
97
97
  - 0
98
- hash: -2232322125532575640
98
+ hash: 328182919252473110
99
99
  required_rubygems_version: !ruby/object:Gem::Requirement
100
100
  none: false
101
101
  requirements:
@@ -104,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
104
  version: '0'
105
105
  requirements: []
106
106
  rubyforge_project:
107
- rubygems_version: 1.8.8
107
+ rubygems_version: 1.8.11
108
108
  signing_key:
109
109
  specification_version: 3
110
110
  summary: Bulk-loading extension for ActiveRecord