activerecord 3.0.20 → 3.1.0.beta1

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 (122) hide show
  1. data/CHANGELOG +220 -91
  2. data/README.rdoc +3 -3
  3. data/examples/performance.rb +88 -109
  4. data/lib/active_record.rb +6 -2
  5. data/lib/active_record/aggregations.rb +22 -45
  6. data/lib/active_record/associations.rb +264 -991
  7. data/lib/active_record/associations/alias_tracker.rb +85 -0
  8. data/lib/active_record/associations/association.rb +231 -0
  9. data/lib/active_record/associations/association_scope.rb +120 -0
  10. data/lib/active_record/associations/belongs_to_association.rb +40 -60
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +15 -63
  12. data/lib/active_record/associations/builder/association.rb +53 -0
  13. data/lib/active_record/associations/builder/belongs_to.rb +85 -0
  14. data/lib/active_record/associations/builder/collection_association.rb +75 -0
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +63 -0
  16. data/lib/active_record/associations/builder/has_many.rb +65 -0
  17. data/lib/active_record/associations/builder/has_one.rb +63 -0
  18. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  19. data/lib/active_record/associations/collection_association.rb +524 -0
  20. data/lib/active_record/associations/collection_proxy.rb +125 -0
  21. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +27 -118
  22. data/lib/active_record/associations/has_many_association.rb +50 -79
  23. data/lib/active_record/associations/has_many_through_association.rb +98 -67
  24. data/lib/active_record/associations/has_one_association.rb +45 -115
  25. data/lib/active_record/associations/has_one_through_association.rb +21 -25
  26. data/lib/active_record/associations/join_dependency.rb +215 -0
  27. data/lib/active_record/associations/join_dependency/join_association.rb +150 -0
  28. data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
  29. data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
  30. data/lib/active_record/associations/join_helper.rb +56 -0
  31. data/lib/active_record/associations/preloader.rb +177 -0
  32. data/lib/active_record/associations/preloader/association.rb +126 -0
  33. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  34. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  35. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
  36. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  37. data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
  38. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  39. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  40. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  41. data/lib/active_record/associations/preloader/through_association.rb +67 -0
  42. data/lib/active_record/associations/singular_association.rb +55 -0
  43. data/lib/active_record/associations/through_association.rb +80 -0
  44. data/lib/active_record/attribute_methods.rb +19 -5
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +9 -8
  46. data/lib/active_record/attribute_methods/dirty.rb +8 -2
  47. data/lib/active_record/attribute_methods/primary_key.rb +33 -13
  48. data/lib/active_record/attribute_methods/read.rb +17 -17
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -4
  50. data/lib/active_record/attribute_methods/write.rb +2 -1
  51. data/lib/active_record/autosave_association.rb +66 -45
  52. data/lib/active_record/base.rb +445 -273
  53. data/lib/active_record/callbacks.rb +24 -33
  54. data/lib/active_record/coders/yaml_column.rb +41 -0
  55. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +106 -13
  56. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +16 -2
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -12
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +16 -16
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +61 -22
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +16 -273
  62. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +80 -42
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +44 -25
  64. data/lib/active_record/connection_adapters/column.rb +268 -0
  65. data/lib/active_record/connection_adapters/mysql2_adapter.rb +686 -0
  66. data/lib/active_record/connection_adapters/mysql_adapter.rb +331 -88
  67. data/lib/active_record/connection_adapters/postgresql_adapter.rb +295 -267
  68. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +3 -7
  69. data/lib/active_record/connection_adapters/sqlite_adapter.rb +108 -26
  70. data/lib/active_record/counter_cache.rb +7 -4
  71. data/lib/active_record/fixtures.rb +174 -192
  72. data/lib/active_record/identity_map.rb +131 -0
  73. data/lib/active_record/locking/optimistic.rb +20 -14
  74. data/lib/active_record/locking/pessimistic.rb +4 -4
  75. data/lib/active_record/log_subscriber.rb +24 -4
  76. data/lib/active_record/migration.rb +265 -144
  77. data/lib/active_record/migration/command_recorder.rb +103 -0
  78. data/lib/active_record/named_scope.rb +68 -25
  79. data/lib/active_record/nested_attributes.rb +58 -15
  80. data/lib/active_record/observer.rb +3 -7
  81. data/lib/active_record/persistence.rb +58 -38
  82. data/lib/active_record/query_cache.rb +25 -3
  83. data/lib/active_record/railtie.rb +21 -12
  84. data/lib/active_record/railties/console_sandbox.rb +6 -0
  85. data/lib/active_record/railties/databases.rake +147 -116
  86. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  87. data/lib/active_record/reflection.rb +176 -44
  88. data/lib/active_record/relation.rb +125 -49
  89. data/lib/active_record/relation/batches.rb +7 -5
  90. data/lib/active_record/relation/calculations.rb +50 -18
  91. data/lib/active_record/relation/finder_methods.rb +47 -26
  92. data/lib/active_record/relation/predicate_builder.rb +24 -21
  93. data/lib/active_record/relation/query_methods.rb +117 -101
  94. data/lib/active_record/relation/spawn_methods.rb +27 -20
  95. data/lib/active_record/result.rb +34 -0
  96. data/lib/active_record/schema.rb +5 -6
  97. data/lib/active_record/schema_dumper.rb +11 -13
  98. data/lib/active_record/serialization.rb +2 -2
  99. data/lib/active_record/serializers/xml_serializer.rb +10 -10
  100. data/lib/active_record/session_store.rb +8 -2
  101. data/lib/active_record/test_case.rb +9 -20
  102. data/lib/active_record/timestamp.rb +21 -9
  103. data/lib/active_record/transactions.rb +16 -15
  104. data/lib/active_record/validations.rb +21 -22
  105. data/lib/active_record/validations/associated.rb +3 -1
  106. data/lib/active_record/validations/uniqueness.rb +48 -58
  107. data/lib/active_record/version.rb +3 -3
  108. data/lib/rails/generators/active_record.rb +6 -0
  109. data/lib/rails/generators/active_record/migration/templates/migration.rb +10 -2
  110. data/lib/rails/generators/active_record/model/model_generator.rb +2 -1
  111. data/lib/rails/generators/active_record/model/templates/migration.rb +6 -5
  112. data/lib/rails/generators/active_record/model/templates/model.rb +2 -0
  113. data/lib/rails/generators/active_record/model/templates/module.rb +2 -0
  114. data/lib/rails/generators/active_record/observer/templates/observer.rb +2 -0
  115. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +2 -1
  116. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +2 -2
  117. metadata +106 -77
  118. checksums.yaml +0 -7
  119. data/lib/active_record/association_preload.rb +0 -431
  120. data/lib/active_record/associations/association_collection.rb +0 -572
  121. data/lib/active_record/associations/association_proxy.rb +0 -304
  122. data/lib/active_record/associations/through_association_scope.rb +0 -160
