activerecord 4.1.8 → 4.2.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (186) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1165 -1591
  3. data/README.rdoc +15 -10
  4. data/lib/active_record/aggregations.rb +15 -8
  5. data/lib/active_record/association_relation.rb +13 -0
  6. data/lib/active_record/associations/alias_tracker.rb +3 -12
  7. data/lib/active_record/associations/association.rb +16 -4
  8. data/lib/active_record/associations/association_scope.rb +84 -43
  9. data/lib/active_record/associations/belongs_to_association.rb +28 -10
  10. data/lib/active_record/associations/builder/association.rb +16 -5
  11. data/lib/active_record/associations/builder/belongs_to.rb +7 -29
  12. data/lib/active_record/associations/builder/collection_association.rb +5 -1
  13. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +9 -14
  14. data/lib/active_record/associations/builder/has_many.rb +1 -1
  15. data/lib/active_record/associations/builder/has_one.rb +2 -2
  16. data/lib/active_record/associations/builder/singular_association.rb +8 -1
  17. data/lib/active_record/associations/collection_association.rb +87 -30
  18. data/lib/active_record/associations/collection_proxy.rb +33 -35
  19. data/lib/active_record/associations/foreign_association.rb +11 -0
  20. data/lib/active_record/associations/has_many_association.rb +83 -22
  21. data/lib/active_record/associations/has_many_through_association.rb +49 -26
  22. data/lib/active_record/associations/has_one_association.rb +1 -1
  23. data/lib/active_record/associations/join_dependency/join_association.rb +25 -15
  24. data/lib/active_record/associations/join_dependency/join_part.rb +0 -1
  25. data/lib/active_record/associations/join_dependency.rb +26 -12
  26. data/lib/active_record/associations/preloader/association.rb +14 -10
  27. data/lib/active_record/associations/preloader/through_association.rb +4 -3
  28. data/lib/active_record/associations/preloader.rb +37 -26
  29. data/lib/active_record/associations/singular_association.rb +17 -2
  30. data/lib/active_record/associations/through_association.rb +16 -12
  31. data/lib/active_record/associations.rb +158 -49
  32. data/lib/active_record/attribute.rb +163 -0
  33. data/lib/active_record/attribute_assignment.rb +20 -12
  34. data/lib/active_record/attribute_decorators.rb +66 -0
  35. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
  36. data/lib/active_record/attribute_methods/dirty.rb +107 -43
  37. data/lib/active_record/attribute_methods/primary_key.rb +7 -8
  38. data/lib/active_record/attribute_methods/query.rb +1 -1
  39. data/lib/active_record/attribute_methods/read.rb +22 -59
  40. data/lib/active_record/attribute_methods/serialization.rb +16 -150
  41. data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -28
  42. data/lib/active_record/attribute_methods/write.rb +9 -24
  43. data/lib/active_record/attribute_methods.rb +57 -95
  44. data/lib/active_record/attribute_set/builder.rb +106 -0
  45. data/lib/active_record/attribute_set.rb +81 -0
  46. data/lib/active_record/attributes.rb +147 -0
  47. data/lib/active_record/autosave_association.rb +30 -12
  48. data/lib/active_record/base.rb +13 -24
  49. data/lib/active_record/callbacks.rb +6 -6
  50. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +85 -53
  51. data/lib/active_record/connection_adapters/abstract/database_statements.rb +52 -50
  52. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  53. data/lib/active_record/connection_adapters/abstract/quoting.rb +60 -60
  54. data/lib/active_record/connection_adapters/abstract/savepoints.rb +1 -1
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +39 -4
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +139 -57
  57. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -34
  58. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +271 -74
  59. data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -118
  60. data/lib/active_record/connection_adapters/abstract_adapter.rb +177 -60
  61. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +295 -141
  62. data/lib/active_record/connection_adapters/column.rb +29 -240
  63. data/lib/active_record/connection_adapters/connection_specification.rb +15 -24
  64. data/lib/active_record/connection_adapters/mysql2_adapter.rb +17 -33
  65. data/lib/active_record/connection_adapters/mysql_adapter.rb +68 -145
  66. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
  67. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  68. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -25
  69. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
  70. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  71. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  73. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  78. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  79. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  80. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -385
  95. data/lib/active_record/connection_adapters/postgresql/quoting.rb +46 -136
  96. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
  97. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
  98. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +134 -43
  99. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  100. data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -477
  101. data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
  102. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -75
  103. data/lib/active_record/connection_handling.rb +1 -1
  104. data/lib/active_record/core.rb +163 -40
  105. data/lib/active_record/counter_cache.rb +60 -6
  106. data/lib/active_record/enum.rb +10 -12
  107. data/lib/active_record/errors.rb +53 -30
  108. data/lib/active_record/explain.rb +1 -1
  109. data/lib/active_record/explain_subscriber.rb +1 -1
  110. data/lib/active_record/fixtures.rb +62 -74
  111. data/lib/active_record/gem_version.rb +4 -4
  112. data/lib/active_record/inheritance.rb +35 -10
  113. data/lib/active_record/integration.rb +4 -4
  114. data/lib/active_record/legacy_yaml_adapter.rb +30 -0
  115. data/lib/active_record/locking/optimistic.rb +46 -26
  116. data/lib/active_record/migration/command_recorder.rb +19 -2
  117. data/lib/active_record/migration/join_table.rb +1 -1
  118. data/lib/active_record/migration.rb +79 -47
  119. data/lib/active_record/model_schema.rb +52 -58
  120. data/lib/active_record/nested_attributes.rb +18 -8
  121. data/lib/active_record/no_touching.rb +1 -1
  122. data/lib/active_record/persistence.rb +48 -27
  123. data/lib/active_record/query_cache.rb +3 -3
  124. data/lib/active_record/querying.rb +10 -7
  125. data/lib/active_record/railtie.rb +19 -14
  126. data/lib/active_record/railties/databases.rake +55 -56
  127. data/lib/active_record/readonly_attributes.rb +0 -1
  128. data/lib/active_record/reflection.rb +281 -117
  129. data/lib/active_record/relation/batches.rb +0 -1
  130. data/lib/active_record/relation/calculations.rb +41 -37
  131. data/lib/active_record/relation/delegation.rb +1 -1
  132. data/lib/active_record/relation/finder_methods.rb +71 -48
  133. data/lib/active_record/relation/merger.rb +39 -29
  134. data/lib/active_record/relation/predicate_builder/array_handler.rb +32 -13
  135. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  136. data/lib/active_record/relation/predicate_builder.rb +42 -12
  137. data/lib/active_record/relation/query_methods.rb +130 -73
  138. data/lib/active_record/relation/spawn_methods.rb +10 -3
  139. data/lib/active_record/relation.rb +57 -25
  140. data/lib/active_record/result.rb +18 -7
  141. data/lib/active_record/sanitization.rb +12 -2
  142. data/lib/active_record/schema.rb +0 -1
  143. data/lib/active_record/schema_dumper.rb +59 -28
  144. data/lib/active_record/schema_migration.rb +5 -4
  145. data/lib/active_record/scoping/default.rb +6 -4
  146. data/lib/active_record/scoping/named.rb +4 -0
  147. data/lib/active_record/serializers/xml_serializer.rb +3 -7
  148. data/lib/active_record/statement_cache.rb +95 -10
  149. data/lib/active_record/store.rb +5 -5
  150. data/lib/active_record/tasks/database_tasks.rb +61 -8
  151. data/lib/active_record/tasks/mysql_database_tasks.rb +32 -17
  152. data/lib/active_record/tasks/postgresql_database_tasks.rb +20 -9
  153. data/lib/active_record/timestamp.rb +9 -7
  154. data/lib/active_record/transactions.rb +54 -28
  155. data/lib/active_record/type/big_integer.rb +13 -0
  156. data/lib/active_record/type/binary.rb +50 -0
  157. data/lib/active_record/type/boolean.rb +31 -0
  158. data/lib/active_record/type/date.rb +50 -0
  159. data/lib/active_record/type/date_time.rb +54 -0
  160. data/lib/active_record/type/decimal.rb +64 -0
  161. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  162. data/lib/active_record/type/decorator.rb +14 -0
  163. data/lib/active_record/type/float.rb +19 -0
  164. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  165. data/lib/active_record/type/integer.rb +59 -0
  166. data/lib/active_record/type/mutable.rb +16 -0
  167. data/lib/active_record/type/numeric.rb +36 -0
  168. data/lib/active_record/type/serialized.rb +62 -0
  169. data/lib/active_record/type/string.rb +40 -0
  170. data/lib/active_record/type/text.rb +11 -0
  171. data/lib/active_record/type/time.rb +26 -0
  172. data/lib/active_record/type/time_value.rb +38 -0
  173. data/lib/active_record/type/type_map.rb +64 -0
  174. data/lib/active_record/type/unsigned_integer.rb +15 -0
  175. data/lib/active_record/type/value.rb +110 -0
  176. data/lib/active_record/type.rb +23 -0
  177. data/lib/active_record/validations/associated.rb +5 -3
  178. data/lib/active_record/validations/presence.rb +5 -3
  179. data/lib/active_record/validations/uniqueness.rb +24 -20
  180. data/lib/active_record/validations.rb +25 -19
  181. data/lib/active_record.rb +5 -0
  182. data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
  183. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
  184. data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
  185. metadata +66 -11
  186. data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -2,6 +2,7 @@ require 'erb'
