activerecord 2.3.3 → 2.3.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (70) hide show
  1. data/CHANGELOG +8 -1
  2. data/Rakefile +32 -15
  3. data/examples/performance.rb +162 -0
  4. data/lib/active_record/associations.rb +37 -5
  5. data/lib/active_record/associations/association_collection.rb +1 -0
  6. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +16 -0
  7. data/lib/active_record/associations/has_many_association.rb +1 -0
  8. data/lib/active_record/associations/has_many_through_association.rb +13 -3
  9. data/lib/active_record/associations/has_one_through_association.rb +8 -2
  10. data/lib/active_record/autosave_association.rb +4 -3
  11. data/lib/active_record/base.rb +18 -10
  12. data/lib/active_record/calculations.rb +2 -0
  13. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +16 -2
  14. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +2 -2
  15. data/lib/active_record/connection_adapters/abstract_adapter.rb +7 -0
  16. data/lib/active_record/connection_adapters/mysql_adapter.rb +17 -8
  17. data/lib/active_record/connection_adapters/postgresql_adapter.rb +32 -13
  18. data/lib/active_record/connection_adapters/sqlite_adapter.rb +12 -0
  19. data/lib/active_record/dirty.rb +1 -1
  20. data/lib/active_record/fixtures.rb +9 -7
  21. data/lib/active_record/i18n_interpolation_deprecation.rb +1 -1
  22. data/lib/active_record/locale/en.yml +4 -0
  23. data/lib/active_record/named_scope.rb +1 -6
  24. data/lib/active_record/reflection.rb +1 -1
  25. data/lib/active_record/schema_dumper.rb +1 -2
  26. data/lib/active_record/serializers/json_serializer.rb +5 -3
  27. data/lib/active_record/serializers/xml_serializer.rb +6 -2
  28. data/lib/active_record/validations.rb +148 -79
  29. data/lib/active_record/version.rb +1 -1
  30. data/test/cases/adapter_test.rb +12 -0
  31. data/test/cases/associations/belongs_to_associations_test.rb +0 -18
  32. data/test/cases/associations/eager_load_nested_include_test.rb +5 -5
  33. data/test/cases/associations/habtm_join_table_test.rb +56 -0
  34. data/test/cases/associations/has_many_associations_test.rb +56 -2
  35. data/test/cases/associations/has_many_through_associations_test.rb +46 -1
  36. data/test/cases/associations/has_one_through_associations_test.rb +10 -0
  37. data/test/cases/associations/join_model_test.rb +4 -4
  38. data/test/cases/base_test.rb +49 -4
  39. data/test/cases/calculations_test.rb +6 -0
  40. data/test/cases/column_definition_test.rb +34 -0
  41. data/test/cases/dirty_test.rb +10 -0
  42. data/test/cases/finder_test.rb +15 -50
  43. data/test/cases/fixtures_test.rb +1 -1
  44. data/test/cases/i18n_test.rb +5 -0
  45. data/test/cases/method_scoping_test.rb +1 -1
  46. data/test/cases/migration_test.rb +39 -11
  47. data/test/cases/modules_test.rb +42 -0
  48. data/test/cases/named_scope_test.rb +6 -4
  49. data/test/cases/pk_test.rb +18 -0
  50. data/test/cases/reflection_test.rb +2 -2
  51. data/test/cases/schema_dumper_test.rb +19 -1
  52. data/test/cases/validations_i18n_test.rb +656 -624
  53. data/test/cases/validations_test.rb +12 -2
  54. data/test/cases/xml_serialization_test.rb +20 -0
  55. data/test/fixtures/fixture_database.sqlite +0 -0
  56. data/test/fixtures/fixture_database.sqlite3 +0 -0
  57. data/test/fixtures/fixture_database_2.sqlite +0 -0
  58. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  59. data/test/fixtures/posts.yml +3 -0
  60. data/test/models/author.rb +1 -0
  61. data/test/models/comment.rb +5 -1
  62. data/test/models/company.rb +2 -0
  63. data/test/models/company_in_module.rb +1 -1
  64. data/test/models/contract.rb +5 -0
  65. data/test/models/organization.rb +2 -0
  66. data/test/models/topic.rb +0 -2
  67. data/test/schema/postgresql_specific_schema.rb +13 -2
  68. data/test/schema/schema.rb +4 -0
  69. metadata +12 -54
  70. data/test/debug.log +0 -415
