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.

Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2799 -617
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +23 -32
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +40 -34
  7. data/lib/active_record/association_relation.rb +22 -0
  8. data/lib/active_record/associations/alias_tracker.rb +4 -2
  9. data/lib/active_record/associations/association.rb +60 -46
  10. data/lib/active_record/associations/association_scope.rb +46 -40
  11. data/lib/active_record/associations/belongs_to_association.rb +17 -4
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  13. data/lib/active_record/associations/builder/association.rb +81 -28
  14. data/lib/active_record/associations/builder/belongs_to.rb +73 -56
  15. data/lib/active_record/associations/builder/collection_association.rb +54 -40
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -64
  18. data/lib/active_record/associations/builder/has_one.rb +13 -50
  19. data/lib/active_record/associations/builder/singular_association.rb +13 -13
  20. data/lib/active_record/associations/collection_association.rb +130 -96
  21. data/lib/active_record/associations/collection_proxy.rb +916 -63
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +15 -13
  23. data/lib/active_record/associations/has_many_association.rb +35 -8
  24. data/lib/active_record/associations/has_many_through_association.rb +37 -17
  25. data/lib/active_record/associations/has_one_association.rb +42 -19
  26. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  27. data/lib/active_record/associations/join_dependency/join_association.rb +39 -22
  28. data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
  29. data/lib/active_record/associations/join_dependency/join_part.rb +21 -8
  30. data/lib/active_record/associations/join_dependency.rb +30 -9
  31. data/lib/active_record/associations/join_helper.rb +1 -11
  32. data/lib/active_record/associations/preloader/association.rb +29 -33
  33. data/lib/active_record/associations/preloader/collection_association.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +2 -2
  35. data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
  36. data/lib/active_record/associations/preloader/has_one.rb +1 -1
  37. data/lib/active_record/associations/preloader/through_association.rb +13 -17
  38. data/lib/active_record/associations/preloader.rb +20 -43
  39. data/lib/active_record/associations/singular_association.rb +11 -11
  40. data/lib/active_record/associations/through_association.rb +3 -3
  41. data/lib/active_record/associations.rb +223 -282
  42. data/lib/active_record/attribute_assignment.rb +134 -154
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
  44. data/lib/active_record/attribute_methods/dirty.rb +36 -29
  45. data/lib/active_record/attribute_methods/primary_key.rb +45 -31
  46. data/lib/active_record/attribute_methods/query.rb +5 -4
  47. data/lib/active_record/attribute_methods/read.rb +67 -90
  48. data/lib/active_record/attribute_methods/serialization.rb +133 -70
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +51 -45
  50. data/lib/active_record/attribute_methods/write.rb +34 -39
  51. data/lib/active_record/attribute_methods.rb +268 -108
  52. data/lib/active_record/autosave_association.rb +80 -73
  53. data/lib/active_record/base.rb +54 -451
  54. data/lib/active_record/callbacks.rb +60 -22
  55. data/lib/active_record/coders/yaml_column.rb +18 -21
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +347 -197
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +146 -138
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +25 -19
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +19 -3
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +151 -142
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +499 -217
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +208 -0
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +209 -44
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +169 -61
  67. data/lib/active_record/connection_adapters/column.rb +67 -36
  68. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  69. data/lib/active_record/connection_adapters/mysql2_adapter.rb +28 -29
  70. data/lib/active_record/connection_adapters/mysql_adapter.rb +200 -73
  71. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +98 -0
  72. data/lib/active_record/connection_adapters/postgresql/cast.rb +160 -0
  73. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +240 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid.rb +374 -0
  75. data/lib/active_record/connection_adapters/postgresql/quoting.rb +183 -0
  76. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  77. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +508 -0
  78. data/lib/active_record/connection_adapters/postgresql_adapter.rb +544 -899
  79. data/lib/active_record/connection_adapters/schema_cache.rb +76 -16
  80. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +595 -16
  81. data/lib/active_record/connection_handling.rb +98 -0
  82. data/lib/active_record/core.rb +472 -0
  83. data/lib/active_record/counter_cache.rb +107 -108
  84. data/lib/active_record/dynamic_matchers.rb +115 -63
  85. data/lib/active_record/errors.rb +36 -18
  86. data/lib/active_record/explain.rb +15 -63
  87. data/lib/active_record/explain_registry.rb +30 -0
  88. data/lib/active_record/explain_subscriber.rb +8 -4
  89. data/lib/active_record/fixture_set/file.rb +55 -0
  90. data/lib/active_record/fixtures.rb +159 -155
  91. data/lib/active_record/inheritance.rb +93 -59
  92. data/lib/active_record/integration.rb +8 -8
  93. data/lib/active_record/locale/en.yml +8 -1
  94. data/lib/active_record/locking/optimistic.rb +39 -43
  95. data/lib/active_record/locking/pessimistic.rb +4 -4
  96. data/lib/active_record/log_subscriber.rb +19 -9
  97. data/lib/active_record/migration/command_recorder.rb +102 -33
  98. data/lib/active_record/migration/join_table.rb +15 -0
  99. data/lib/active_record/migration.rb +411 -173
  100. data/lib/active_record/model_schema.rb +81 -94
  101. data/lib/active_record/nested_attributes.rb +173 -131
  102. data/lib/active_record/null_relation.rb +67 -0
  103. data/lib/active_record/persistence.rb +254 -106
  104. data/lib/active_record/query_cache.rb +18 -36
  105. data/lib/active_record/querying.rb +19 -15
  106. data/lib/active_record/railtie.rb +113 -38
  107. data/lib/active_record/railties/console_sandbox.rb +3 -4
  108. data/lib/active_record/railties/controller_runtime.rb +4 -3
  109. data/lib/active_record/railties/databases.rake +115 -368
  110. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  111. data/lib/active_record/readonly_attributes.rb +7 -3
  112. data/lib/active_record/reflection.rb +110 -61
  113. data/lib/active_record/relation/batches.rb +29 -29
  114. data/lib/active_record/relation/calculations.rb +155 -125
  115. data/lib/active_record/relation/delegation.rb +94 -18
  116. data/lib/active_record/relation/finder_methods.rb +151 -203
  117. data/lib/active_record/relation/merger.rb +188 -0
  118. data/lib/active_record/relation/predicate_builder.rb +85 -42
  119. data/lib/active_record/relation/query_methods.rb +793 -146
  120. data/lib/active_record/relation/spawn_methods.rb +43 -150
  121. data/lib/active_record/relation.rb +293 -173
  122. data/lib/active_record/result.rb +48 -7
  123. data/lib/active_record/runtime_registry.rb +17 -0
  124. data/lib/active_record/sanitization.rb +41 -54
  125. data/lib/active_record/schema.rb +19 -12
  126. data/lib/active_record/schema_dumper.rb +41 -41
  127. data/lib/active_record/schema_migration.rb +46 -0
  128. data/lib/active_record/scoping/default.rb +56 -52
  129. data/lib/active_record/scoping/named.rb +78 -103
  130. data/lib/active_record/scoping.rb +54 -124
  131. data/lib/active_record/serialization.rb +6 -2
  132. data/lib/active_record/serializers/xml_serializer.rb +9 -15
  133. data/lib/active_record/statement_cache.rb +26 -0
  134. data/lib/active_record/store.rb +131 -15
  135. data/lib/active_record/tasks/database_tasks.rb +204 -0
  136. data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
  137. data/lib/active_record/tasks/mysql_database_tasks.rb +144 -0
  138. data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
  139. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  140. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  141. data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
  142. data/lib/active_record/test_case.rb +67 -38
  143. data/lib/active_record/timestamp.rb +16 -11
  144. data/lib/active_record/transactions.rb +73 -51
  145. data/lib/active_record/validations/associated.rb +19 -13
  146. data/lib/active_record/validations/presence.rb +65 -0
  147. data/lib/active_record/validations/uniqueness.rb +110 -57
  148. data/lib/active_record/validations.rb +18 -17
  149. data/lib/active_record/version.rb +7 -6
  150. data/lib/active_record.rb +63 -45
  151. data/lib/rails/generators/active_record/migration/migration_generator.rb +45 -8
  152. data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
  153. data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
  154. data/lib/rails/generators/active_record/model/model_generator.rb +5 -4
  155. data/lib/rails/generators/active_record/model/templates/model.rb +4 -6
  156. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  157. data/lib/rails/generators/active_record.rb +3 -5
  158. metadata +43 -29
  159. data/examples/associations.png +0 -0
  160. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  161. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  162. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  163. data/lib/active_record/dynamic_finder_match.rb +0 -68
  164. data/lib/active_record/dynamic_scope_match.rb +0 -23
  165. data/lib/active_record/fixtures/file.rb +0 -65
  166. data/lib/active_record/identity_map.rb +0 -162
  167. data/lib/active_record/observer.rb +0 -121
  168. data/lib/active_record/session_store.rb +0 -360
  169. data/lib/rails/generators/active_record/migration.rb +0 -15
  170. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  171. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  172. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  173. 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 call(*args)