2
2
  require 'yaml'
3
3
  require 'zlib'
4
4
  require 'active_support/dependencies'
5
+ require 'active_support/core_ext/digest/uuid'
5
6
  require 'active_record/fixture_set/file'
6
7
  require 'active_record/errors'
7
8
 
@@ -14,9 +15,10 @@ module ActiveRecord
14
15
  # They are stored in YAML files, one file per model, which are placed in the directory
15
16
  # appointed by <tt>ActiveSupport::TestCase.fixture_path=(path)</tt> (this is automatically
16
17
  # configured for Rails, so you can just put your files in <tt><your-rails-app>/test/fixtures/</tt>).
17
- # The fixture file ends with the <tt>.yml</tt> file extension (Rails example:
18
- # <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>). The format of a fixture file looks
19
- # like this:
18
+ # The fixture file ends with the +.yml+ file extension, for example:
19
+ # <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>).
20
+ #
21
+ # The format of a fixture file looks like this:
20
22
  #
21
23
  # rubyonrails:
22
24
  # id: 1
@@ -32,7 +34,7 @@ module ActiveRecord
32
34
  # is followed by an indented list of key/value pairs in the "key: value" format. Records are
33
35
  # separated by a blank line for your viewing pleasure.
34
36
  #
35
- # Note that fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
37
+ # Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
36
38
  # See http://yaml.org/type/omap.html