@@ -249,9 +249,10 @@ module ActiveRecord
249
249
  unless valid = association.valid?
250
250
  if reflection.options[:autosave]
251
251
  unless association.marked_for_destruction?
252
- association.errors.each do |attribute, message|
253
- attribute = "#{reflection.name}_#{attribute}"
254
- errors.add(attribute, message) unless errors.on(attribute)
252
+ association.errors.each_error do |attribute, error|
253
+ error = error.dup
254
+ error.attribute = "#{reflection.name}_#{attribute}"
255
+ errors.add(error) unless errors.on(error.attribute)
255
256
  end
256
257
  end
257
258
  else
@@ -1364,7 +1364,7 @@ module ActiveRecord #:nodoc:
1364
1364
  end
1365
1365
  defaults << options[:default] if options[:default]
1366
1366
  defaults.flatten!
1367
- defaults << attribute_key_name.humanize
1367
+ defaults << attribute_key_name.to_s.humanize
1368
1368
  options[:count] ||= 1
1369
1369
  I18n.translate(defaults.shift, options.merge(:default => defaults, :scope => [:activerecord, :attributes]))
1370
1370
  end
@@ -2294,20 +2294,24 @@ module ActiveRecord #:nodoc:
2294
2294
  # And for value objects on a composed_of relationship:
2295
2295
  # { :address => Address.new("123 abc st.", "chicago") }
2296
2296
  # # => "address_street='123 abc st.' and address_city='chicago'"
2297
- def sanitize_sql_hash_for_conditions(attrs, table_name = quoted_table_name)
2297
+ def sanitize_sql_hash_for_conditions(attrs, default_table_name = quoted_table_name)
2298
2298
  attrs = expand_hash_conditions_for_aggregates(attrs)
2299
2299
 
2300
2300
  conditions = attrs.map do |attr, value|
2301
+ table_name = default_table_name
2302
+
2301
2303
  unless value.is_a?(Hash)
2302
2304
  attr = attr.to_s
2303
2305
 
2304
2306
  # Extract table name from qualified attribute names.
2305
2307
  if attr.include?('.')
2306
- table_name, attr = attr.split('.', 2)
2307
- table_name = connection.quote_table_name(table_name)
2308
+ attr_table_name, attr = attr.split('.', 2)
2309
+ attr_table_name = connection.quote_table_name(attr_table_name)
2310
+ else
2311
+ attr_table_name = table_name
2308
2312
  end
2309
2313
 
2310
- attribute_condition("#{table_name}.#{connection.quote_column_name(attr)}", value)
2314
+ attribute_condition("#{attr_table_name}.#{connection.quote_column_name(attr)}", value)
2311
2315
  else
2312
2316
  sanitize_sql_hash_for_conditions(value, connection.quote_table_name(attr.to_s))
2313
2317
  end
@@ -3028,16 +3032,22 @@ module ActiveRecord #:nodoc:
3028
3032
 
3029
3033
  def execute_callstack_for_multiparameter_attributes(callstack)
3030
3034
  errors = []
3031
- callstack.each do |name, values|
3035
+ callstack.each do |name, values_with_empty_parameters|
3032
3036
  begin
