activerecord 3.2.22.4 → 4.0.13
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2799 -617
- data/MIT-LICENSE +1 -1
- data/README.rdoc +23 -32
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +40 -34
- data/lib/active_record/association_relation.rb +22 -0
- data/lib/active_record/associations/alias_tracker.rb +4 -2
- data/lib/active_record/associations/association.rb +60 -46
- data/lib/active_record/associations/association_scope.rb +46 -40
- data/lib/active_record/associations/belongs_to_association.rb +17 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
- data/lib/active_record/associations/builder/association.rb +81 -28
- data/lib/active_record/associations/builder/belongs_to.rb +73 -56
- data/lib/active_record/associations/builder/collection_association.rb +54 -40
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -64
- data/lib/active_record/associations/builder/has_one.rb +13 -50
- data/lib/active_record/associations/builder/singular_association.rb +13 -13
- data/lib/active_record/associations/collection_association.rb +130 -96
- data/lib/active_record/associations/collection_proxy.rb +916 -63
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +15 -13
- data/lib/active_record/associations/has_many_association.rb +35 -8
- data/lib/active_record/associations/has_many_through_association.rb +37 -17
- data/lib/active_record/associations/has_one_association.rb +42 -19
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -22
- data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
- data/lib/active_record/associations/join_dependency/join_part.rb +21 -8
- data/lib/active_record/associations/join_dependency.rb +30 -9
- data/lib/active_record/associations/join_helper.rb +1 -11
- data/lib/active_record/associations/preloader/association.rb +29 -33
- data/lib/active_record/associations/preloader/collection_association.rb +1 -1
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
- data/lib/active_record/associations/preloader/has_one.rb +1 -1
- data/lib/active_record/associations/preloader/through_association.rb +13 -17
- data/lib/active_record/associations/preloader.rb +20 -43
- data/lib/active_record/associations/singular_association.rb +11 -11
- data/lib/active_record/associations/through_association.rb +3 -3
- data/lib/active_record/associations.rb +223 -282
- data/lib/active_record/attribute_assignment.rb +134 -154
- data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
- data/lib/active_record/attribute_methods/dirty.rb +36 -29
- data/lib/active_record/attribute_methods/primary_key.rb +45 -31
- data/lib/active_record/attribute_methods/query.rb +5 -4
- data/lib/active_record/attribute_methods/read.rb +67 -90
- data/lib/active_record/attribute_methods/serialization.rb +133 -70
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +51 -45
- data/lib/active_record/attribute_methods/write.rb +34 -39
- data/lib/active_record/attribute_methods.rb +268 -108
- data/lib/active_record/autosave_association.rb +80 -73
- data/lib/active_record/base.rb +54 -451
- data/lib/active_record/callbacks.rb +60 -22
- data/lib/active_record/coders/yaml_column.rb +18 -21
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +347 -197
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +146 -138
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +25 -19
- data/lib/active_record/connection_adapters/abstract/quoting.rb +19 -3
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +151 -142
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +499 -217
- data/lib/active_record/connection_adapters/abstract/transaction.rb +208 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +209 -44
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +169 -61
- data/lib/active_record/connection_adapters/column.rb +67 -36
- data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +28 -29
- data/lib/active_record/connection_adapters/mysql_adapter.rb +200 -73
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +98 -0
- data/lib/active_record/connection_adapters/postgresql/cast.rb +160 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +240 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +374 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +183 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +508 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +544 -899
- data/lib/active_record/connection_adapters/schema_cache.rb +76 -16
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +595 -16
- data/lib/active_record/connection_handling.rb +98 -0
- data/lib/active_record/core.rb +472 -0
- data/lib/active_record/counter_cache.rb +107 -108
- data/lib/active_record/dynamic_matchers.rb +115 -63
- data/lib/active_record/errors.rb +36 -18
- data/lib/active_record/explain.rb +15 -63
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +8 -4
- data/lib/active_record/fixture_set/file.rb +55 -0
- data/lib/active_record/fixtures.rb +159 -155
- data/lib/active_record/inheritance.rb +93 -59
- data/lib/active_record/integration.rb +8 -8
- data/lib/active_record/locale/en.yml +8 -1
- data/lib/active_record/locking/optimistic.rb +39 -43
- data/lib/active_record/locking/pessimistic.rb +4 -4
- data/lib/active_record/log_subscriber.rb +19 -9
- data/lib/active_record/migration/command_recorder.rb +102 -33
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/migration.rb +411 -173
- data/lib/active_record/model_schema.rb +81 -94
- data/lib/active_record/nested_attributes.rb +173 -131
- data/lib/active_record/null_relation.rb +67 -0
- data/lib/active_record/persistence.rb +254 -106
- data/lib/active_record/query_cache.rb +18 -36
- data/lib/active_record/querying.rb +19 -15
- data/lib/active_record/railtie.rb +113 -38
- data/lib/active_record/railties/console_sandbox.rb +3 -4
- data/lib/active_record/railties/controller_runtime.rb +4 -3
- data/lib/active_record/railties/databases.rake +115 -368
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +7 -3
- data/lib/active_record/reflection.rb +110 -61
- data/lib/active_record/relation/batches.rb +29 -29
- data/lib/active_record/relation/calculations.rb +155 -125
- data/lib/active_record/relation/delegation.rb +94 -18
- data/lib/active_record/relation/finder_methods.rb +151 -203
- data/lib/active_record/relation/merger.rb +188 -0
- data/lib/active_record/relation/predicate_builder.rb +85 -42
- data/lib/active_record/relation/query_methods.rb +793 -146
- data/lib/active_record/relation/spawn_methods.rb +43 -150
- data/lib/active_record/relation.rb +293 -173
- data/lib/active_record/result.rb +48 -7
- data/lib/active_record/runtime_registry.rb +17 -0
- data/lib/active_record/sanitization.rb +41 -54
- data/lib/active_record/schema.rb +19 -12
- data/lib/active_record/schema_dumper.rb +41 -41
- data/lib/active_record/schema_migration.rb +46 -0
- data/lib/active_record/scoping/default.rb +56 -52
- data/lib/active_record/scoping/named.rb +78 -103
- data/lib/active_record/scoping.rb +54 -124
- data/lib/active_record/serialization.rb +6 -2
- data/lib/active_record/serializers/xml_serializer.rb +9 -15
- data/lib/active_record/statement_cache.rb +26 -0
- data/lib/active_record/store.rb +131 -15
- data/lib/active_record/tasks/database_tasks.rb +204 -0
- data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +144 -0
- data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
- data/lib/active_record/test_case.rb +67 -38
- data/lib/active_record/timestamp.rb +16 -11
- data/lib/active_record/transactions.rb +73 -51
- data/lib/active_record/validations/associated.rb +19 -13
- data/lib/active_record/validations/presence.rb +65 -0
- data/lib/active_record/validations/uniqueness.rb +110 -57
- data/lib/active_record/validations.rb +18 -17
- data/lib/active_record/version.rb +7 -6
- data/lib/active_record.rb +63 -45
- data/lib/rails/generators/active_record/migration/migration_generator.rb +45 -8
- data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
- data/lib/rails/generators/active_record/model/model_generator.rb +5 -4
- data/lib/rails/generators/active_record/model/templates/model.rb +4 -6
- data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
- data/lib/rails/generators/active_record.rb +3 -5
- metadata +43 -29
- data/examples/associations.png +0 -0
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
- data/lib/active_record/dynamic_finder_match.rb +0 -68
- data/lib/active_record/dynamic_scope_match.rb +0 -23
- data/lib/active_record/fixtures/file.rb +0 -65
- data/lib/active_record/identity_map.rb +0 -162
- data/lib/active_record/observer.rb +0 -121
- data/lib/active_record/session_store.rb +0 -360
- data/lib/rails/generators/active_record/migration.rb +0 -15
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,11 +1,15 @@
|
|
1
1
|
require 'active_support/notifications'
|
2
|
+
require 'active_record/explain_registry'
|
2
3
|
|
3
4
|
module ActiveRecord
|
4
5
|
class ExplainSubscriber # :nodoc:
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def start(name, id, payload)
|
7
|
+
# unused
|
8
|
+
end
|
9
|
+
|
10
|
+
def finish(name, id, payload)
|
11
|
+
if ExplainRegistry.collect? && !ignore_payload?(payload)
|
12
|
+
ExplainRegistry.queries << payload.values_at(:sql, :binds)
|
9
13
|
end
|
10
14
|
end
|
11
15
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module ActiveRecord
|
5
|
+
class FixtureSet
|
6
|
+
class File # :nodoc:
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
##
|
10
|
+
# Open a fixture file named +file+. When called with a block, the block
|
11
|
+
# is called with the filehandle and the filehandle is automatically closed
|
12
|
+
# when the block finishes.
|
13
|
+
def self.open(file)
|
14
|
+
x = new file
|
15
|
+
block_given? ? yield(x) : x
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(file)
|
19
|
+
@file = file
|
20
|
+
@rows = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def each(&block)
|
24
|
+
rows.each(&block)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
private
|
29
|
+
def rows
|
30
|
+
return @rows if @rows
|
31
|
+
|
32
|
+
begin
|
33
|
+
data = YAML.load(render(IO.read(@file)))
|
34
|
+
rescue ArgumentError, Psych::SyntaxError => error
|
35
|
+
raise Fixture::FormatError, "a YAML error occurred parsing #{@file}. 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
|
36
|
+
end
|
37
|
+
@rows = data ? validate(data).to_a : []
|
38
|
+
end
|
39
|
+
|
40
|
+
def render(content)
|
41
|
+
ERB.new(content).result
|
42
|
+
end
|
43
|
+
|
44
|
+
# Validate our unmarshalled data.
|
45
|
+
def validate(data)
|
46
|
+
unless Hash === data || YAML::Omap === data
|
47
|
+
raise Fixture::FormatError, 'fixture is not a hash'
|
48
|
+
end
|
49
|
+
|
50
|
+
raise Fixture::FormatError unless data.all? { |name, row| Hash === row }
|
51
|
+
data
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,28 +1,14 @@
|
|
1
1
|
require 'erb'
|
2
|
-
|
3
|
-
begin
|
4
|
-
require 'psych'
|
5
|
-
rescue LoadError
|
6
|
-
end
|
7
|
-
|
8
2
|
require 'yaml'
|
9
3
|
require 'zlib'
|
10
4
|
require 'active_support/dependencies'
|
11
|
-
require '
|
12
|
-
require '
|
13
|
-
require 'active_support/core_ext/logger'
|
14
|
-
require 'active_support/ordered_hash'
|
15
|
-
require 'active_record/fixtures/file'
|
5
|
+
require 'active_record/fixture_set/file'
|
6
|
+
require 'active_record/errors'
|
16
7
|
|
17
|
-
|
8
|
+
module ActiveRecord
|
18
9
|
class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
|
19
10
|
end
|
20
|
-
else
|
21
|
-
class FixtureClassNotFound < StandardError #:nodoc:
|
22
|
-
end
|
23
|
-
end
|
24
11
|
|
25
|
-
module ActiveRecord
|
26
12
|
# \Fixtures are a way of organizing data that you want to test against; in short, sample data.
|
27
13
|
#
|
28
14
|
# They are stored in YAML files, one file per model, which are placed in the directory
|
@@ -96,7 +82,7 @@ module ActiveRecord
|
|
96
82
|
# end
|
97
83
|
#
|
98
84
|
# test "find_alt_method_2" do
|
99
|
-
# assert_equal "Ruby on Rails", @rubyonrails.
|
85
|
+
# assert_equal "Ruby on Rails", @rubyonrails.name
|
100
86
|
# end
|
101
87
|
#
|
102
88
|
# In order to use these methods to access fixtured data within your testcases, you must specify one of the
|
@@ -262,7 +248,7 @@ module ActiveRecord
|
|
262
248
|
#
|
263
249
|
# ### in fruit.rb
|
264
250
|
#
|
265
|
-
# belongs_to :eater, :
|
251
|
+
# belongs_to :eater, polymorphic: true
|
266
252
|
#
|
267
253
|
# ### in fruits.yml
|
268
254
|
#
|
@@ -364,8 +350,8 @@ module ActiveRecord
|
|
364
350
|
# to the rescue:
|
365
351
|
#
|
366
352
|
# george_reginald:
|
367
|
-
# monkey_id: <%= ActiveRecord::
|
368
|
-
# pirate_id: <%= ActiveRecord::
|
353
|
+
# monkey_id: <%= ActiveRecord::FixtureSet.identify(:reginald) %>
|
354
|
+
# pirate_id: <%= ActiveRecord::FixtureSet.identify(:george) %>
|
369
355
|
#
|
370
356
|
# == Support for YAML defaults
|
371
357
|
#
|
@@ -377,22 +363,38 @@ module ActiveRecord
|
|
377
363
|
#
|
378
364
|
# first:
|
379
365
|
# name: Smurf
|
380
|
-
# *DEFAULTS
|
366
|
+
# <<: *DEFAULTS
|
381
367
|
#
|
382
368
|
# second:
|
383
369
|
# name: Fraggle
|
384
|
-
# *DEFAULTS
|
370
|
+
# <<: *DEFAULTS
|
385
371
|
#
|
386
372
|
# Any fixture labeled "DEFAULTS" is safely ignored.
|
387
|
-
class
|
373
|
+
class FixtureSet
|
374
|
+
#--
|
375
|
+
# An instance of FixtureSet is normally stored in a single YAML file and possibly in a folder with the same name.
|
376
|
+
#++
|
377
|
+
|
388
378
|
MAX_ID = 2 ** 30 - 1
|
389
379
|
|
390
380
|
@@all_cached_fixtures = Hash.new { |h,k| h[k] = {} }
|
391
381
|
|
392
|
-
def self.find_table_name(
|
382
|
+
def self.find_table_name(fixture_set_name) # :nodoc:
|
383
|
+
ActiveSupport::Deprecation.warn(
|
384
|
+
"ActiveRecord::Fixtures.find_table_name is deprecated and shall be removed from future releases. Use ActiveRecord::Fixtures.default_fixture_model_name instead.")
|
385
|
+
default_fixture_model_name(fixture_set_name)
|
386
|
+
end
|
387
|
+
|
388
|
+
def self.default_fixture_model_name(fixture_set_name) # :nodoc:
|
393
389
|
ActiveRecord::Base.pluralize_table_names ?
|
394
|
-
|
395
|
-
|
390
|
+
fixture_set_name.singularize.camelize :
|
391
|
+
fixture_set_name.camelize
|
392
|
+
end
|
393
|
+
|
394
|
+
def self.default_fixture_table_name(fixture_set_name) # :nodoc:
|
395
|
+
"#{ ActiveRecord::Base.table_name_prefix }"\
|
396
|
+
"#{ fixture_set_name.tr('/', '_') }"\
|
397
|
+
"#{ ActiveRecord::Base.table_name_suffix }".to_sym
|
396
398
|
end
|
397
399
|
|
398
400
|
def self.reset_cache
|
@@ -419,11 +421,7 @@ module ActiveRecord
|
|
419
421
|
cache_for_connection(connection).update(fixtures_map)
|
420
422
|
end
|
421
423
|
|
422
|
-
|
423
|
-
# TODO:NOTE: in the next version, the __with_new_arity suffix and
|
424
|
-
# the method with the old arity will be removed.
|
425
|
-
#++
|
426
|
-
def self.instantiate_fixtures__with_new_arity(object, fixture_set, load_instances = true) # :nodoc:
|
424
|
+
def self.instantiate_fixtures(object, fixture_set, load_instances = true)
|
427
425
|
if load_instances
|
428
426
|
fixture_set.each do |fixture_name, fixture|
|
429
427
|
begin
|
@@ -435,79 +433,60 @@ module ActiveRecord
|
|
435
433
|
end
|
436
434
|
end
|
437
435
|
|
438
|
-
# The use with parameters <tt>(object, fixture_set_name, fixture_set, load_instances = true)</tt> is deprecated, +fixture_set_name+ parameter is not used.
|
439
|
-
# Use as:
|
440
|
-
#
|
441
|
-
# instantiate_fixtures(object, fixture_set, load_instances = true)
|
442
|
-
def self.instantiate_fixtures(object, fixture_set, load_instances = true, rails_3_2_compatibility_argument = true)
|
443
|
-
unless load_instances == true || load_instances == false
|
444
|
-
ActiveSupport::Deprecation.warn(
|
445
|
-
"ActiveRecord::Fixtures.instantiate_fixtures with parameters (object, fixture_set_name, fixture_set, load_instances = true) is deprecated and shall be removed from future releases. Use it with parameters (object, fixture_set, load_instances = true) instead (skip fixture_set_name).",
|
446
|
-
caller)
|
447
|
-
fixture_set = load_instances
|
448
|
-
load_instances = rails_3_2_compatibility_argument
|
449
|
-
end
|
450
|
-
instantiate_fixtures__with_new_arity(object, fixture_set, load_instances)
|
451
|
-
end
|
452
|
-
|
453
436
|
def self.instantiate_all_loaded_fixtures(object, load_instances = true)
|
454
437
|
all_loaded_fixtures.each_value do |fixture_set|
|
455
|
-
|
438
|
+
instantiate_fixtures(object, fixture_set, load_instances)
|
456
439
|
end
|
457
440
|
end
|
458
441
|
|
459
442
|
cattr_accessor :all_loaded_fixtures
|
460
443
|
self.all_loaded_fixtures = {}
|
461
444
|
|
462
|
-
def self.create_fixtures(fixtures_directory,
|
463
|
-
|
464
|
-
|
465
|
-
class_names[n.tr('/', '_').to_sym] = n.classify if n.include?('/')
|
466
|
-
}
|
445
|
+
def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {})
|
446
|
+
fixture_set_names = Array(fixture_set_names).map(&:to_s)
|
447
|
+
class_names = class_names.stringify_keys
|
467
448
|
|
468
449
|
# FIXME: Apparently JK uses this.
|
469
450
|
connection = block_given? ? yield : ActiveRecord::Base.connection
|
470
451
|
|
471
|
-
files_to_read =
|
472
|
-
fixture_is_cached?(connection,
|
452
|
+
files_to_read = fixture_set_names.reject { |fs_name|
|
453
|
+
fixture_is_cached?(connection, fs_name)
|
473
454
|
}
|
474
455
|
|
475
456
|
unless files_to_read.empty?
|
476
457
|
connection.disable_referential_integrity do
|
477
458
|
fixtures_map = {}
|
478
459
|
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
fixtures_map[path] = ActiveRecord::Fixtures.new(
|
460
|
+
fixture_sets = files_to_read.map do |fs_name|
|
461
|
+
fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new
|
483
462
|
connection,
|
484
|
-
|
485
|
-
class_names[
|
486
|
-
::File.join(fixtures_directory,
|
463
|
+
fs_name,
|
464
|
+
class_names[fs_name] || default_fixture_model_name(fs_name),
|
465
|
+
::File.join(fixtures_directory, fs_name))
|
487
466
|
end
|
488
467
|
|
489
468
|
all_loaded_fixtures.update(fixtures_map)
|
490
469
|
|
491
470
|
connection.transaction(:requires_new => true) do
|
492
|
-
|
493
|
-
conn =
|
494
|
-
table_rows =
|
471
|
+
fixture_sets.each do |fs|
|
472
|
+
conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
|
473
|
+
table_rows = fs.table_rows
|
495
474
|
|
496
475
|
table_rows.keys.each do |table|
|
497
476
|
conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
|
498
477
|
end
|
499
478
|
|
500
|
-
table_rows.each do |
|
479
|
+
table_rows.each do |fixture_set_name, rows|
|
501
480
|
rows.each do |row|
|
502
|
-
conn.insert_fixture(row,
|
481
|
+
conn.insert_fixture(row, fixture_set_name)
|
503
482
|
end
|
504
483
|
end
|
505
484
|
end
|
506
485
|
|
507
486
|
# Cap primary key sequences to max(pk).
|
508
487
|
if connection.respond_to?(:reset_pk_sequence!)
|
509
|
-
|
510
|
-
connection.reset_pk_sequence!(table_name
|
488
|
+
fixture_sets.each do |fs|
|
489
|
+
connection.reset_pk_sequence!(fs.table_name)
|
511
490
|
end
|
512
491
|
end
|
513
492
|
end
|
@@ -515,7 +494,7 @@ module ActiveRecord
|
|
515
494
|
cache_fixtures(connection, fixtures_map)
|
516
495
|
end
|
517
496
|
end
|
518
|
-
cached_fixtures(connection,
|
497
|
+
cached_fixtures(connection, fixture_set_names)
|
519
498
|
end
|
520
499
|
|
521
500
|
# Returns a consistent, platform-independent identifier for +label+.
|
@@ -526,25 +505,24 @@ module ActiveRecord
|
|
526
505
|
|
527
506
|
attr_reader :table_name, :name, :fixtures, :model_class
|
528
507
|
|
529
|
-
def initialize(connection,
|
530
|
-
@
|
531
|
-
@
|
532
|
-
@
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
@fixtures = ActiveSupport::OrderedHash.new
|
537
|
-
@table_name = "#{ActiveRecord::Base.table_name_prefix}#{@table_name}#{ActiveRecord::Base.table_name_suffix}"
|
538
|
-
|
539
|
-
# Should be an AR::Base type class
|
540
|
-
if class_name.is_a?(Class)
|
541
|
-
@table_name = class_name.table_name
|
542
|
-
@connection = class_name.connection
|
543
|
-
@model_class = class_name
|
508
|
+
def initialize(connection, name, class_name, path)
|
509
|
+
@fixtures = {} # Ordered hash
|
510
|
+
@name = name
|
511
|
+
@path = path
|
512
|
+
|
513
|
+
if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
|
514
|
+
@model_class = class_name
|
544
515
|
else
|
545
|
-
@model_class
|
516
|
+
@model_class = class_name.constantize rescue nil
|
546
517
|
end
|
547
518
|
|
519
|
+
@connection = ( model_class.respond_to?(:connection) ?
|
520
|
+
model_class.connection : connection )
|
521
|
+
|
522
|
+
@table_name = ( model_class.respond_to?(:table_name) ?
|
523
|
+
model_class.table_name :
|
524
|
+
self.class.default_fixture_table_name(name) )
|
525
|
+
|
548
526
|
read_fixture_files
|
549
527
|
end
|
550
528
|
|
@@ -582,19 +560,19 @@ module ActiveRecord
|
|
582
560
|
if model_class && model_class < ActiveRecord::Base
|
583
561
|
# fill in timestamp columns if they aren't specified and the model is set to record_timestamps
|
584
562
|
if model_class.record_timestamps
|
585
|
-
timestamp_column_names.each do |
|
586
|
-
row[
|
563
|
+
timestamp_column_names.each do |c_name|
|
564
|
+
row[c_name] = now unless row.key?(c_name)
|
587
565
|
end
|
588
566
|
end
|
589
567
|
|
590
568
|
# interpolate the fixture label
|
591
569
|
row.each do |key, value|
|
592
|
-
row[key] = label if value
|
570
|
+
row[key] = label if value == "$LABEL"
|
593
571
|
end
|
594
572
|
|
595
573
|
# generate a primary key if necessary
|
596
574
|
if has_primary_key_column? && !row.include?(primary_key_name)
|
597
|
-
row[primary_key_name] = ActiveRecord::
|
575
|
+
row[primary_key_name] = ActiveRecord::FixtureSet.identify(label)
|
598
576
|
end
|
599
577
|
|
600
578
|
# If STI is used, find the correct subclass for association reflection
|
@@ -617,15 +595,15 @@ module ActiveRecord
|
|
617
595
|
row[association.foreign_type] = $1
|
618
596
|
end
|
619
597
|
|
620
|
-
row[fk_name] = ActiveRecord::
|
598
|
+
row[fk_name] = ActiveRecord::FixtureSet.identify(value)
|
621
599
|
end
|
622
600
|
when :has_and_belongs_to_many
|
623
601
|
if (targets = row.delete(association.name.to_s))
|
624
602
|
targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
|
625
|
-
table_name = association.
|
603
|
+
table_name = association.join_table
|
626
604
|
rows[table_name].concat targets.map { |target|
|
627
605
|
{ association.foreign_key => row[primary_key_name],
|
628
|
-
association.association_foreign_key => ActiveRecord::
|
606
|
+
association.association_foreign_key => ActiveRecord::FixtureSet.identify(target) }
|
629
607
|
}
|
630
608
|
end
|
631
609
|
end
|
@@ -661,25 +639,31 @@ module ActiveRecord
|
|
661
639
|
end
|
662
640
|
|
663
641
|
def read_fixture_files
|
664
|
-
yaml_files = Dir["#{@
|
642
|
+
yaml_files = Dir["#{@path}/{**,*}/*.yml"].select { |f|
|
665
643
|
::File.file?(f)
|
666
644
|
} + [yaml_file_path]
|
667
645
|
|
668
646
|
yaml_files.each do |file|
|
669
|
-
|
670
|
-
fh.each do |
|
671
|
-
fixtures[
|
647
|
+
FixtureSet::File.open(file) do |fh|
|
648
|
+
fh.each do |fixture_name, row|
|
649
|
+
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
|
672
650
|
end
|
673
651
|
end
|
674
652
|
end
|
675
653
|
end
|
676
654
|
|
677
655
|
def yaml_file_path
|
678
|
-
"#{@
|
656
|
+
"#{@path}.yml"
|
679
657
|
end
|
680
658
|
|
681
659
|
end
|
682
660
|
|
661
|
+
#--
|
662
|
+
# Deprecate 'Fixtures' in favor of 'FixtureSet'.
|
663
|
+
#++
|
664
|
+
# :nodoc:
|
665
|
+
Fixtures = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActiveRecord::Fixtures', 'ActiveRecord::FixtureSet')
|
666
|
+
|
683
667
|
class Fixture #:nodoc:
|
684
668
|
include Enumerable
|
685
669
|
|
@@ -712,7 +696,7 @@ module ActiveRecord
|
|
712
696
|
|
713
697
|
def find
|
714
698
|
if model_class
|
715
|
-
model_class.find(fixture[model_class.primary_key])
|
699
|
+
model_class.unscoped.find(fixture[model_class.primary_key])
|
716
700
|
else
|
717
701
|
raise FixtureClassNotFound, "No class attached to find."
|
718
702
|
end
|
@@ -724,15 +708,22 @@ module ActiveRecord
|
|
724
708
|
module TestFixtures
|
725
709
|
extend ActiveSupport::Concern
|
726
710
|
|
727
|
-
|
728
|
-
|
729
|
-
|
711
|
+
def before_setup
|
712
|
+
setup_fixtures
|
713
|
+
super
|
714
|
+
end
|
730
715
|
|
731
|
-
|
716
|
+
def after_teardown
|
717
|
+
super
|
718
|
+
teardown_fixtures
|
719
|
+
end
|
720
|
+
|
721
|
+
included do
|
722
|
+
class_attribute :fixture_path, :instance_writer => false
|
732
723
|
class_attribute :fixture_table_names
|
733
724
|
class_attribute :fixture_class_names
|
734
725
|
class_attribute :use_transactional_fixtures
|
735
|
-
class_attribute :use_instantiated_fixtures
|
726
|
+
class_attribute :use_instantiated_fixtures # true, false, or :no_instances
|
736
727
|
class_attribute :pre_loaded_fixtures
|
737
728
|
|
738
729
|
self.fixture_table_names = []
|
@@ -740,34 +731,48 @@ module ActiveRecord
|
|
740
731
|
self.use_instantiated_fixtures = false
|
741
732
|
self.pre_loaded_fixtures = false
|
742
733
|
|
743
|
-
self.fixture_class_names = Hash.new do |h,
|
744
|
-
h[
|
734
|
+
self.fixture_class_names = Hash.new do |h, fixture_set_name|
|
735
|
+
h[fixture_set_name] = ActiveRecord::FixtureSet.default_fixture_model_name(fixture_set_name)
|
745
736
|
end
|
746
737
|
end
|
747
738
|
|
748
739
|
module ClassMethods
|
740
|
+
# Sets the model class for a fixture when the class name cannot be inferred from the fixture name.
|
741
|
+
#
|
742
|
+
# Examples:
|
743
|
+
#
|
744
|
+
# set_fixture_class some_fixture: SomeModel,
|
745
|
+
# 'namespaced/fixture' => Another::Model
|
746
|
+
#
|
747
|
+
# The keys must be the fixture names, that coincide with the short paths to the fixture files.
|
748
|
+
#--
|
749
|
+
# It is also possible to pass the class name instead of the class:
|
750
|
+
# set_fixture_class 'some_fixture' => 'SomeModel'
|
751
|
+
# I think this option is redundant, i propose to deprecate it.
|
752
|
+
# Isn't it easier to always pass the class itself?
|
753
|
+
# (2011-12-20 alexeymuranov)
|
754
|
+
#++
|
749
755
|
def set_fixture_class(class_names = {})
|
750
|
-
self.fixture_class_names = self.fixture_class_names.merge(class_names)
|
756
|
+
self.fixture_class_names = self.fixture_class_names.merge(class_names.stringify_keys)
|
751
757
|
end
|
752
758
|
|
753
|
-
def fixtures(*
|
754
|
-
if
|
755
|
-
|
756
|
-
|
759
|
+
def fixtures(*fixture_set_names)
|
760
|
+
if fixture_set_names.first == :all
|
761
|
+
fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
|
762
|
+
fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
|
757
763
|
else
|
758
|
-
|
764
|
+
fixture_set_names = fixture_set_names.flatten.map { |n| n.to_s }
|
759
765
|
end
|
760
766
|
|
761
|
-
self.fixture_table_names |=
|
762
|
-
require_fixture_classes(
|
763
|
-
setup_fixture_accessors(
|
767
|
+
self.fixture_table_names |= fixture_set_names
|
768
|
+
require_fixture_classes(fixture_set_names)
|
769
|
+
setup_fixture_accessors(fixture_set_names)
|
764
770
|
end
|
765
771
|
|
766
772
|
def try_to_load_dependency(file_name)
|
767
773
|
require_dependency file_name
|
768
774
|
rescue LoadError => e
|
769
|
-
# Let's hope the developer has included it
|
770
|
-
|
775
|
+
# Let's hope the developer has included it
|
771
776
|
# Let's warn in case this is a subdependency, otherwise
|
772
777
|
# subdependency error messages are totally cryptic
|
773
778
|
if ActiveRecord::Base.logger
|
@@ -775,40 +780,45 @@ module ActiveRecord
|
|
775
780
|
end
|
776
781
|
end
|
777
782
|
|
778
|
-
def require_fixture_classes(
|
779
|
-
|
780
|
-
|
783
|
+
def require_fixture_classes(fixture_set_names = nil)
|
784
|
+
if fixture_set_names
|
785
|
+
fixture_set_names = fixture_set_names.map { |n| n.to_s }
|
786
|
+
else
|
787
|
+
fixture_set_names = fixture_table_names
|
788
|
+
end
|
789
|
+
|
790
|
+
fixture_set_names.each do |file_name|
|
781
791
|
file_name = file_name.singularize if ActiveRecord::Base.pluralize_table_names
|
782
792
|
try_to_load_dependency(file_name)
|
783
793
|
end
|
784
794
|
end
|
785
795
|
|
786
|
-
def setup_fixture_accessors(
|
787
|
-
|
796
|
+
def setup_fixture_accessors(fixture_set_names = nil)
|
797
|
+
fixture_set_names = Array(fixture_set_names || fixture_table_names)
|
788
798
|
methods = Module.new do
|
789
|
-
|
790
|
-
|
799
|
+
fixture_set_names.each do |fs_name|
|
800
|
+
fs_name = fs_name.to_s
|
801
|
+
accessor_name = fs_name.tr('/', '_').to_sym
|
791
802
|
|
792
|
-
define_method(
|
793
|
-
force_reload =
|
803
|
+
define_method(accessor_name) do |*fixture_names|
|
804
|
+
force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
|
794
805
|
|
795
|
-
@fixture_cache[
|
806
|
+
@fixture_cache[fs_name] ||= {}
|
796
807
|
|
797
|
-
instances =
|
798
|
-
|
808
|
+
instances = fixture_names.map do |f_name|
|
809
|
+
f_name = f_name.to_s
|
810
|
+
@fixture_cache[fs_name].delete(f_name) if force_reload
|
799
811
|
|
800
|
-
if @loaded_fixtures[
|
801
|
-
|
802
|
-
@fixture_cache[fixture_name][fixture] ||= @loaded_fixtures[fixture_name][fixture.to_s].find
|
803
|
-
end
|
812
|
+
if @loaded_fixtures[fs_name][f_name]
|
813
|
+
@fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
|
804
814
|
else
|
805
|
-
raise StandardError, "No fixture
|
815
|
+
raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
|
806
816
|
end
|
807
817
|
end
|
808
818
|
|
809
819
|
instances.size == 1 ? instances.first : instances
|
810
820
|
end
|
811
|
-
private
|
821
|
+
private accessor_name
|
812
822
|
end
|
813
823
|
end
|
814
824
|
include methods
|
@@ -831,7 +841,7 @@ module ActiveRecord
|
|
831
841
|
end
|
832
842
|
|
833
843
|
def setup_fixtures
|
834
|
-
return
|
844
|
+
return if ActiveRecord::Base.configurations.blank?
|
835
845
|
|
836
846
|
if pre_loaded_fixtures && !use_transactional_fixtures
|
837
847
|
raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
|
@@ -851,13 +861,11 @@ module ActiveRecord
|
|
851
861
|
end
|
852
862
|
@fixture_connections = enlist_fixture_connections
|
853
863
|
@fixture_connections.each do |connection|
|
854
|
-
connection.
|
855
|
-
connection.transaction_joinable = false
|
856
|
-
connection.begin_db_transaction
|
864
|
+
connection.begin_transaction joinable: false
|
857
865
|
end
|
858
866
|
# Load fixtures for every test.
|
859
867
|
else
|
860
|
-
ActiveRecord::
|
868
|
+
ActiveRecord::FixtureSet.reset_cache
|
861
869
|
@@already_loaded_fixtures[self.class] = nil
|
862
870
|
@loaded_fixtures = load_fixtures
|
863
871
|
end
|
@@ -867,32 +875,28 @@ module ActiveRecord
|
|
867
875
|
end
|
868
876
|
|
869
877
|
def teardown_fixtures
|
870
|
-
return
|
871
|
-
|
872
|
-
unless run_in_transaction?
|
873
|
-
ActiveRecord::Fixtures.reset_cache
|
874
|
-
end
|
878
|
+
return if ActiveRecord::Base.configurations.blank?
|
875
879
|
|
876
880
|
# Rollback changes if a transaction is active.
|
877
881
|
if run_in_transaction?
|
878
882
|
@fixture_connections.each do |connection|
|
879
|
-
if connection.
|
880
|
-
connection.rollback_db_transaction
|
881
|
-
connection.decrement_open_transactions
|
882
|
-
end
|
883
|
+
connection.rollback_transaction if connection.transaction_open?
|
883
884
|
end
|
884
885
|
@fixture_connections.clear
|
886
|
+
else
|
887
|
+
ActiveRecord::FixtureSet.reset_cache
|
885
888
|
end
|
889
|
+
|
886
890
|
ActiveRecord::Base.clear_active_connections!
|
887
891
|
end
|
888
892
|
|
889
893
|
def enlist_fixture_connections
|
890
|
-
ActiveRecord::Base.connection_handler.
|
894
|
+
ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
|
891
895
|
end
|
892
896
|
|
893
897
|
private
|
894
898
|
def load_fixtures
|
895
|
-
fixtures = ActiveRecord::
|
899
|
+
fixtures = ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names)
|
896
900
|
Hash[fixtures.map { |f| [f.name, f] }]
|
897
901
|
end
|
898
902
|
|
@@ -901,16 +905,16 @@ module ActiveRecord
|
|
901
905
|
|
902
906
|
def instantiate_fixtures
|
903
907
|
if pre_loaded_fixtures
|
904
|
-
raise RuntimeError, 'Load fixtures before instantiating them.' if ActiveRecord::
|
908
|
+
raise RuntimeError, 'Load fixtures before instantiating them.' if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
|
905
909
|
unless @@required_fixture_classes
|
906
|
-
self.class.require_fixture_classes ActiveRecord::
|
910
|
+
self.class.require_fixture_classes ActiveRecord::FixtureSet.all_loaded_fixtures.keys
|
907
911
|
@@required_fixture_classes = true
|
908
912
|
end
|
909
|
-
ActiveRecord::
|
913
|
+
ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
|
910
914
|
else
|
911
915
|
raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
|
912
916
|
@loaded_fixtures.each_value do |fixture_set|
|
913
|
-
ActiveRecord::
|
917
|
+
ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
|
914
918
|
end
|
915
919
|
end
|
916
920
|
end
|