6
- if queries = Thread.current[:available_queries_for_explain]
7
- payload = args.last
8
- queries << payload.values_at(:sql, :binds) unless ignore_payload?(payload)
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 'active_support/core_ext/array/wrap'
12
- require 'active_support/core_ext/object/blank'
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
- if defined? ActiveRecord
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.news
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, :polymorphic => true
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::Fixtures.identify(:reginald) %>
368
- # pirate_id: <%= ActiveRecord::Fixtures.identify(:george) %>
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 Fixtures
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(table_name) # :nodoc:
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
- table_name.to_s.singularize.camelize :
395
- table_name.to_s.camelize
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
- ActiveRecord::Fixtures.instantiate_fixtures(object, fixture_set, load_instances)
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, table_names, class_names = {})
463
- table_names = [table_names].flatten.map { |n| n.to_s }
464
- table_names.each { |n|
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 = table_names.reject { |table_name|
472
- fixture_is_cached?(connection, table_name)
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
- fixture_files = files_to_read.map do |path|
480
- table_name = path.tr '/', '_'
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
- table_name,
485
- class_names[table_name.to_sym] || table_name.classify,
486
- ::File.join(fixtures_directory, path))
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
- fixture_files.each do |ff|
493
- conn = ff.model_class.respond_to?(:connection) ? ff.model_class.connection : connection
494
- table_rows = ff.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 |table_name,rows|
479
+ table_rows.each do |fixture_set_name, rows|
501
480
  rows.each do |row|
502
- conn.insert_fixture(row, table_name)
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
- table_names.each do |table_name|
510
- connection.reset_pk_sequence!(table_name.tr('/', '_'))
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, table_names)
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, table_name, class_name, fixture_path)
530
- @connection = connection
531
- @table_name = table_name
532
- @fixture_path = fixture_path
533
- @name = table_name # preserve fixture base name
534
- @class_name = class_name
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 = class_name.constantize rescue nil
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 |name|
586
- row[name] = now unless row.key?(name)
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.is_a?(String) && value == "$LABEL"
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::Fixtures.identify(label)
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::Fixtures.identify(value)
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.options[:join_table]
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::Fixtures.identify(target) }
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["#{@fixture_path}/{**,*}/*.yml"].select { |f|
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
- Fixtures::File.open(file) do |fh|
670
- fh.each do |name, row|
671
- fixtures[name] = ActiveRecord::Fixture.new(row, model_class)
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
- "#{@fixture_path}.yml"
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
- included do
728
- setup :setup_fixtures
729
- teardown :teardown_fixtures
711
+ def before_setup
712
+ setup_fixtures
713
+ super
714
+ end
730
715
 
731
- class_attribute :fixture_path
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 # true, false, or :no_instances
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, table_name|
744
- h[table_name] = ActiveRecord::Fixtures.find_table_name(table_name)
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(*fixture_names)
754
- if fixture_names.first == :all
755
- fixture_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
756
- fixture_names.map! { |f| f[(fixture_path.size + 1)..-5] }
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
- fixture_names = fixture_names.flatten.map { |n| n.to_s }
764
+ fixture_set_names = fixture_set_names.flatten.map { |n| n.to_s }
759
765
  end
760
766
 
761
- self.fixture_table_names |= fixture_names
762
- require_fixture_classes(fixture_names)
763
- setup_fixture_accessors(fixture_names)
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 himself
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(fixture_names = nil)
779
- (fixture_names || fixture_table_names).each do |fixture_name|
780
- file_name = fixture_name.to_s
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(fixture_names = nil)
787
- fixture_names = Array.wrap(fixture_names || fixture_table_names)
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
- fixture_names.each do |fixture_name|
790
- fixture_name = fixture_name.to_s.tr('./', '_')
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(fixture_name) do |*fixtures|
793
- force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :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[fixture_name] ||= {}
806
+ @fixture_cache[fs_name] ||= {}
796
807
 
797
- instances = fixtures.map do |fixture|
798
- @fixture_cache[fixture_name].delete(fixture) if force_reload
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[fixture_name][fixture.to_s]
801
- ActiveRecord::IdentityMap.without do
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 with name '#{fixture}' found for table '#{fixture_name}'"
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 fixture_name
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 unless !ActiveRecord::Base.configurations.blank?
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.increment_open_transactions
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::Fixtures.reset_cache
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 unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
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.open_transactions != 0
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.connection_pools.values.map(&:connection)
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::Fixtures.create_fixtures(fixture_path, fixture_table_names, fixture_class_names)
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::Fixtures.all_loaded_fixtures.empty?
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::Fixtures.all_loaded_fixtures.keys
910
+ self.class.require_fixture_classes ActiveRecord::FixtureSet.all_loaded_fixtures.keys
907
911
  @@required_fixture_classes = true
908
912
  end
909
- ActiveRecord::Fixtures.instantiate_all_loaded_fixtures(self, load_instances?)
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::Fixtures.instantiate_fixtures(self, fixture_set, load_instances?)
917
+ ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
914
918
  end
915
919
  end
916
920
  end