3033
3037
  klass = (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass
3038
+ # in order to allow a date to be set without a year, we must keep the empty values.
3039
+ # Otherwise, we wouldn't be able to distinguish it from a date with an empty day.
3040
+ values = values_with_empty_parameters.reject(&:nil?)
3041
+
3034
3042
  if values.empty?
3035
3043
  send(name + "=", nil)
3036
3044
  else
3045
+
3037
3046
  value = if Time == klass
3038
3047
  instantiate_time_object(name, values)
3039
3048
  elsif Date == klass
3040
3049
  begin
3050
+ values = values_with_empty_parameters.collect do |v| v.nil? ? 1 : v end
3041
3051
  Date.new(*values)
3042
3052
  rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
3043
3053
  instantiate_time_object(name, values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
@@ -3065,10 +3075,8 @@ module ActiveRecord #:nodoc:
3065
3075
  attribute_name = multiparameter_name.split("(").first
3066
3076
  attributes[attribute_name] = [] unless attributes.include?(attribute_name)
3067
3077
 
3068
- unless value.empty?
3069
- attributes[attribute_name] <<
3070
- [ find_parameter_position(multiparameter_name), type_cast_attribute_value(multiparameter_name, value) ]
3071
- end
3078
+ parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
3079
+ attributes[attribute_name] << [ find_parameter_position(multiparameter_name), parameter_value ]
3072
3080
  end
3073
3081
 
3074
3082
  attributes.each { |name, values| attributes[name] = values.sort_by{ |v| v.first }.collect { |v| v.last } }
@@ -190,6 +190,8 @@ module ActiveRecord
190
190
  sql << ", #{options[:group_field]} AS #{options[:group_alias]}" if options[:group]
191
191
  if options[:from]
192
192
  sql << " FROM #{options[:from]} "
193
+ elsif scope && scope[:from] && !use_workaround
194
+ sql << " FROM #{scope[:from]} "
193
195
  else
194
196
  sql << " FROM (SELECT #{distinct}#{column_name}" if use_workaround
195
197
  sql << " FROM #{connection.quote_table_name(table_name)} "
@@ -277,7 +277,6 @@ module ActiveRecord
277
277
  add_column_options!(column_sql, column_options) unless type.to_sym == :primary_key
278
278
  column_sql
279
279
  end
280
- alias to_s :to_sql
281
280
 
282
281
  private
283
282
 
@@ -316,6 +315,20 @@ module ActiveRecord
316
315
  @base = base
317
316
  end
318
317
 
318
+ #Handles non supported datatypes - e.g. XML
319
+ def method_missing(symbol, *args)
320
+ if symbol.to_s == 'xml'
321
+ xml_column_fallback(args)
322
+ end
323
+ end
324
+
325
+ def xml_column_fallback(*args)
326
+ case @base.adapter_name.downcase
327
+ when 'sqlite', 'mysql'
328
+ options = args.extract_options!
329
+ column(args[0], :text, options)
330
+ end
331
+ end
319
332
  # Appends a primary key definition to the table definition.
320
333
  # Can be called multiple times, but this is probably not a good idea.
321
334
  def primary_key(name)
@@ -508,7 +521,7 @@ module ActiveRecord
508
521
  # concatenated together. This string can then be prepended and appended to
509
522
  # to generate the final SQL to create the table.
510
523
  def to_sql
511
- @columns * ', '
524
+ @columns.map(&:to_sql) * ', '
512
525
  end
513
526
 
514
527
  private
@@ -706,3 +719,4 @@ module ActiveRecord
706
719
 
707
720
  end
708
721
  end
722
+
@@ -99,7 +99,7 @@ module ActiveRecord
99
99
  # See also TableDefinition#column for details on how to create columns.
100
100
  def create_table(table_name, options = {})
101
101
  table_definition = TableDefinition.new(self)
102
- table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name)) unless options[:id] == false
102
+ table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
103
103
 
104
104
  yield table_definition
105
105
 
@@ -321,7 +321,7 @@ module ActiveRecord
321
321
  schema_migrations_table.column :version, :string, :null => false
322
322
  end
323
323
  add_index sm_table, :version, :unique => true,
324
- :name => 'unique_schema_migrations'
324
+ :name => "#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}"
325
325
 
326
326
  # Backwards-compatibility: if we find schema_info, assume we've
327
327
  # migrated up to that point:
@@ -54,6 +54,13 @@ module ActiveRecord
54
54
  false
55
55
  end
56
56
 
57
+ # Can this adapter determine the primary key for tables not attached
58
+ # to an ActiveRecord class, such as join tables? Backend specific, as
59
+ # the abstract adapter always returns +false+.
60
+ def supports_primary_key?
61
+ false
62
+ end
63
+
57
64
  # Does this adapter support using DISTINCT within COUNT? This is +true+
58
65
  # for all adapters except sqlite.
59
66
  def supports_count_distinct?
@@ -52,12 +52,7 @@ module ActiveRecord
52
52
  socket = config[:socket]
53
53
  username = config[:username] ? config[:username].to_s : 'root'
54
54
  password = config[:password].to_s
55
-
56
- if config.has_key?(:database)
57
- database = config[:database]
58
- else
59
- raise ArgumentError, "No database specified. Missing argument: database."
60
- end
55
+ database = config[:database]
61
56
 
62
57
  # Require the MySQL driver and define Mysql::Result.all_hashes
63
58
  unless defined? Mysql
@@ -80,7 +75,7 @@ module ActiveRecord
80
75
  module ConnectionAdapters
81
76
  class MysqlColumn < Column #:nodoc:
82
77
  def extract_default(default)
83
- if type == :binary || type == :text
78
+ if sql_type =~ /blob/i || type == :text
84
79
  if default.blank?
85
80
  return null ? nil : ''
86
81
  else
@@ -94,7 +89,7 @@ module ActiveRecord
94
89
  end
95
90
 
96
91
  def has_default?
97
- return false if type == :binary || type == :text #mysql forbids defaults on blob and text columns
92
+ return false if sql_type =~ /blob/i || type == :text #mysql forbids defaults on blob and text columns
98
93
  super
99
94
  end
100
95
 
@@ -212,6 +207,10 @@ module ActiveRecord
212
207
  true
213
208
  end
214
209
 
210
+ def supports_primary_key? #:nodoc:
211
+ true
212
+ end
213
+
215
214
  def supports_savepoints? #:nodoc:
216
215
  true
217
216
  end
@@ -554,6 +553,12 @@ module ActiveRecord
554
553
  keys.length == 1 ? [keys.first, nil] : nil
555
554
  end
556
555
 
556
+ # Returns just a table's primary key
557
+ def primary_key(table)
558
+ pk_and_sequence = pk_and_sequence_for(table)
559
+ pk_and_sequence && pk_and_sequence.first
560
+ end
561
+
557
562
  def case_sensitive_equality_operator
558
563
  "= BINARY"
559
564
  end
@@ -573,6 +578,10 @@ module ActiveRecord
573
578
  @connection.ssl_set(@config[:sslkey], @config[:sslcert], @config[:sslca], @config[:sslcapath], @config[:sslcipher])
574
579
  end
575
580
 
581
+ @connection.options(Mysql::OPT_CONNECT_TIMEOUT, @config[:connect_timeout]) if @config[:connect_timeout]
582
+ @connection.options(Mysql::OPT_READ_TIMEOUT, @config[:read_timeout]) if @config[:read_timeout]
583
+ @connection.options(Mysql::OPT_WRITE_TIMEOUT, @config[:write_timeout]) if @config[:write_timeout]
584
+
576
585
  @connection.real_connect(*@connection_options)
577
586
 
578
587
  # reconnect must be set after real_connect is called, because real_connect sets it to false internally
@@ -39,6 +39,12 @@ module ActiveRecord
39
39
  end
40
40
 
41
41
  module ConnectionAdapters
42
+ class TableDefinition
43
+ def xml(*args)
44
+ options = args.extract_options!
45
+ column(args[0], 'xml', options)
46
+ end
47
+ end
42
48
  # PostgreSQL-specific extensions to column definitions in a table.
43
49
  class PostgreSQLColumn < Column #:nodoc:
44
50
  # Instantiates a new PostgreSQL column definition in a table.
@@ -67,7 +73,7 @@ module ActiveRecord
67
73
  # depending on the server specifics
68
74
  super
69
75
  end
70
-
76
+
71
77
  # Maps PostgreSQL-specific data types to logical Rails types.
72
78
  def simplified_type(field_type)
73
79
  case field_type
@@ -99,10 +105,10 @@ module ActiveRecord
99
105
  :string
100
106
  # XML type
101
107
  when /^xml$/
102
- :string
108
+ :xml
103
109
  # Arrays
104
110
  when /^\D+\[\]$/
105
- :string
111
+ :string
106
112
  # Object identifier types
107
113
  when /^oid$/
108
114
  :integer
@@ -111,7 +117,7 @@ module ActiveRecord
111
117
  super
112
118
  end
113
119
  end
114
-
120
+
115
121
  # Extracts the value from a PostgreSQL column default definition.
116
122
  def self.extract_value_from_default(default)
117
123
  case default
@@ -194,7 +200,8 @@ module ActiveRecord
194
200
  :time => { :name => "time" },
195
201
  :date => { :name => "date" },
196
202
  :binary => { :name => "bytea" },
197
- :boolean => { :name => "boolean" }
203
+ :boolean => { :name => "boolean" },
204
+ :xml => { :name => "xml" }
198
205
  }
199
206
 
200
207
  # Returns 'PostgreSQL' as adapter name for identification purposes.
@@ -249,6 +256,11 @@ module ActiveRecord
249
256
  true
250
257
  end
251
258
 