37
39
  # for the specification. You will need ordered fixtures when you have foreign key constraints
38
40
  # on keys in the same table. This is commonly needed for tree structures. Example:
@@ -60,8 +62,8 @@ module ActiveRecord
60
62
  # end
61
63
  # end
62
64
  #
63
- # By default, <tt>test_helper.rb</tt> will load all of your fixtures into your test database,
64
- # so this test will succeed.
65
+ # By default, +test_helper.rb+ will load all of your fixtures into your test
66
+ # database, so this test will succeed.
65
67
  #
66
68
  # The testing environment will automatically load the all fixtures into the database before each
67
69
  # test. To ensure consistent data, the environment deletes the fixtures before running the load.
@@ -179,6 +181,9 @@ module ActiveRecord
179
181
  # * Stable, autogenerated IDs
180
182
  # * Label references for associations (belongs_to, has_one, has_many)
181
183
  # * HABTM associations as inline lists
184
+ #
185
+ # There are some more advanced features available even if the id is specified:
186
+ #
182
187
  # * Autofilled timestamp columns
183
188
  # * Fixture label interpolation
184
189
  # * Support for YAML defaults
@@ -361,6 +366,7 @@ module ActiveRecord
361
366
  # geeksomnia:
362
367
  # name: Geeksomnia's Account
363
368
  # subdomain: $LABEL
369
+ # email: $LABEL@email.com
364
370
  #
365
371
  # Also, sometimes (like when porting older join table fixtures) you'll need
366
372
  # to be able to get a hold of the identifier for a given label. ERB
@@ -372,8 +378,9 @@ module ActiveRecord
372
378
  #
373
379
  # == Support for YAML defaults
374
380
  #
375
- # You probably already know how to use YAML to set and reuse defaults in
376
- # your <tt>database.yml</tt> file. You can use the same technique in your fixtures:
381
+ # You can set and reuse defaults in your fixtures YAML file.
382
+ # This is the same technique used in the +database.yml+ file to specify
383
+ # defaults:
377
384
  #
378
385
  # DEFAULTS: &DEFAULTS
379
386
  # created_on: <%= 3.weeks.ago.to_s(:db) %>
@@ -389,7 +396,8 @@ module ActiveRecord
389
396
  # Any fixture labeled "DEFAULTS" is safely ignored.
390
397
  class FixtureSet
391
398
  #--
392
- # An instance of FixtureSet is normally stored in a single YAML file and possibly in a folder with the same name.
399
+ # An instance of FixtureSet is normally stored in a single YAML file and
400
+ # possibly in a folder with the same name.
393
401
  #++
394
402
 
395
403
  MAX_ID = 2 ** 30 - 1
@@ -459,13 +467,7 @@ module ActiveRecord
459
467
  @config = config
460
468
 