@@ -1,4 +1,5 @@
1
1
  require 'active_record/connection_adapters/sqlite_adapter'
2
+ require 'sqlite3'
2
3
 
3
4
  module ActiveRecord
4
5
  class Base
@@ -20,16 +21,12 @@ module ActiveRecord
20
21
  raise ArgumentError, 'adapter name should be "sqlite3"'
21
22
  end
22
23
 
23
- unless self.class.const_defined?(:SQLite3)
24
- require_library_or_gem(config[:adapter])
25
- end
26
-
27
24
  db = SQLite3::Database.new(
28
25
  config[:database],
29
26
  :results_as_hash => true
30
27
  )
31
28
 
32
- db.busy_timeout(config[:timeout]) unless config[:timeout].nil?
29
+ db.busy_timeout(config[:timeout]) if config[:timeout]
33
30
 
34
31
  ConnectionAdapters::SQLite3Adapter.new(db, logger, config)
35
32
  end
@@ -51,8 +48,7 @@ module ActiveRecord
51
48
  if @connection.respond_to?(:encoding)
52
49
  @connection.encoding.to_s
53
50
  else
54
- encoding = @connection.execute('PRAGMA encoding')
55
- encoding[0]['encoding']
51
+ @connection.execute('PRAGMA encoding')[0]['encoding']
56
52
  end
57
53
  end
58
54
 
@@ -50,6 +50,7 @@ module ActiveRecord
50
50
 
51
51
  def initialize(connection, logger, config)
52
52
  super(connection, logger)
53
+ @statements = {}
53
54
  @config = config
54
55
  end
55
56
 
@@ -57,14 +58,28 @@ module ActiveRecord
57
58
  'SQLite'
58
59
  end
59
60
 
61
+ # Returns true if SQLite version is '2.0.0' or greater, false otherwise.
60
62
  def supports_ddl_transactions?
61
63
  sqlite_version >= '2.0.0'
62
64
  end
63
65
 
66
+ # Returns true if SQLite version is '3.6.8' or greater, false otherwise.
67
+ def supports_savepoints?
68
+ sqlite_version >= '3.6.8'
69
+ end
70
+
71
+ # Returns true, since this connection adapter supports prepared statement
72
+ # caching.
73
+ def supports_statement_cache?
74
+ true
75
+ end
76
+
77
+ # Returns true, since this connection adapter supports migrations.
64
78
  def supports_migrations? #:nodoc:
65
79
  true
66
80
  end
67
81
 
82
+ # Returns true.
68
83
  def supports_primary_key? #:nodoc:
69
84
  true
70
85
  end
@@ -73,19 +88,30 @@ module ActiveRecord
73
88
  true
74
89
  end
75
90
 
91
+ # Returns true if SQLite version is '3.1.6' or greater, false otherwise.
76
92
  def supports_add_column?
77
93
  sqlite_version >= '3.1.6'
78
94
  end
79
95
 
96
+ # Disconnects from the database if already connected. Otherwise, this
97
+ # method does nothing.
80
98
  def disconnect!
81
99
  super
100
+ clear_cache!
82
101
  @connection.close rescue nil
83
102
  end
84
103
 
104
+ # Clears the prepared statements cache.
105
+ def clear_cache!
106
+ @statements.clear
107
+ end
108
+
109
+ # Returns true if SQLite version is '3.2.6' or greater, false otherwise.
85
110
  def supports_count_distinct? #:nodoc:
86
111
  sqlite_version >= '3.2.6'
87
112
  end
88
113
 
114
+ # Returns true if SQLite version is '3.1.0' or greater, false otherwise.
89
115
  def supports_autoincrement? #:nodoc:
90
116
  sqlite_version >= '3.1.0'
91
117
  end
@@ -115,13 +141,13 @@ module ActiveRecord
115
141
  end
116
142
 
117
143
  def quote_column_name(name) #:nodoc:
118
- %Q("#{name.to_s.gsub('"', '""')}")
144
+ %Q("#{name}")
119
145
  end
120
146
 
121
147
  # Quote date/time values for use in SQL input. Includes microseconds
122
148
  # if the value is a Time responding to usec.
123
149
  def quoted_date(value) #:nodoc:
124
- if value.acts_like?(:time) && value.respond_to?(:usec)
150
+ if value.respond_to?(:usec)
125
151
  "#{super}.#{sprintf("%06d", value.usec)}"
126
152
  else
127
153
  super
@@ -131,6 +157,42 @@ module ActiveRecord
131
157
 
132
158
  # DATABASE STATEMENTS ======================================
133
159
 
160
+ def exec_query(sql, name = nil, binds = [])
161
+ log(sql, name, binds) do
162
+
163
+ # Don't cache statements without bind values
164
+ if binds.empty?
165
+ stmt = @connection.prepare(sql)
166
+ cols = stmt.columns
167
+ records = stmt.to_a
168
+ stmt.close
169
+ stmt = records
170
+ else
171
+ cache = @statements[sql] ||= {
172
+ :stmt => @connection.prepare(sql)
173
+ }
174
+ stmt = cache[:stmt]
175
+ cols = cache[:cols] ||= stmt.columns
176
+ stmt.reset!
177
+ stmt.bind_params binds.map { |col, val|
178
+ type_cast(val, col)
179
+ }
180
+ end
181
+
182
+ ActiveRecord::Result.new(cols, stmt.to_a)
183
+ end
184
+ end
185
+
186
+ def exec_delete(sql, name = 'SQL', binds = [])
187
+ exec_query(sql, name, binds)
188
+ @connection.changes
189
+ end
190
+ alias :exec_update :exec_delete
191
+
192
+ def last_inserted_id(result)
193
+ @connection.last_insert_row_id
194
+ end
195
+
134
196
  def execute(sql, name = nil) #:nodoc:
135
197
  log(sql, name) { @connection.execute(sql) }
136
198
  end
@@ -146,14 +208,25 @@ module ActiveRecord
146
208
  end
147
209
 
148
210
  def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
149
- super || @connection.last_insert_row_id
211
+ super
212
+ id_value || @connection.last_insert_row_id
150
213
  end
151
214
  alias :create :insert_sql
152
215
 
153
216
  def select_rows(sql, name = nil)
154
- execute(sql, name).map do |row|
155
- (0...(row.size / 2)).map { |i| row[i] }
156
- end
217
+ exec_query(sql, name).rows
218
+ end
219
+
220
+ def create_savepoint
221
+ execute("SAVEPOINT #{current_savepoint_name}")
222
+ end
223
+
224
+ def rollback_to_savepoint
225
+ execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}")
226
+ end
227
+
228
+ def release_savepoint
229
+ execute("RELEASE SAVEPOINT #{current_savepoint_name}")
157
230
  end
158
231
 
159
232
  def begin_db_transaction #:nodoc:
@@ -170,31 +243,42 @@ module ActiveRecord
170
243
 
171
244
  # SCHEMA STATEMENTS ========================================
172
245
 
173
- def tables(name = nil) #:nodoc:
246
+ def tables(name = 'SCHEMA') #:nodoc:
174
247
  sql = <<-SQL
175
248
  SELECT name
176
249
  FROM sqlite_master
177
250
  WHERE type = 'table' AND NOT name = 'sqlite_sequence'
178
251
  SQL
179
252
 
180
- execute(sql, name).map do |row|
253
+ exec_query(sql, name).map do |row|
181
254
  row['name']
182
255
  end
183
256
  end
184
257
 
258
+ # Returns an array of +SQLiteColumn+ objects for the table specified by +table_name+.
185
259
  def columns(table_name, name = nil) #:nodoc:
186
260
  table_structure(table_name).map do |field|
261
+ case field["dflt_value"]
262
+ when /^null$/i
263
+ field["dflt_value"] = nil
264
+ when /^'(.*)'$/
265
+ field["dflt_value"] = $1.gsub(/''/, "'")
266
+ when /^"(.*)"$/
267
+ field["dflt_value"] = $1.gsub(/""/, '"')
268
+ end
269
+
187
270
  SQLiteColumn.new(field['name'], field['dflt_value'], field['type'], field['notnull'].to_i == 0)
188
271
  end
189
272
  end
190
273
 
274
+ # Returns an array of indexes for the given table.
191
275
  def indexes(table_name, name = nil) #:nodoc:
192
- execute("PRAGMA index_list(#{quote_table_name(table_name)})", name).map do |row|
276
+ exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", name).map do |row|
193
277
  IndexDefinition.new(
194
278
  table_name,
195
279
  row['name'],
196
- row['unique'].to_i != 0,
197
- execute("PRAGMA index_info('#{row['name']}')").map { |col|
280
+ row['unique'] != 0,
281
+ exec_query("PRAGMA index_info('#{row['name']}')").map { |col|
198
282
  col['name']
199
283
  })
200
284
  end
@@ -202,17 +286,21 @@ module ActiveRecord
202
286
 
203
287
  def primary_key(table_name) #:nodoc:
204
288
  column = table_structure(table_name).find { |field|
205
- field['pk'].to_i == 1
289
+ field['pk'] == 1
206
290
  }
207
291
  column && column['name']
208
292
  end
209
293
 
210
294
  def remove_index!(table_name, index_name) #:nodoc:
211
- execute "DROP INDEX #{quote_column_name(index_name)}"
295
+ exec_query "DROP INDEX #{quote_column_name(index_name)}"
212
296
  end
213
297
 
298
+ # Renames a table.
299
+ #
300
+ # Example:
301
+ # rename_table('octopuses', 'octopi')
214
302
  def rename_table(name, new_name)
215
- execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
303
+ exec_query "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
216
304
  end
217
305
 
218
306
  # See: http://www.sqlite.org/lang_altertable.html
@@ -249,7 +337,7 @@ module ActiveRecord
249
337
 
250
338
  def change_column_null(table_name, column_name, null, default = nil)
251
339
  unless null || default.nil?
252
- execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
340
+ exec_query("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
253
341
  end
254
342
  alter_table(table_name) do |definition|
255
343
  definition[column_name].null = null
@@ -280,18 +368,12 @@ module ActiveRecord
280
368
  end
281
369
 
282
370
  protected
283
- def select(sql, name = nil) #:nodoc:
284
- execute(sql, name).map do |row|
285
- record = {}
286
- row.each do |key, value|
287
- record[key.sub(/^"?\w+"?\./, '')] = value if key.is_a?(String)
288
- end
289
- record
290
- end
371
+ def select(sql, name = nil, binds = []) #:nodoc:
372
+ exec_query(sql, name, binds).to_a
291
373
  end
292
374
 
293
375
  def table_structure(table_name)
294
- structure = @connection.table_info(quote_table_name(table_name))
376
+ structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", 'SCHEMA').to_hash
295
377
  raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
296
378
  structure
297
379
  end
@@ -367,11 +449,11 @@ module ActiveRecord
367
449
  quoted_columns = columns.map { |col| quote_column_name(col) } * ','
368
450
 
369
451
  quoted_to = quote_table_name(to)
370
- @connection.execute "SELECT * FROM #{quote_table_name(from)}" do |row|
452
+ exec_query("SELECT * FROM #{quote_table_name(from)}").each do |row|
371
453
  sql = "INSERT INTO #{quoted_to} (#{quoted_columns}) VALUES ("
372
454
  sql << columns.map {|col| quote row[column_mappings[col]]} * ', '
373
455
  sql << ')'
374
- @connection.execute sql
456
+ exec_query sql
375
457
  end
376
458
  end
377
459
 
@@ -30,9 +30,10 @@ module ActiveRecord
30
30
  reflection = belongs_to.find { |e| e.class_name == expected_name }
31
31
  counter_name = reflection.counter_cache_column
32
32
 
33
- self.unscoped.where(arel_table[self.primary_key].eq(object.id)).arel.update({
33
+ stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({
34
34
  arel_table[counter_name] => object.send(association).count
35
35
  })
36
+ connection.update stmt.to_sql
36
37
  end
37
38
  return true
38
39
  end
@@ -56,15 +57,15 @@ module ActiveRecord
56
57
  # Post.update_counters 5, :comment_count => -1, :action_count => 1
57
58
  # # Executes the following SQL:
58
59
  # # UPDATE posts
59
- # # SET comment_count = comment_count - 1,
60
- # # action_count = action_count + 1
60
+ # # SET comment_count = COALESCE(comment_count, 0) - 1,
61
+ # # action_count = COALESCE(action_count, 0) + 1
61
62
  # # WHERE id = 5
62
63
  #
63
64
  # # For the Posts with id of 10 and 15, increment the comment_count by 1
64
65
  # Post.update_counters [10, 15], :comment_count => 1
65
66
  # # Executes the following SQL:
66
67
  # # UPDATE posts
67
- # # SET comment_count = comment_count + 1,
68
+ # # SET comment_count = COALESCE(comment_count, 0) + 1,
68
69
  # # WHERE id IN (10, 15)
69
70
  def update_counters(id, counters)
70
71
  updates = counters.map do |counter_name, value|
@@ -73,6 +74,8 @@ module ActiveRecord
73
74
  "#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}"
74
75
  end
75
76
 
77
+ IdentityMap.remove_by_id(symbolized_base_class, id) if IdentityMap.enabled?
78
+
76
79
  update_all(updates.join(', '), primary_key => id )
77
80
  end
78
81
 
@@ -12,15 +12,7 @@ require 'active_support/dependencies'
12
12
  require 'active_support/core_ext/array/wrap'
13
13
  require 'active_support/core_ext/object/blank'
14
14
  require 'active_support/core_ext/logger'
15
-
16
- if RUBY_VERSION < '1.9'
17
- module YAML #:nodoc:
18
- class Omap #:nodoc:
19
- def keys; map { |k, v| k } end
20
- def values; map { |k, v| v } end
21
- end
22
- end
23
- end
15
+ require 'active_support/ordered_hash'
24
16
 
25
17
  if defined? ActiveRecord
26
18
  class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
@@ -181,10 +173,10 @@ class FixturesFileNotFound < StandardError; end
181
173
  # traversed in the database to create the fixture hash and/or instance variables. This is expensive for
182
174
  # large sets of fixtured data.
183
175
  #
184
- # = Dynamic fixtures with ERb
176
+ # = Dynamic fixtures with ERB
185
177
  #
186
178
  # Some times you don't care about the content of the fixtures as much as you care about the volume. In these cases, you can
187
- # mix ERb in with your YAML or CSV fixtures to create a bunch of fixtures for load testing, like:
179
+ # mix ERB in with your YAML or CSV fixtures to create a bunch of fixtures for load testing, like:
188
180
  #
189
181
  # <% for i in 1..1000 %>
190
182
  # fix_<%= i %>:
@@ -194,7 +186,7 @@ class FixturesFileNotFound < StandardError; end
194
186
  #
195
187
  # This will create 1000 very simple YAML fixtures.
196
188
  #
197
- # Using ERb, you can also inject dynamic values into your fixtures with inserts like <tt><%= Date.today.strftime("%Y-%m-%d") %></tt>.
189
+ # Using ERB, you can also inject dynamic values into your fixtures with inserts like <tt><%= Date.today.strftime("%Y-%m-%d") %></tt>.
198
190
  # This is however a feature to be used with some caution. The point of fixtures are that they're
199
191
  # stable units of predictable sample data. If you feel that you need to inject dynamic values, then
200
192
  # perhaps you should reexamine whether your application is properly testable. Hence, dynamic values
@@ -452,20 +444,23 @@ class FixturesFileNotFound < StandardError; end
452
444
  #
453
445
  # Any fixture labeled "DEFAULTS" is safely ignored.
454
446
 
455
- class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
447
+ class Fixtures
456
448
  MAX_ID = 2 ** 30 - 1
457
- DEFAULT_FILTER_RE = /\.ya?ml$/
458
449
 
459
- @@all_cached_fixtures = {}
450
+ @@all_cached_fixtures = Hash.new { |h,k| h[k] = {} }
460
451
 
461
- def self.reset_cache(connection = nil)
462
- connection ||= ActiveRecord::Base.connection
463
- @@all_cached_fixtures[connection.object_id] = {}
452
+ def self.find_table_name(table_name) # :nodoc:
453
+ ActiveRecord::Base.pluralize_table_names ?
454
+ table_name.to_s.singularize.camelize :
455
+ table_name.to_s.camelize
456
+ end
457
+
458
+ def self.reset_cache
459
+ @@all_cached_fixtures.clear
464
460
  end
465
461
 
466
462
  def self.cache_for_connection(connection)
467
- @@all_cached_fixtures[connection.object_id] ||= {}
468
- @@all_cached_fixtures[connection.object_id]
463
+ @@all_cached_fixtures[connection]
469
464
  end
470
465
 
471
466
  def self.fixture_is_cached?(connection, table_name)
@@ -474,27 +469,23 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
474
469
 
475
470
  def self.cached_fixtures(connection, keys_to_fetch = nil)
476
471
  if keys_to_fetch
477
- fixtures = cache_for_connection(connection).values_at(*keys_to_fetch)
472
+ cache_for_connection(connection).values_at(*keys_to_fetch)
478
473
  else
479
- fixtures = cache_for_connection(connection).values
474
+ cache_for_connection(connection).values
480
475
  end
481
- fixtures.size > 1 ? fixtures : fixtures.first
482
476
  end
483
477
 
484
478
  def self.cache_fixtures(connection, fixtures_map)
485
479
  cache_for_connection(connection).update(fixtures_map)
486
480
  end
487
481
 
488
- def self.instantiate_fixtures(object, table_name, fixtures, load_instances = true)
489
- object.instance_variable_set "@#{table_name.to_s.gsub('.','_')}", fixtures
482
+ def self.instantiate_fixtures(object, fixture_name, fixtures, load_instances = true)
490
483
  if load_instances
491
- ActiveRecord::Base.silence do
492
- fixtures.each do |name, fixture|
493
- begin
494
- object.instance_variable_set "@#{name}", fixture.find
495
- rescue FixtureClassNotFound
496
- nil
497
- end
484
+ fixtures.each do |name, fixture|
485
+ begin
486
+ object.instance_variable_set "@#{name}", fixture.find
487
+ rescue FixtureClassNotFound
488
+ nil
498
489
  end
499
490
  end
500
491
  end
@@ -511,36 +502,58 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
511
502
 
512
503
  def self.create_fixtures(fixtures_directory, table_names, class_names = {})
513
504
  table_names = [table_names].flatten.map { |n| n.to_s }
514
- table_names.each { |n| class_names[n.tr('/', '_').to_sym] = n.classify if n.include?('/') }
515
- connection = block_given? ? yield : ActiveRecord::Base.connection
505
+ table_names.each { |n|
506
+ class_names[n.tr('/', '_').to_sym] = n.classify if n.include?('/')
507
+ }
516
508
 
517
- table_names_to_fetch = table_names.reject { |table_name| fixture_is_cached?(connection, table_name) }
509
+ # FIXME: Apparently JK uses this.
510
+ connection = block_given? ? yield : ActiveRecord::Base.connection
518
511
 
519
- unless table_names_to_fetch.empty?
520
- ActiveRecord::Base.silence do
521
- connection.disable_referential_integrity do
522
- fixtures_map = {}
512
+ files_to_read = table_names.reject { |table_name|
513
+ fixture_is_cached?(connection, table_name)
514
+ }
523
515
 
524
- fixtures = table_names_to_fetch.map do |table_name|
525
- fixtures_map[table_name] = Fixtures.new(connection, table_name.tr('/', '_'), class_names[table_name.tr('/', '_').to_sym], File.join(fixtures_directory, table_name))
526
- end
516
+ unless files_to_read.empty?
517
+ connection.disable_referential_integrity do
518
+ fixtures_map = {}
527
519
 
528
- all_loaded_fixtures.update(fixtures_map)
520
+ fixture_files = files_to_read.map do |path|
521
+ table_name = path.tr '/', '_'
529
522
 
530
- connection.transaction(:requires_new => true) do
531
- fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures }
532
- fixtures.each { |fixture| fixture.insert_fixtures }
523
+ fixtures_map[path] = Fixtures.new(
524
+ connection,
525
+ table_name,
526
+ class_names[table_name.to_sym] || table_name.classify,
527
+ File.join(fixtures_directory, path))
528
+ end
529
+
530
+ all_loaded_fixtures.update(fixtures_map)
533
531
 
534
- # Cap primary key sequences to max(pk).
535
- if connection.respond_to?(:reset_pk_sequence!)
536
- table_names.each do |table_name|
537
- connection.reset_pk_sequence!(table_name.tr('/', '_'))
532
+ connection.transaction(:requires_new => true) do
533
+ fixture_files.each do |ff|
534
+ conn = ff.model_class.respond_to?(:connection) ? ff.model_class.connection : connection
535
+ table_rows = ff.table_rows
536
+
537
+ table_rows.keys.each do |table|
538
+ conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
539
+ end
540
+
541
+ table_rows.each do |table_name,rows|
542
+ rows.each do |row|
543
+ conn.insert_fixture(row, table_name)
538
544
  end
539
545
  end
540
546
  end
541
547
 
542
- cache_fixtures(connection, fixtures_map)
548
+ # Cap primary key sequences to max(pk).
549
+ if connection.respond_to?(:reset_pk_sequence!)
550
+ table_names.each do |table_name|
551
+ connection.reset_pk_sequence!(table_name.tr('/', '_'))
552
+ end
553
+ end
543
554
  end
555
+
556
+ cache_fixtures(connection, fixtures_map)
544
557
  end
545
558
  end
546
559
  cached_fixtures(connection, table_names)
@@ -552,40 +565,59 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
552
565
  Zlib.crc32(label.to_s) % MAX_ID
553
566
  end
554
567
 
555
- attr_reader :table_name, :name
568
+ attr_reader :table_name, :name, :fixtures, :model_class
569
+
570
+ def initialize(connection, table_name, class_name, fixture_path)
571
+ @connection = connection
572
+ @table_name = table_name
573
+ @fixture_path = fixture_path
574
+ @name = table_name # preserve fixture base name
575
+ @class_name = class_name
576
+
577
+ @fixtures = ActiveSupport::OrderedHash.new
578
+ @table_name = "#{ActiveRecord::Base.table_name_prefix}#{@table_name}#{ActiveRecord::Base.table_name_suffix}"
579
+
580
+ # Should be an AR::Base type class
581
+ if class_name.is_a?(Class)
582
+ @table_name = class_name.table_name
583
+ @connection = class_name.connection
584
+ @model_class = class_name
585
+ else
586
+ @model_class = class_name.constantize rescue nil
587
+ end
556
588
 
557
- def initialize(connection, table_name, class_name, fixture_path, file_filter = DEFAULT_FILTER_RE)
558
- @connection, @table_name, @fixture_path, @file_filter = connection, table_name, fixture_path, file_filter
559
- @name = table_name # preserve fixture base name
560
- @class_name = class_name ||
561
- (ActiveRecord::Base.pluralize_table_names ? @table_name.singularize.camelize : @table_name.camelize)
562
- @table_name = "#{ActiveRecord::Base.table_name_prefix}#{@table_name}#{ActiveRecord::Base.table_name_suffix}"
563
- @table_name = class_name.table_name if class_name.respond_to?(:table_name)
564
- @connection = class_name.connection if class_name.respond_to?(:connection)
565
589
  read_fixture_files
566
590
  end
567
591
 
568
- def delete_existing_fixtures
569
- @connection.delete "DELETE FROM #{@connection.quote_table_name(table_name)}", 'Fixture Delete'
592
+ def [](x)
593
+ fixtures[x]
594
+ end
595
+
596
+ def []=(k,v)
597
+ fixtures[k] = v
570
598
  end
571
599
 
572
- def insert_fixtures
600
+ def each(&block)
601
+ fixtures.each(&block)
602
+ end
603
+
604
+ def size
605
+ fixtures.size
606
+ end
607
+
608
+ # Return a hash of rows to be inserted. The key is the table, the value is
609
+ # a list of rows to insert to that table.
610
+ def table_rows
573
611
  now = ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now
574
612
  now = now.to_s(:db)
575
613
 
576
614
  # allow a standard key to be used for doing defaults in YAML
577
- if is_a?(Hash)
578
- delete('DEFAULTS')
579
- else
580
- delete(assoc('DEFAULTS'))
581
- end
615
+ fixtures.delete('DEFAULTS')
582
616
 
583
617
  # track any join tables we need to insert later
584
- habtm_fixtures = Hash.new do |h, habtm|
585
- h[habtm] = HabtmFixtures.new(@connection, habtm.options[:join_table], nil, nil)
586
- end
618
+ rows = Hash.new { |h,table| h[table] = [] }
587
619
 
588
- each do |label, fixture|
620
+ rows[table_name] = fixtures.map do |label, fixture|
589
621
  row = fixture.to_hash
590
622
 
591
623
  if model_class && model_class < ActiveRecord::Base
@@ -621,14 +653,9 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
621
653
  fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
622
654
 
623
655
  if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
624
- if association.options[:polymorphic]
625
- if value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
626
- target_type = $1
627
- target_type_name = (association.options[:foreign_type] || "#{association.name}_type").to_s
628
-
629
- # support polymorphic belongs_to as "label (Type)"
630
- row[target_type_name] = target_type
631
- end
656
+ if association.options[:polymorphic] && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
657
+ # support polymorphic belongs_to as "label (Type)"
658
+ row[association.foreign_type] = $1
632
659
  end
633
660
 
634
661
  row[fk_name] = Fixtures.identify(value)
@@ -636,47 +663,22 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
636
663
  when :has_and_belongs_to_many
637
664
  if (targets = row.delete(association.name.to_s))
638
665
  targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
639
- join_fixtures = habtm_fixtures[association]
640
-
641
- targets.each do |target|
642
- join_fixtures["#{label}_#{target}"] = Fixture.new(
643
- { association.primary_key_name => row[primary_key_name],
644
- association.association_foreign_key => Fixtures.identify(target) },
645
- nil, @connection)
646
- end
666
+ table_name = association.options[:join_table]
667
+ rows[table_name].concat targets.map { |target|
668
+ { association.foreign_key => row[primary_key_name],
669
+ association.association_foreign_key => Fixtures.identify(target) }
670
+ }
647
671
  end
648
672
  end
649
673
  end
650
674
  end
651
675
 
652
- @connection.insert_fixture(fixture, @table_name)
653
- end
654
-
655
- # insert any HABTM join tables we discovered
656
- habtm_fixtures.values.each do |fixture|
657
- fixture.delete_existing_fixtures
658
- fixture.insert_fixtures
676
+ row
659
677
  end
678
+ rows
660
679
  end
661
680
 
662
681
  private
663
- class HabtmFixtures < ::Fixtures #:nodoc:
664
- def read_fixture_files; end
665
- end
666
-
667
- def model_class
668
- unless defined?(@model_class)
669
- @model_class =
670
- if @class_name.nil? || @class_name.is_a?(Class)
671
- @class_name
672
- else
673
- @class_name.constantize rescue nil
674
- end
675
- end
676
-
677
- @model_class
678
- end
679
-
680
682
  def primary_key_name
681
683
  @primary_key_name ||= model_class && model_class.primary_key
682
684
  end
@@ -730,7 +732,7 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
730
732
  raise Fixture::FormatError, "Bad data for #{@class_name} fixture named #{name} (nil)"
731
733
  end
732
734
 
733
- self[name] = Fixture.new(data, model_class, @connection)
735
+ fixtures[name] = Fixture.new(data, model_class)
734
736
  end
735
737
  end
736
738
  end
@@ -743,7 +745,7 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
743
745
  reader.each do |row|
744
746
  data = {}
745
747
  row.each_with_index { |cell, j| data[header[j].to_s.strip] = cell.to_s.strip }
746
- self["#{@class_name.to_s.underscore}_#{i+=1}"] = Fixture.new(data, model_class, @connection)
748
+ fixtures["#{@class_name.to_s.underscore}_#{i+=1}"] = Fixture.new(data, model_class)
747
749
  end
748
750
  end
749
751
 
@@ -759,16 +761,10 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
759
761
  File.basename(@fixture_path).split(".").first
760
762
  end
761
763
 
762
- RESCUE_ERRORS = [ ArgumentError ]
763
-
764
- if defined?(Psych) && defined?(Psych::SyntaxError)
765
- RESCUE_ERRORS << Psych::SyntaxError
766
- end
767
-
768
764
  def parse_yaml_string(fixture_content)
769
765
  YAML::load(erb_render(fixture_content))
770
- rescue *RESCUE_ERRORS => error
771
- raise Fixture::FormatError, "a YAML error occurred parsing #{yaml_file_path}. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at http://www.yaml.org/faq.html\nThe exact error was:\n #{error.class}: #{error}", error.backtrace
766
+ rescue => error
767
+ raise Fixture::FormatError, "a YAML error occurred parsing #{yaml_file_path}. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at http://www.yaml.org/faq.html\nThe exact error was:\n #{error.class}: #{error}"
772
768
  end
773
769
 
774
770
  def erb_render(fixture_content)
@@ -785,44 +781,30 @@ class Fixture #:nodoc:
785
781
  class FormatError < FixtureError #:nodoc:
786
782
  end
787
783
 
788
- attr_reader :model_class
784
+ attr_reader :model_class, :fixture
789
785
 
790
- def initialize(fixture, model_class, connection = ActiveRecord::Base.connection)
791
- @connection = connection
792
- @fixture = fixture
793
- @model_class = model_class.is_a?(Class) ? model_class : model_class.constantize rescue nil
786
+ def initialize(fixture, model_class)
787
+ @fixture = fixture
788
+ @model_class = model_class
794
789
  end
795
790
 
796
791
  def class_name
797
- @model_class.name if @model_class
792
+ model_class.name if model_class
798
793
  end
799
794
 
800
795
  def each
801
- @fixture.each { |item| yield item }
796
+ fixture.each { |item| yield item }
802
797
  end
803
798
 
804
799
  def [](key)
805
- @fixture[key]
806
- end
807
-
808
- def to_hash
809
- @fixture
800
+ fixture[key]
810
801
  end
811
802
 
812
- def key_list
813
- @fixture.keys.map { |column_name| @connection.quote_column_name(column_name) }.join(', ')
814
- end
815
-
816
- def value_list
817
- cols = (model_class && model_class < ActiveRecord::Base) ? model_class.columns_hash : {}
818
- @fixture.map do |key, value|
819
- @connection.quote(value, cols[key]).gsub('[^\]\\n', "\n").gsub('[^\]\\r', "\r")
820
- end.join(', ')
821
- end
803
+ alias :to_hash :fixture
822
804
 
823
805
  def find
824
806
  if model_class
825
- model_class.find(self[model_class.primary_key])
807
+ model_class.find(fixture[model_class.primary_key])
826
808
  else
827
809
  raise FixtureClassNotFound, "No class attached to find."
828
810
  end
@@ -837,19 +819,21 @@ module ActiveRecord
837
819
  setup :setup_fixtures
838
820
  teardown :teardown_fixtures
839
821
 
840
- superclass_delegating_accessor :fixture_path
841
- superclass_delegating_accessor :fixture_table_names
842
- superclass_delegating_accessor :fixture_class_names
843
- superclass_delegating_accessor :use_transactional_fixtures
844
- superclass_delegating_accessor :use_instantiated_fixtures # true, false, or :no_instances
845
- superclass_delegating_accessor :pre_loaded_fixtures
822
+ class_attribute :fixture_path
823
+ class_attribute :fixture_table_names
824
+ class_attribute :fixture_class_names
825
+ class_attribute :use_transactional_fixtures
826
+ class_attribute :use_instantiated_fixtures # true, false, or :no_instances
827
+ class_attribute :pre_loaded_fixtures
846
828
 
847
829
  self.fixture_table_names = []
848
830
  self.use_transactional_fixtures = true
849
831
  self.use_instantiated_fixtures = false
850
832
  self.pre_loaded_fixtures = false
851
833
 
852
- self.fixture_class_names = {}
834
+ self.fixture_class_names = Hash.new do |h, table_name|
835
+ h[table_name] = Fixtures.find_table_name(table_name)
836
+ end
853
837
  end
854
838
 
855
839
  module ClassMethods
@@ -857,17 +841,17 @@ module ActiveRecord
857
841
  self.fixture_class_names = self.fixture_class_names.merge(class_names)
858
842
  end
859
843
 
860
- def fixtures(*table_names)
861
- if table_names.first == :all
862
- table_names = Dir["#{fixture_path}/**/*.{yml,csv}"]
863
- table_names.map! { |f| f[(fixture_path.size + 1)..-5] }
844
+ def fixtures(*fixture_names)
845
+ if fixture_names.first == :all
846
+ fixture_names = Dir["#{fixture_path}/**/*.{yml,csv}"]
847
+ fixture_names.map! { |f| f[(fixture_path.size + 1)..-5] }
864
848
  else
865
- table_names = table_names.flatten.map { |n| n.to_s }
849
+ fixture_names = fixture_names.flatten.map { |n| n.to_s }
866
850
  end
867
851
 
868
- self.fixture_table_names |= table_names
869
- require_fixture_classes(table_names)
870
- setup_fixture_accessors(table_names)
852
+ self.fixture_table_names |= fixture_names
853
+ require_fixture_classes(fixture_names)
854
+ setup_fixture_accessors(fixture_names)
871
855
  end
872
856
 
873
857
  def try_to_load_dependency(file_name)
@@ -882,38 +866,43 @@ module ActiveRecord
882
866
  end
883
867
  end
884
868
 
885
- def require_fixture_classes(table_names = nil)
886
- (table_names || fixture_table_names).each do |table_name|
887
- file_name = table_name.to_s
869
+ def require_fixture_classes(fixture_names = nil)
870
+ (fixture_names || fixture_table_names).each do |fixture_name|
871
+ file_name = fixture_name.to_s
888
872
  file_name = file_name.singularize if ActiveRecord::Base.pluralize_table_names
889
873
  try_to_load_dependency(file_name)
890
874
  end
891
875
  end
892
876
 
893
- def setup_fixture_accessors(table_names = nil)
894
- table_names = Array.wrap(table_names || fixture_table_names)
895
- table_names.each do |table_name|
896
- table_name = table_name.to_s.tr('./', '_')
877
+ def setup_fixture_accessors(fixture_names = nil)
878
+ fixture_names = Array.wrap(fixture_names || fixture_table_names)
879
+ methods = Module.new do
880
+ fixture_names.each do |fixture_name|
881
+ fixture_name = fixture_name.to_s.tr('./', '_')
897
882
 
898
- redefine_method(table_name) do |*fixtures|
899
- force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload
883
+ define_method(fixture_name) do |*fixtures|
884
+ force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload
900
885
 
901
- @fixture_cache[table_name] ||= {}
886
+ @fixture_cache[fixture_name] ||= {}
902
887
 
903
- instances = fixtures.map do |fixture|
904
- @fixture_cache[table_name].delete(fixture) if force_reload
888
+ instances = fixtures.map do |fixture|
889
+ @fixture_cache[fixture_name].delete(fixture) if force_reload
905
890
 
906
- if @loaded_fixtures[table_name][fixture.to_s]
907
- @fixture_cache[table_name][fixture] ||= @loaded_fixtures[table_name][fixture.to_s].find
908
- else
909
- raise StandardError, "No fixture with name '#{fixture}' found for table '#{table_name}'"
891
+ if @loaded_fixtures[fixture_name][fixture.to_s]
892
+ ActiveRecord::IdentityMap.without do
893
+ @fixture_cache[fixture_name][fixture] ||= @loaded_fixtures[fixture_name][fixture.to_s].find
894
+ end
895
+ else
896
+ raise StandardError, "No fixture with name '#{fixture}' found for table '#{fixture_name}'"
897
+ end
910
898
  end
911
- end
912
899
 
913
- instances.size == 1 ? instances.first : instances
900
+ instances.size == 1 ? instances.first : instances
901
+ end
902
+ private fixture_name
914
903
  end
915
- private table_name
916
904
  end
905
+ include methods
917
906
  end
918
907
 
919
908
  def uses_transaction(*methods)
@@ -933,7 +922,7 @@ module ActiveRecord
933
922
  end
934
923
 
935
924
  def setup_fixtures
936
- return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
925
+ return unless !ActiveRecord::Base.configurations.blank?
937
926
 
938
927
  if pre_loaded_fixtures && !use_transactional_fixtures
939
928
  raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
@@ -947,7 +936,7 @@ module ActiveRecord
947
936
  if @@already_loaded_fixtures[self.class]
948
937
  @loaded_fixtures = @@already_loaded_fixtures[self.class]
949
938
  else
950
- load_fixtures
939
+ @loaded_fixtures = load_fixtures
951
940
  @@already_loaded_fixtures[self.class] = @loaded_fixtures
952
941
  end
953
942
  ActiveRecord::Base.connection.increment_open_transactions
@@ -957,7 +946,7 @@ module ActiveRecord
957
946
  else
958
947
  Fixtures.reset_cache
959
948
  @@already_loaded_fixtures[self.class] = nil
960
- load_fixtures
949
+ @loaded_fixtures = load_fixtures
961
950
  end
962
951
 
963
952
  # Instantiate fixtures for every test if requested.
@@ -981,15 +970,8 @@ module ActiveRecord
981
970
 
982
971
  private
983
972
  def load_fixtures
984
- @loaded_fixtures = {}
985
973
  fixtures = Fixtures.create_fixtures(fixture_path, fixture_table_names, fixture_class_names)
986
- unless fixtures.nil?
987
- if fixtures.instance_of?(Fixtures)
988
- @loaded_fixtures[fixtures.name] = fixtures
989
- else
990
- fixtures.each { |f| @loaded_fixtures[f.name] = f }
991
- end
992
- end
974
+ Hash[fixtures.map { |f| [f.name, f] }]
993
975
  end
994
976
 
995
977
  # for pre_loaded_fixtures, only require the classes once. huge speed improvement
@@ -1005,8 +987,8 @@ module ActiveRecord
1005
987
  Fixtures.instantiate_all_loaded_fixtures(self, load_instances?)
1006
988
  else
1007
989
  raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
1008
- @loaded_fixtures.each do |table_name, fixtures|
1009
- Fixtures.instantiate_fixtures(self, table_name, fixtures, load_instances?)
990
+ @loaded_fixtures.each do |fixture_name, fixtures|
991
+ Fixtures.instantiate_fixtures(self, fixture_name, fixtures, load_instances?)
1010
992
  end
1011
993
  end
1012
994
  end