259
+ # Does PostgreSQL support finding primary key on non-ActiveRecord tables?
260
+ def supports_primary_key? #:nodoc:
261
+ true
262
+ end
263
+
252
264
  # Does PostgreSQL support standard conforming strings?
253
265
  def supports_standard_conforming_strings?
254
266
  # Temporarily set the client message level above error to prevent unintentional
@@ -272,7 +284,7 @@ module ActiveRecord
272
284
  def supports_ddl_transactions?
273
285
  true
274
286
  end
275
-
287
+
276
288
  def supports_savepoints?
277
289
  true
278
290
  end
@@ -364,7 +376,7 @@ module ActiveRecord
364
376
  if value.kind_of?(String) && column && column.type == :binary
365
377
  "#{quoted_string_prefix}'#{escape_bytea(value)}'"
366
378
  elsif value.kind_of?(String) && column && column.sql_type =~ /^xml$/
367
- "xml '#{quote_string(value)}'"
379
+ "xml E'#{quote_string(value)}'"
368
380
  elsif value.kind_of?(Numeric) && column && column.sql_type =~ /^money$/
369
381
  # Not truly string input, so doesn't require (or allow) escape string syntax.
370
382
  "'#{value.to_s}'"
@@ -563,7 +575,7 @@ module ActiveRecord
563
575
  def rollback_db_transaction
564
576
  execute "ROLLBACK"
565
577
  end
566
-
578
+
567
579
  if defined?(PGconn::PQTRANS_IDLE)
568
580
  # The ruby-pg driver supports inspecting the transaction status,
569
581
  # while the ruby-postgres driver does not.
@@ -810,6 +822,12 @@ module ActiveRecord
810
822
  nil
811
823
  end
812
824
 
825
+ # Returns just a table's primary key
826
+ def primary_key(table)
827
+ pk_and_sequence = pk_and_sequence_for(table)
828
+ pk_and_sequence && pk_and_sequence.first
829
+ end
830
+
813
831
  # Renames a table.
814
832
  def rename_table(name, new_name)
815
833
  execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
@@ -908,18 +926,18 @@ module ActiveRecord
908
926
  sql = "DISTINCT ON (#{columns}) #{columns}, "
909
927
  sql << order_columns * ', '
910
928
  end
911
-
929
+
912
930
  # Returns an ORDER BY clause for the passed order option.
913
- #
931
+ #
914
932
  # PostgreSQL does not allow arbitrary ordering when using DISTINCT ON, so we work around this
915
933
  # by wrapping the +sql+ string as a sub-select and ordering in that query.
916
934
  def add_order_by_for_association_limiting!(sql, options) #:nodoc:
917
935
  return sql if options[:order].blank?
918
-
936
+
919
937
  order = options[:order].split(',').collect { |s| s.strip }.reject(&:blank?)
920
938
  order.map! { |s| 'DESC' if s =~ /\bdesc$/i }
921
939
  order = order.zip((0...order.size).to_a).map { |s,i| "id_list.alias_#{i} #{s}" }.join(', ')
922
-
940
+
923
941
  sql.replace "SELECT * FROM (#{sql}) AS id_list ORDER BY #{order}"
924
942
  end
925
943
 
@@ -1032,7 +1050,7 @@ module ActiveRecord
1032
1050
  if res.ftype(cell_index) == MONEY_COLUMN_TYPE_OID
1033
1051
  # Because money output is formatted according to the locale, there are two
1034
1052
  # cases to consider (note the decimal separators):
1035
- # (1) $12,345,678.12
1053
+ # (1) $12,345,678.12
1036
1054
  # (2) $12.345.678,12
1037
1055
  case column = row[cell_index]
1038
1056
  when /^-?\D+[\d,]+\.\d{2}$/ # (1)
@@ -1092,3 +1110,4 @@ module ActiveRecord
1092
1110
  end
1093
1111
  end
1094
1112
  end
1113
+
@@ -16,6 +16,10 @@ module ActiveRecord
16
16
  db.results_as_hash = true if defined? SQLite::Version
17
17
  db.type_translation = false
18
18
 
19
+ message = "Support for SQLite2Adapter and DeprecatedSQLiteAdapter has been removed from Rails 3. "
20
+ message << "You should migrate to SQLite 3+ or use the plugin from git://github.com/rails/sqlite2_adapter.git with Rails 3."
21
+ ActiveSupport::Deprecation.warn(message)
22
+
19
23
  # "Downgrade" deprecated sqlite API