461
469
  # Remove string values that aren't constants or subclasses of AR
462
- @class_names.delete_if { |k,klass|
463
- unless klass.is_a? Class
464
- klass = klass.safe_constantize
465
- ActiveSupport::Deprecation.warn("The ability to pass in strings as a class name to `set_fixture_class` will be removed in Rails 4.2. Use the class itself instead.")
466
- end
467
- !insert_class(@class_names, k, klass)
468
- }
470
+ @class_names.delete_if { |klass_name, klass| !insert_class(@class_names, klass_name, klass) }
469
471
  end
470
472
 
471
473
  def [](fs_name)
@@ -516,14 +518,14 @@ module ActiveRecord
516
518
  ::File.join(fixtures_directory, fs_name))
517
519
  end
518
520
 
519
- all_loaded_fixtures.update(fixtures_map)
521
+ update_all_loaded_fixtures fixtures_map
520
522
 
521
523
  connection.transaction(:requires_new => true) do
522
524
  fixture_sets.each do |fs|
523
525
  conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
524
526
  table_rows = fs.table_rows
525
527
 
526
- table_rows.keys.each do |table|
528
+ table_rows.each_key do |table|
527
529
  conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
528
530
  end
529
531
 
@@ -532,12 +534,10 @@ module ActiveRecord
532
534
  conn.insert_fixture(row, fixture_set_name)
533
535
  end
534
536
  end
535
- end
536
537
 
537
- # Cap primary key sequences to max(pk).
538
- if connection.respond_to?(:reset_pk_sequence!)
539
- fixture_sets.each do |fs|
540
- connection.reset_pk_sequence!(fs.table_name)
538
+ # Cap primary key sequences to max(pk).
539
+ if conn.respond_to?(:reset_pk_sequence!)
540
+ conn.reset_pk_sequence!(fs.table_name)
541
541
  end
542
542
  end
543
543
  end
@@ -549,9 +549,13 @@ module ActiveRecord
549
549
  end
550
550
 
551
551
  # Returns a consistent, platform-independent identifier for +label+.
552
- # Identifiers are positive integers less than 2^32.
553
- def self.identify(label)
554
- Zlib.crc32(label.to_s) % MAX_ID
552
+ # Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
553
+ def self.identify(label, column_type = :integer)
554
+ if column_type == :uuid
555
+ Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
556
+ else
557
+ Zlib.crc32(label.to_s) % MAX_ID
558
+ end
555
559
  end
556
560
 
557
561
  # Superclass for the evaluation contexts used by ERB fixtures.
@@ -559,6 +563,10 @@ module ActiveRecord
559
563
  @context_class ||= Class.new
560
564
  end
561
565
 
566
+ def self.update_all_loaded_fixtures(fixtures_map) # :nodoc:
567
+ all_loaded_fixtures.update(fixtures_map)
568
+ end
569
+
562
570
  attr_reader :table_name, :name, :fixtures, :model_class, :config
563
571
 
564
572
  def initialize(connection, name, class_name, path, config = ActiveRecord::Base)
@@ -567,10 +575,6 @@ module ActiveRecord
567
575
  @config = config
568
576
  @model_class = nil
569
577
 
570
- if class_name.is_a?(String)
571
- ActiveSupport::Deprecation.warn("The ability to pass in strings as a class name to `FixtureSet.new` will be removed in Rails 4.2. Use the class itself instead.")
572
- end
573
-
574
578
  if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
575
579
  @model_class = class_name
576
580
  else
@@ -627,12 +631,12 @@ module ActiveRecord
627
631
 
628
632
  # interpolate the fixture label
629
633
  row.each do |key, value|
630
- row[key] = label if "$LABEL" == value
634
+ row[key] = value.gsub("$LABEL", label.to_s) if value.is_a?(String)
631
635
  end
632
636
 
633
637
  # generate a primary key if necessary
634
638
  if has_primary_key_column? && !row.include?(primary_key_name)
635
- row[primary_key_name] = ActiveRecord::FixtureSet.identify(label)
639
+ row[primary_key_name] = ActiveRecord::FixtureSet.identify(label, primary_key_type)
636
640
  end
637
641
 
638
642
  # If STI is used, find the correct subclass for association reflection
@@ -643,19 +647,20 @@ module ActiveRecord
643
647
  model_class
644
648
  end
645
649
 
646
- reflection_class._reflections.values.each do |association|
650
+ reflection_class._reflections.each_value do |association|
647
651
  case association.macro
648
652
  when :belongs_to
649
653
  # Do not replace association name with association foreign key if they are named the same
