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.
- data/CHANGELOG +220 -91
- data/README.rdoc +3 -3
- data/examples/performance.rb +88 -109
- data/lib/active_record.rb +6 -2
- data/lib/active_record/aggregations.rb +22 -45
- data/lib/active_record/associations.rb +264 -991
- data/lib/active_record/associations/alias_tracker.rb +85 -0
- data/lib/active_record/associations/association.rb +231 -0
- data/lib/active_record/associations/association_scope.rb +120 -0
- data/lib/active_record/associations/belongs_to_association.rb +40 -60
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +15 -63
- data/lib/active_record/associations/builder/association.rb +53 -0
- data/lib/active_record/associations/builder/belongs_to.rb +85 -0
- data/lib/active_record/associations/builder/collection_association.rb +75 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +63 -0
- data/lib/active_record/associations/builder/has_many.rb +65 -0
- data/lib/active_record/associations/builder/has_one.rb +63 -0
- data/lib/active_record/associations/builder/singular_association.rb +32 -0
- data/lib/active_record/associations/collection_association.rb +524 -0
- data/lib/active_record/associations/collection_proxy.rb +125 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +27 -118
- data/lib/active_record/associations/has_many_association.rb +50 -79
- data/lib/active_record/associations/has_many_through_association.rb +98 -67
- data/lib/active_record/associations/has_one_association.rb +45 -115
- data/lib/active_record/associations/has_one_through_association.rb +21 -25
- data/lib/active_record/associations/join_dependency.rb +215 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +150 -0
- data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
- data/lib/active_record/associations/join_helper.rb +56 -0
- data/lib/active_record/associations/preloader.rb +177 -0
- data/lib/active_record/associations/preloader/association.rb +126 -0
- data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
- data/lib/active_record/associations/preloader/collection_association.rb +24 -0
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
- data/lib/active_record/associations/preloader/has_many.rb +17 -0
- data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
- data/lib/active_record/associations/preloader/has_one.rb +23 -0
- data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
- data/lib/active_record/associations/preloader/singular_association.rb +21 -0
- data/lib/active_record/associations/preloader/through_association.rb +67 -0
- data/lib/active_record/associations/singular_association.rb +55 -0
- data/lib/active_record/associations/through_association.rb +80 -0
- data/lib/active_record/attribute_methods.rb +19 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +9 -8
- data/lib/active_record/attribute_methods/dirty.rb +8 -2
- data/lib/active_record/attribute_methods/primary_key.rb +33 -13
- data/lib/active_record/attribute_methods/read.rb +17 -17
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -4
- data/lib/active_record/attribute_methods/write.rb +2 -1
- data/lib/active_record/autosave_association.rb +66 -45
- data/lib/active_record/base.rb +445 -273
- data/lib/active_record/callbacks.rb +24 -33
- data/lib/active_record/coders/yaml_column.rb +41 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +106 -13
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +16 -2
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -12
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +16 -16
- data/lib/active_record/connection_adapters/abstract/quoting.rb +61 -22
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +16 -273
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +80 -42
- data/lib/active_record/connection_adapters/abstract_adapter.rb +44 -25
- data/lib/active_record/connection_adapters/column.rb +268 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +686 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +331 -88
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +295 -267
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +3 -7
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +108 -26
- data/lib/active_record/counter_cache.rb +7 -4
- data/lib/active_record/fixtures.rb +174 -192
- data/lib/active_record/identity_map.rb +131 -0
- data/lib/active_record/locking/optimistic.rb +20 -14
- data/lib/active_record/locking/pessimistic.rb +4 -4
- data/lib/active_record/log_subscriber.rb +24 -4
- data/lib/active_record/migration.rb +265 -144
- data/lib/active_record/migration/command_recorder.rb +103 -0
- data/lib/active_record/named_scope.rb +68 -25
- data/lib/active_record/nested_attributes.rb +58 -15
- data/lib/active_record/observer.rb +3 -7
- data/lib/active_record/persistence.rb +58 -38
- data/lib/active_record/query_cache.rb +25 -3
- data/lib/active_record/railtie.rb +21 -12
- data/lib/active_record/railties/console_sandbox.rb +6 -0
- data/lib/active_record/railties/databases.rake +147 -116
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/reflection.rb +176 -44
- data/lib/active_record/relation.rb +125 -49
- data/lib/active_record/relation/batches.rb +7 -5
- data/lib/active_record/relation/calculations.rb +50 -18
- data/lib/active_record/relation/finder_methods.rb +47 -26
- data/lib/active_record/relation/predicate_builder.rb +24 -21
- data/lib/active_record/relation/query_methods.rb +117 -101
- data/lib/active_record/relation/spawn_methods.rb +27 -20
- data/lib/active_record/result.rb +34 -0
- data/lib/active_record/schema.rb +5 -6
- data/lib/active_record/schema_dumper.rb +11 -13
- data/lib/active_record/serialization.rb +2 -2
- data/lib/active_record/serializers/xml_serializer.rb +10 -10
- data/lib/active_record/session_store.rb +8 -2
- data/lib/active_record/test_case.rb +9 -20
- data/lib/active_record/timestamp.rb +21 -9
- data/lib/active_record/transactions.rb +16 -15
- data/lib/active_record/validations.rb +21 -22
- data/lib/active_record/validations/associated.rb +3 -1
- data/lib/active_record/validations/uniqueness.rb +48 -58
- data/lib/active_record/version.rb +3 -3
- data/lib/rails/generators/active_record.rb +6 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +10 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -1
- data/lib/rails/generators/active_record/model/templates/migration.rb +6 -5
- data/lib/rails/generators/active_record/model/templates/model.rb +2 -0
- data/lib/rails/generators/active_record/model/templates/module.rb +2 -0
- data/lib/rails/generators/active_record/observer/templates/observer.rb +2 -0
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +2 -1
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +2 -2
- metadata +106 -77
- checksums.yaml +0 -7
- data/lib/active_record/association_preload.rb +0 -431
- data/lib/active_record/associations/association_collection.rb +0 -572
- data/lib/active_record/associations/association_proxy.rb +0 -304
- 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])
|
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
|
-
|
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
|
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.
|
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
|
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
|
-
|
155
|
-
|
156
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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']
|
197
|
-
|
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']
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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.
|
462
|
-
|
463
|
-
|
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
|
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
|
-
|
472
|
+
cache_for_connection(connection).values_at(*keys_to_fetch)
|
478
473
|
else
|
479
|
-
|
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,
|
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
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
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|
|
515
|
-
|
505
|
+
table_names.each { |n|
|
506
|
+
class_names[n.tr('/', '_').to_sym] = n.classify if n.include?('/')
|
507
|
+
}
|
516
508
|
|
517
|
-
|
509
|
+
# FIXME: Apparently JK uses this.
|
510
|
+
connection = block_given? ? yield : ActiveRecord::Base.connection
|
518
511
|
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
fixtures_map = {}
|
512
|
+
files_to_read = table_names.reject { |table_name|
|
513
|
+
fixture_is_cached?(connection, table_name)
|
514
|
+
}
|
523
515
|
|
524
|
-
|
525
|
-
|
526
|
-
|
516
|
+
unless files_to_read.empty?
|
517
|
+
connection.disable_referential_integrity do
|
518
|
+
fixtures_map = {}
|
527
519
|
|
528
|
-
|
520
|
+
fixture_files = files_to_read.map do |path|
|
521
|
+
table_name = path.tr '/', '_'
|
529
522
|
|
530
|
-
|
531
|
-
|
532
|
-
|
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
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
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
|
-
|
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
|
569
|
-
|
592
|
+
def [](x)
|
593
|
+
fixtures[x]
|
594
|
+
end
|
595
|
+
|
596
|
+
def []=(k,v)
|
597
|
+
fixtures[k] = v
|
570
598
|
end
|
571
599
|
|
572
|
-
def
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
626
|
-
|
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
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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}"
|
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
|
791
|
-
@
|
792
|
-
@
|
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
|
-
|
792
|
+
model_class.name if model_class
|
798
793
|
end
|
799
794
|
|
800
795
|
def each
|
801
|
-
|
796
|
+
fixture.each { |item| yield item }
|
802
797
|
end
|
803
798
|
|
804
799
|
def [](key)
|
805
|
-
|
806
|
-
end
|
807
|
-
|
808
|
-
def to_hash
|
809
|
-
@fixture
|
800
|
+
fixture[key]
|
810
801
|
end
|
811
802
|
|
812
|
-
|
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(
|
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
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
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(*
|
861
|
-
if
|
862
|
-
|
863
|
-
|
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
|
-
|
849
|
+
fixture_names = fixture_names.flatten.map { |n| n.to_s }
|
866
850
|
end
|
867
851
|
|
868
|
-
self.fixture_table_names |=
|
869
|
-
require_fixture_classes(
|
870
|
-
setup_fixture_accessors(
|
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(
|
886
|
-
(
|
887
|
-
file_name =
|
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(
|
894
|
-
|
895
|
-
|
896
|
-
|
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
|
-
|
899
|
-
|
883
|
+
define_method(fixture_name) do |*fixtures|
|
884
|
+
force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload
|
900
885
|
|
901
|
-
|
886
|
+
@fixture_cache[fixture_name] ||= {}
|
902
887
|
|
903
|
-
|
904
|
-
|
888
|
+
instances = fixtures.map do |fixture|
|
889
|
+
@fixture_cache[fixture_name].delete(fixture) if force_reload
|
905
890
|
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
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
|
-
|
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
|
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
|
-
|
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 |
|
1009
|
-
Fixtures.instantiate_fixtures(self,
|
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
|