20
24
  if SQLite.const_defined?(:Version)
21
25
  ConnectionAdapters::SQLite2Adapter.new(db, logger, config)
@@ -27,6 +31,10 @@ module ActiveRecord
27
31
 
28
32
  private
29
33
  def parse_sqlite_config!(config)
34
+ if config.include?(:dbfile)
35
+ ActiveSupport::Deprecation.warn "Please update config/database.yml to use 'database' instead of 'dbfile'"
36
+ end
37
+
30
38
  config[:database] ||= config[:dbfile]
31
39
  # Require database.
32
40
  unless config[:database]
@@ -104,6 +112,10 @@ module ActiveRecord
104
112
  true
105
113
  end
106
114
 
115
+ def supports_primary_key? #:nodoc:
116
+ true
117
+ end
118
+
107
119
  def requires_reloading?
108
120
  true
109
121
  end
@@ -143,7 +143,7 @@ module ActiveRecord
143
143
  if partial_updates?
144
144
  # Serialized attributes should always be written in case they've been
145
145
  # changed in place.
146
- update_without_dirty(changed | self.class.serialized_attributes.keys)
146
+ update_without_dirty(changed | (attributes.keys & self.class.serialized_attributes.keys))
147
147
  else
148
148
  update_without_dirty
149
149
  end
@@ -621,7 +621,8 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
621
621
  targets.each do |target|
622
622
  join_fixtures["#{label}_#{target}"] = Fixture.new(
623
623
  { association.primary_key_name => row[primary_key_name],
624
- association.association_foreign_key => Fixtures.identify(target) }, nil)
624
+ association.association_foreign_key => Fixtures.identify(target) },
625
+ nil, @connection)
625
626
  end
626
627
  end
627
628
  end
@@ -705,12 +706,12 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
705
706
 
706
707
  yaml_value.each do |fixture|
707
708
  raise Fixture::FormatError, "Bad data for #{@class_name} fixture named #{fixture}" unless fixture.respond_to?(:each)
708
- fixture.each do |name, data|
709
+ fixture.each do |name, data|
709
710
  unless data
710
711
  raise Fixture::FormatError, "Bad data for #{@class_name} fixture named #{name} (nil)"
711
712
  end
712
713
 
713
- self[name] = Fixture.new(data, model_class)
714
+ self[name] = Fixture.new(data, model_class, @connection)
714
715
  end
715
716
  end
716
717
  end
@@ -723,7 +724,7 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
723
724
  reader.each do |row|
724
725
  data = {}
725
726
  row.each_with_index { |cell, j| data[header[j].to_s.strip] = cell.to_s.strip }
726
- self["#{@class_name.to_s.underscore}_#{i+=1}"] = Fixture.new(data, model_class)
727
+ self["#{@class_name.to_s.underscore}_#{i+=1}"] = Fixture.new(data, model_class, @connection)
727
728
  end
728
729
  end
729
730
 
@@ -761,7 +762,8 @@ class Fixture #:nodoc:
761
762
 
762
763
  attr_reader :model_class
763
764
 
764
- def initialize(fixture, model_class)
765
+ def initialize(fixture, model_class, connection = ActiveRecord::Base.connection)
766
+ @connection = connection
765
767
  @fixture = fixture
766
768
  @model_class = model_class.is_a?(Class) ? model_class : model_class.constantize rescue nil
767
769
  end
@@ -783,14 +785,14 @@ class Fixture #:nodoc:
783
785
  end
784
786
 
785
787
  def key_list
786
- columns = @fixture.keys.collect{ |column_name| ActiveRecord::Base.connection.quote_column_name(column_name) }
788
+ columns = @fixture.keys.collect{ |column_name| @connection.quote_column_name(column_name) }
787
789
  columns.join(", ")
788
790
  end
789
791
 
790
792
  def value_list
791
793
  list = @fixture.inject([]) do |fixtures, (key, value)|
792
794
  col = model_class.columns_hash[key] if model_class.respond_to?(:ancestors) && model_class.ancestors.include?(ActiveRecord::Base)
793
- fixtures << ActiveRecord::Base.connection.quote(value, col).gsub('[^\]\\n', "\n").gsub('[^\]\\r', "\r")
795
+ fixtures << @connection.quote(value, col).gsub('[^\]\\n', "\n").gsub('[^\]\\r', "\r")
794
796
  end
795
797
  list * ', '
796
798
  end