650
654
  fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
651
655
 
652
656
  if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
653
- if association.options[:polymorphic] && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
657
+ if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
654
658
  # support polymorphic belongs_to as "label (Type)"
655
659
  row[association.foreign_type] = $1
656
660
  end
657
661
 
658
- row[fk_name] = ActiveRecord::FixtureSet.identify(value)
662
+ fk_type = reflection_class.columns_hash[fk_name].type
663
+ row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
659
664
  end
660
665
  when :has_many
661
666
  if association.options[:through]
@@ -682,6 +687,10 @@ module ActiveRecord
682
687
  def name
683
688
  @association.name
684
689
  end
690
+
691
+ def primary_key_type
692
+ @association.klass.column_types[@association.klass.primary_key].type
693
+ end
685
694
  end
686
695
 
687
696
  class HasManyThroughProxy < ReflectionProxy # :nodoc:
@@ -692,6 +701,10 @@ module ActiveRecord
692
701
  def lhs_key
693
702
  @association.through_reflection.foreign_key
694
703
  end
704
+
705
+ def join_table
706
+ @association.through_reflection.table_name
707
+ end
695
708
  end
696
709
 
697
710
  private
@@ -699,17 +712,22 @@ module ActiveRecord
699
712
  @primary_key_name ||= model_class && model_class.primary_key
700
713
  end
701
714
 
715
+ def primary_key_type
716
+ @primary_key_type ||= model_class && model_class.column_types[model_class.primary_key].type
717
+ end
718
+
702
719
  def add_join_records(rows, row, association)
703
720
  # This is the case when the join table has no fixtures file
704
721
  if (targets = row.delete(association.name.to_s))
705
- table_name = association.join_table
706
- lhs_key = association.lhs_key
707
- rhs_key = association.rhs_key
722
+ table_name = association.join_table
723
+ column_type = association.primary_key_type
724
+ lhs_key = association.lhs_key
725
+ rhs_key = association.rhs_key
708
726
 
709
727
  targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
710
728
  rows[table_name].concat targets.map { |target|
711
729
  { lhs_key => row[primary_key_name],
712
- rhs_key => ActiveRecord::FixtureSet.identify(target) }
730
+ rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) }
713
731
  }
714
732
  end
715
733
  end
@@ -790,7 +808,9 @@ module ActiveRecord
790
808
 
791
809
  def find
792
810
  if model_class
793
- model_class.find(fixture[model_class.primary_key])
811
+ model_class.unscoped do
812
+ model_class.find(fixture[model_class.primary_key])
813
+ end
794
814
  else
795
815
  raise FixtureClassNotFound, "No class attached to find."
796
816
  end
@@ -854,34 +874,9 @@ module ActiveRecord
854
874
  end
855
875
 
856
876
  self.fixture_table_names |= fixture_set_names
857
- require_fixture_classes(fixture_set_names, self.config)
858
877
  setup_fixture_accessors(fixture_set_names)
859
878
  end
860
879
 
861
- def try_to_load_dependency(file_name)
862
- require_dependency file_name
863
- rescue LoadError => e
864
- unless fixture_class_names.key?(file_name.pluralize)
865
- if ActiveRecord::Base.logger
866
- ActiveRecord::Base.logger.warn("Unable to load #{file_name}, make sure you added it to ActiveSupport::TestCase.set_fixture_class")
867
- ActiveRecord::Base.logger.warn("underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
868
- end
869
- end
870
- end
871
-
872
- def require_fixture_classes(fixture_set_names = nil, config = ActiveRecord::Base)
873
- if fixture_set_names
874
- fixture_set_names = fixture_set_names.map { |n| n.to_s }
875
- else
876
- fixture_set_names = fixture_table_names
877
- end
878
-
879
- fixture_set_names.each do |file_name|
880
- file_name = file_name.singularize if config.pluralize_table_names
881
- try_to_load_dependency(file_name)
882
- end
883
- end
884
-
885
880
  def setup_fixture_accessors(fixture_set_names = nil)
886
881
  fixture_set_names = Array(fixture_set_names || fixture_table_names)
887
882
  methods = Module.new do
@@ -958,7 +953,7 @@ module ActiveRecord
958
953
  end
959
954
 
960
955
  # Instantiate fixtures for every test if requested.
961
- instantiate_fixtures(config) if use_instantiated_fixtures
956
+ instantiate_fixtures if use_instantiated_fixtures
962
957
  end
963
958
 
964
959
  def teardown_fixtures
@@ -985,16 +980,9 @@ module ActiveRecord
985
980
  Hash[fixtures.map { |f| [f.name, f] }]
986
981
  end
987
982
 
988
- # for pre_loaded_fixtures, only require the classes once. huge speed improvement
989
- @@required_fixture_classes = false
990
-
991
- def instantiate_fixtures(config)
983
+ def instantiate_fixtures
992
984
  if pre_loaded_fixtures
993
985
  raise RuntimeError, 'Load fixtures before instantiating them.' if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
994
- unless @@required_fixture_classes
995
- self.class.require_fixture_classes ActiveRecord::FixtureSet.all_loaded_fixtures.keys, config
996
- @@required_fixture_classes = true
997
- end
998
986
  ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
999
987
  else
1000
988
  raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
@@ -1,14 +1,14 @@
1
1
  module ActiveRecord
2
- # Returns the version of the currently loaded ActiveRecord as a <tt>Gem::Version</tt>
2
+ # Returns the version of the currently loaded Active Record as a <tt>Gem::Version</tt>
3
3
  def self.gem_version
4
4
  Gem::Version.new VERSION::STRING
5
5
  end
6
6
 
7
7
  module VERSION
8
8
  MAJOR = 4
9
- MINOR = 1
10
- TINY = 8
11
- PRE = nil
9
+ MINOR = 2
10
+ TINY = 11
11
+ PRE = "3"
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
14
  end
@@ -1,6 +1,37 @@
1
1
  require 'active_support/core_ext/hash/indifferent_access'
2
2
 
3
3
  module ActiveRecord
4
+ # == Single table inheritance
5
+ #
6
+ # Active Record allows inheritance by storing the name of the class in a column that by
7
+ # default is named "type" (can be changed by overwriting <tt>Base.inheritance_column</tt>).
8
+ # This means that an inheritance looking like this:
9
+ #
10
+ # class Company < ActiveRecord::Base; end
11
+ # class Firm < Company; end
12
+ # class Client < Company; end
13
+ # class PriorityClient < Client; end
14
+ #
15
+ # When you do <tt>Firm.create(name: "37signals")</tt>, this record will be saved in
16
+ # the companies table with type = "Firm". You can then fetch this row again using
17
+ # <tt>Company.where(name: '37signals').first</tt> and it will return a Firm object.
18
+ #
19
+ # Be aware that because the type column is an attribute on the record every new
20
+ # subclass will instantly be marked as dirty and the type column will be included
21
+ # in the list of changed attributes on the record. This is different from non
22
+ # STI classes:
23
+ #
24
+ # Company.new.changed? # => false
25
+ # Firm.new.changed? # => true
26
+ # Firm.new.changes # => {"type"=>["","Firm"]}
27
+ #
28
+ # If you don't have a type column defined in your table, single-table inheritance won't
29
+ # be triggered. In that case, it'll work just like normal subclasses with no special magic
30
+ # for differentiating between them or reloading the right type with find.
31
+ #
32
+ # Note, all the attributes for all the cases are kept in the same table. Read more:
33
+ # http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
34
+ #
4
35
  module Inheritance
5
36
  extend ActiveSupport::Concern
6
37
 
@@ -49,12 +80,12 @@ module ActiveRecord
49
80
  end
50
81
 
51
82
  def symbolized_base_class
52
- ActiveSupport::Deprecation.warn("ActiveRecord::Base.symbolized_base_class is deprecated and will be removed without replacement.")
83
+ ActiveSupport::Deprecation.warn('`ActiveRecord::Base.symbolized_base_class` is deprecated and will be removed without replacement.')
53
84
  @symbolized_base_class ||= base_class.to_s.to_sym
54
85
  end
55
86
 
56
87
  def symbolized_sti_name
57
- ActiveSupport::Deprecation.warn("ActiveRecord::Base.symbolized_sti_name is deprecated and will be removed without replacement.")
88
+ ActiveSupport::Deprecation.warn('`ActiveRecord::Base.symbolized_sti_name` is deprecated and will be removed without replacement.')
58
89
  @symbolized_sti_name ||= sti_name.present? ? sti_name.to_sym : symbolized_base_class
59
90
  end
60
91
 
@@ -120,14 +151,8 @@ module ActiveRecord
120
151
  candidates << type_name
121
152
 
122
153
  candidates.each do |candidate|
123
- begin
124
- constant = ActiveSupport::Dependencies.constantize(candidate)
125
- return constant if candidate == constant.to_s
126
- # We don't want to swallow NoMethodError < NameError errors
127
- rescue NoMethodError
128
- raise
129
- rescue NameError
130
- end
154
+ constant = ActiveSupport::Dependencies.safe_constantize(candidate)
155
+ return constant if candidate == constant.to_s
131
156
  end
132
157
 
133
158
  raise NameError.new("uninitialized constant #{candidates.first}", candidates.first)
@@ -55,16 +55,16 @@ module ActiveRecord
55
55
  def cache_key(*timestamp_names)
56
56
  case
57
57
  when new_record?
58
- "#{self.class.model_name.cache_key}/new"
58
+ "#{model_name.cache_key}/new"
59
59
  when timestamp_names.any?
60
60
  timestamp = max_updated_column_timestamp(timestamp_names)
61
61
  timestamp = timestamp.utc.to_s(cache_timestamp_format)
62
- "#{self.class.model_name.cache_key}/#{id}-#{timestamp}"
62
+ "#{model_name.cache_key}/#{id}-#{timestamp}"
63
63
  when timestamp = max_updated_column_timestamp
64
64
  timestamp = timestamp.utc.to_s(cache_timestamp_format)
65
- "#{self.class.model_name.cache_key}/#{id}-#{timestamp}"
65
+ "#{model_name.cache_key}/#{id}-#{timestamp}"
66
66
  else
67
- "#{self.class.model_name.cache_key}/#{id}"
67
+ "#{model_name.cache_key}/#{id}"
68
68
  end
69
69
  end
70
70
 
@@ -0,0 +1,30 @@
1
+ module ActiveRecord
2
+ module LegacyYamlAdapter
3
+ def self.convert(klass, coder)
4
+ return coder unless coder.is_a?(Psych::Coder)
5
+
6
+ case coder["active_record_yaml_version"]
7
+ when 0 then coder
8
+ else
9
+ if coder["attributes"].is_a?(AttributeSet)
10
+ coder
11
+ else
12
+ Rails41.convert(klass, coder)
13
+ end
14
+ end
15
+ end
16
+
17
+ module Rails41
18
+ def self.convert(klass, coder)
19
+ attributes = klass.attributes_builder
20
+ .build_from_database(coder["attributes"])
21
+ new_record = coder["attributes"][klass.primary_key].blank?
22
+
23
+ {
24
+ "attributes" => attributes,
25
+ "new_record" => new_record,
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -66,7 +66,16 @@ module ActiveRecord
66
66
  send(lock_col + '=', previous_lock_value + 1)
67
67
  end
68
68
 
69
- def _update_record(attribute_names = @attributes.keys) #:nodoc:
69
+ def _create_record(attribute_names = self.attribute_names, *) # :nodoc:
70
+ if locking_enabled?
71
+ # We always want to persist the locking version, even if we don't detect
72
+ # a change from the default, since the database might have no default
73
+ attribute_names |= [self.class.locking_column]
74
+ end
75
+ super
76
+ end
77
+
78
+ def _update_record(attribute_names = self.attribute_names) #:nodoc:
70
79
  return super unless locking_enabled?
71
80
  return 0 if attribute_names.empty?
72
81
 
@@ -80,17 +89,15 @@ module ActiveRecord
80
89
  begin
81
90
  relation = self.class.unscoped
82
91
 
83
- stmt = relation.where(
84
- relation.table[self.class.primary_key].eq(id).and(
85
- relation.table[lock_col].eq(self.class.quote_value(previous_lock_value, column_for_attribute(lock_col)))
86
- )
87
- ).arel.compile_update(
88
- arel_attributes_with_values_for_update(attribute_names),
89
- self.class.primary_key
92
+ affected_rows = relation.where(
93
+ self.class.primary_key => id,
94
+ lock_col => previous_lock_value,
95
+ ).update_all(
96
+ Hash[attributes_for_update(attribute_names).map do |name|
97
+ [name, _read_attribute(name)]
98
+ end]
90
99
  )
91
100
 
92
- affected_rows = self.class.connection.update stmt
93
-
94
101
  unless affected_rows == 1
95
102
  raise ActiveRecord::StaleObjectError.new(self, "update")
96
103
  end
@@ -120,7 +127,7 @@ module ActiveRecord
120
127
  if locking_enabled?
121
128
  column_name = self.class.locking_column
122
129
  column = self.class.columns_hash[column_name]
123
- substitute = self.class.connection.substitute_at(column, relation.bind_values.length)
130
+ substitute = self.class.connection.substitute_at(column)
124
131
 
125
132
  relation = relation.where(self.class.arel_table[column_name].eq(substitute))
126
133
  relation.bind_values << [column, self[column_name].to_i]
@@ -141,7 +148,7 @@ module ActiveRecord
141
148
 
142
149
  # Set the column to use for optimistic locking. Defaults to +lock_version+.
143
150
  def locking_column=(value)
144
- @column_defaults = nil
151
+ clear_caches_calculated_from_columns
145
152
  @locking_column = value.to_s
146
153
  end
147
154
 
@@ -151,12 +158,6 @@ module ActiveRecord
151
158
  @locking_column
152
159
  end
153
160
 
154
- # Quote the column name used for optimistic locking.
155
- def quoted_locking_column
156
- ActiveSupport::Deprecation.warn "ActiveRecord::Base.quoted_locking_column is deprecated and will be removed in Rails 4.2 or later."
157
- connection.quote_column_name(locking_column)
158
- end
159
-
160
161
  # Reset the column used for optimistic locking back to the +lock_version+ default.
161
162
  def reset_locking_column
162
163
  self.locking_column = DEFAULT_LOCKING_COLUMN
@@ -169,18 +170,37 @@ module ActiveRecord
169
170
  super
170
171
  end
171
172
 
172
- def column_defaults
173
- @column_defaults ||= begin
174
- defaults = super
175
-
176
- if defaults.key?(locking_column) && lock_optimistically
177
- defaults[locking_column] ||= 0
173
+ private
174
+
175
+ # We need to apply this decorator here, rather than on module inclusion. The closure
176
+ # created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the
177
+ # sub class being decorated. As such, changes to `lock_optimistically`, or
178
+ # `locking_column` would not be picked up.
179
+ def inherited(subclass)
180
+ subclass.class_eval do
181
+ is_lock_column = ->(name, _) { lock_optimistically && name == locking_column }
182
+ decorate_matching_attribute_types(is_lock_column, :_optimistic_locking) do |type|
183
+ LockingType.new(type)
178
184
  end
179
-
180
- defaults
181
185
  end
186
+ super
182
187
  end
183
188
  end
184
189
  end
190
+
191
+ class LockingType < SimpleDelegator # :nodoc:
192
+ def type_cast_from_database(value)
193
+ # `nil` *should* be changed to 0
194
+ super.to_i
195
+ end
196
+
197
+ def init_with(coder)
198
+ __setobj__(coder['subtype'])
199
+ end
200
+
201
+ def encode_with(coder)
202
+ coder['subtype'] = __getobj__
203
+ end
204
+ end
185
205
  end
186
206
  end
@@ -74,7 +74,9 @@ module ActiveRecord
74
74
  :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
75
75
  :change_column_default, :add_reference, :remove_reference, :transaction,
76
76
  :drop_join_table, :drop_table, :execute_block, :enable_extension,
77
- :change_column, :execute, :remove_columns, :change_column_null # irreversible methods need to be here too
77
+ :change_column, :execute, :remove_columns, :change_column_null,
78
+ :add_foreign_key, :remove_foreign_key
79
+ # irreversible methods need to be here too
78
80
  ].each do |method|
79
81
  class_eval <<-EOV, __FILE__, __LINE__ + 1
80
82
  def #{method}(*args, &block) # def create_table(*args, &block)
@@ -85,7 +87,7 @@ module ActiveRecord
85
87
  alias :add_belongs_to :add_reference
86
88
  alias :remove_belongs_to :remove_reference
87
89
 
88
- def change_table(table_name, options = {})
90
+ def change_table(table_name, options = {}) # :nodoc:
89
91
  yield delegate.update_table_definition(table_name, self)
90
92
  end
91
93
 
@@ -167,6 +169,21 @@ module ActiveRecord
167
169
  [:change_column_null, args]
168
170
  end
169
171
 
172
+ def invert_add_foreign_key(args)
173
+ from_table, to_table, add_options = args
174
+ add_options ||= {}
175
+
176
+ if add_options[:name]
177
+ options = { name: add_options[:name] }
178
+ elsif add_options[:column]
179
+ options = { column: add_options[:column] }
180
+ else
181
+ options = to_table
182
+ end
183
+
184
+ [:remove_foreign_key, [from_table, options]]
185
+ end
186
+
170
187
  # Forwards any missing method call to the \target.
171
188
  def method_missing(method, *args, &block)
172
189
  if @delegate.respond_to?(method)
@@ -8,7 +8,7 @@ module ActiveRecord
8
8
  end
9
9
 
10
10
  def join_table_name(table_1, table_2)
11
- [table_1.to_s, table_2.to_s].sort.join("_").to_sym
11
+ ModelSchema.derive_join_table_name(table_1, table_2).to_sym
12
12
  end
13
13
  end
14
14
  end