activerecord 4.2.11.1 → 5.0.0

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 (246) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1282 -1195
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -8
  5. data/examples/performance.rb +2 -3
  6. data/examples/simple.rb +0 -1
  7. data/lib/active_record.rb +8 -4
  8. data/lib/active_record/aggregations.rb +35 -24
  9. data/lib/active_record/association_relation.rb +3 -3
  10. data/lib/active_record/associations.rb +317 -209
  11. data/lib/active_record/associations/alias_tracker.rb +19 -16
  12. data/lib/active_record/associations/association.rb +11 -9
  13. data/lib/active_record/associations/association_scope.rb +73 -102
  14. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  15. data/lib/active_record/associations/builder/association.rb +28 -34
  16. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  17. data/lib/active_record/associations/builder/collection_association.rb +7 -19
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
  19. data/lib/active_record/associations/builder/has_many.rb +4 -4
  20. data/lib/active_record/associations/builder/has_one.rb +11 -6
  21. data/lib/active_record/associations/builder/singular_association.rb +3 -10
  22. data/lib/active_record/associations/collection_association.rb +49 -41
  23. data/lib/active_record/associations/collection_proxy.rb +67 -27
  24. data/lib/active_record/associations/foreign_association.rb +1 -1
  25. data/lib/active_record/associations/has_many_association.rb +20 -71
  26. data/lib/active_record/associations/has_many_through_association.rb +8 -47
  27. data/lib/active_record/associations/has_one_association.rb +12 -5
  28. data/lib/active_record/associations/join_dependency.rb +29 -19
  29. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  30. data/lib/active_record/associations/preloader.rb +14 -4
  31. data/lib/active_record/associations/preloader/association.rb +46 -52
  32. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  33. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  35. data/lib/active_record/associations/preloader/through_association.rb +27 -14
  36. data/lib/active_record/associations/singular_association.rb +7 -1
  37. data/lib/active_record/associations/through_association.rb +11 -3
  38. data/lib/active_record/attribute.rb +68 -18
  39. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  40. data/lib/active_record/attribute_assignment.rb +19 -140
  41. data/lib/active_record/attribute_decorators.rb +6 -5
  42. data/lib/active_record/attribute_methods.rb +76 -47
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  44. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  45. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  46. data/lib/active_record/attribute_methods/query.rb +2 -2
  47. data/lib/active_record/attribute_methods/read.rb +31 -59
  48. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  50. data/lib/active_record/attribute_methods/write.rb +13 -37
  51. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  52. data/lib/active_record/attribute_set.rb +30 -3
  53. data/lib/active_record/attribute_set/builder.rb +6 -4
  54. data/lib/active_record/attributes.rb +199 -81
  55. data/lib/active_record/autosave_association.rb +49 -16
  56. data/lib/active_record/base.rb +32 -23
  57. data/lib/active_record/callbacks.rb +39 -43
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +20 -8
  60. data/lib/active_record/collection_cache_key.rb +40 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
  62. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  63. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
  64. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  65. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
  66. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  67. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  68. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
  69. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  70. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
  71. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  72. data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
  73. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
  74. data/lib/active_record/connection_adapters/column.rb +28 -43
  75. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  76. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  77. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  78. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  79. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  80. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  81. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  82. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  83. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  84. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  85. data/lib/active_record/connection_adapters/mysql2_adapter.rb +29 -166
  86. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  87. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
  88. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -57
  91. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  96. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  100. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  106. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  107. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  108. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  109. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
  111. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  112. data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
  113. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  114. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  115. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  116. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
  119. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  120. data/lib/active_record/connection_handling.rb +37 -14
  121. data/lib/active_record/core.rb +89 -107
  122. data/lib/active_record/counter_cache.rb +13 -24
  123. data/lib/active_record/dynamic_matchers.rb +1 -20
  124. data/lib/active_record/enum.rb +113 -76
  125. data/lib/active_record/errors.rb +87 -48
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +1 -1
  128. data/lib/active_record/fixture_set/file.rb +26 -5
  129. data/lib/active_record/fixtures.rb +76 -40
  130. data/lib/active_record/gem_version.rb +4 -4
  131. data/lib/active_record/inheritance.rb +32 -40
  132. data/lib/active_record/integration.rb +4 -4
  133. data/lib/active_record/internal_metadata.rb +56 -0
  134. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  135. data/lib/active_record/locale/en.yml +3 -2
  136. data/lib/active_record/locking/optimistic.rb +15 -15
  137. data/lib/active_record/locking/pessimistic.rb +1 -1
  138. data/lib/active_record/log_subscriber.rb +43 -21
  139. data/lib/active_record/migration.rb +363 -133
  140. data/lib/active_record/migration/command_recorder.rb +59 -18
  141. data/lib/active_record/migration/compatibility.rb +126 -0
  142. data/lib/active_record/model_schema.rb +129 -41
  143. data/lib/active_record/nested_attributes.rb +58 -29
  144. data/lib/active_record/null_relation.rb +16 -8
  145. data/lib/active_record/persistence.rb +121 -80
  146. data/lib/active_record/query_cache.rb +15 -18
  147. data/lib/active_record/querying.rb +10 -9
  148. data/lib/active_record/railtie.rb +23 -16
  149. data/lib/active_record/railties/controller_runtime.rb +1 -1
  150. data/lib/active_record/railties/databases.rake +69 -46
  151. data/lib/active_record/readonly_attributes.rb +1 -1
  152. data/lib/active_record/reflection.rb +282 -115
  153. data/lib/active_record/relation.rb +176 -116
  154. data/lib/active_record/relation/batches.rb +139 -34
  155. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  156. data/lib/active_record/relation/calculations.rb +79 -108
  157. data/lib/active_record/relation/delegation.rb +7 -20
  158. data/lib/active_record/relation/finder_methods.rb +163 -81
  159. data/lib/active_record/relation/from_clause.rb +32 -0
  160. data/lib/active_record/relation/merger.rb +16 -42
  161. data/lib/active_record/relation/predicate_builder.rb +120 -107
  162. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  163. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  164. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  165. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  166. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  167. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  168. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  169. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  170. data/lib/active_record/relation/query_attribute.rb +19 -0
  171. data/lib/active_record/relation/query_methods.rb +308 -244
  172. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  173. data/lib/active_record/relation/spawn_methods.rb +4 -7
  174. data/lib/active_record/relation/where_clause.rb +174 -0
  175. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  176. data/lib/active_record/result.rb +4 -3
  177. data/lib/active_record/runtime_registry.rb +1 -1
  178. data/lib/active_record/sanitization.rb +95 -66
  179. data/lib/active_record/schema.rb +26 -22
  180. data/lib/active_record/schema_dumper.rb +62 -38
  181. data/lib/active_record/schema_migration.rb +11 -14
  182. data/lib/active_record/scoping.rb +32 -15
  183. data/lib/active_record/scoping/default.rb +23 -9
  184. data/lib/active_record/scoping/named.rb +49 -28
  185. data/lib/active_record/secure_token.rb +38 -0
  186. data/lib/active_record/serialization.rb +2 -4
  187. data/lib/active_record/statement_cache.rb +16 -14
  188. data/lib/active_record/store.rb +8 -3
  189. data/lib/active_record/suppressor.rb +58 -0
  190. data/lib/active_record/table_metadata.rb +68 -0
  191. data/lib/active_record/tasks/database_tasks.rb +57 -43
  192. data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
  193. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  194. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  195. data/lib/active_record/timestamp.rb +20 -9
  196. data/lib/active_record/touch_later.rb +58 -0
  197. data/lib/active_record/transactions.rb +138 -56
  198. data/lib/active_record/type.rb +66 -17
  199. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  200. data/lib/active_record/type/date.rb +2 -45
  201. data/lib/active_record/type/date_time.rb +2 -49
  202. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  203. data/lib/active_record/type/internal/timezone.rb +15 -0
  204. data/lib/active_record/type/serialized.rb +15 -14
  205. data/lib/active_record/type/time.rb +10 -16
  206. data/lib/active_record/type/type_map.rb +4 -4
  207. data/lib/active_record/type_caster.rb +7 -0
  208. data/lib/active_record/type_caster/connection.rb +29 -0
  209. data/lib/active_record/type_caster/map.rb +19 -0
  210. data/lib/active_record/validations.rb +33 -32
  211. data/lib/active_record/validations/absence.rb +23 -0
  212. data/lib/active_record/validations/associated.rb +10 -3
  213. data/lib/active_record/validations/length.rb +24 -0
  214. data/lib/active_record/validations/presence.rb +11 -12
  215. data/lib/active_record/validations/uniqueness.rb +30 -29
  216. data/lib/rails/generators/active_record/migration.rb +7 -0
  217. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  218. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  219. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  220. data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
  221. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  222. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  223. metadata +59 -34
  224. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  225. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  226. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  227. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  228. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  229. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  230. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  231. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  232. data/lib/active_record/type/big_integer.rb +0 -13
  233. data/lib/active_record/type/binary.rb +0 -50
  234. data/lib/active_record/type/boolean.rb +0 -31
  235. data/lib/active_record/type/decimal.rb +0 -64
  236. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  237. data/lib/active_record/type/decorator.rb +0 -14
  238. data/lib/active_record/type/float.rb +0 -19
  239. data/lib/active_record/type/integer.rb +0 -59
  240. data/lib/active_record/type/mutable.rb +0 -16
  241. data/lib/active_record/type/numeric.rb +0 -36
  242. data/lib/active_record/type/string.rb +0 -40
  243. data/lib/active_record/type/text.rb +0 -11
  244. data/lib/active_record/type/time_value.rb +0 -38
  245. data/lib/active_record/type/unsigned_integer.rb +0 -15
  246. data/lib/active_record/type/value.rb +0 -110
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
  #
8
8
  # returns the collected queries local to the current thread.
9
9
  #
10
- # See the documentation of <tt>ActiveSupport::PerThreadRegistry</tt>
10
+ # See the documentation of ActiveSupport::PerThreadRegistry
11
11
  # for further details.
12
12
  class ExplainRegistry # :nodoc:
13
13
  extend ActiveSupport::PerThreadRegistry
@@ -14,7 +14,7 @@ module ActiveRecord
14
14
  end
15
15
 
16
16
  # SCHEMA queries cannot be EXPLAINed, also we do not want to run EXPLAIN on
17
- # our own EXPLAINs now matter how loopingly beautiful that would be.
17
+ # our own EXPLAINs no matter how loopingly beautiful that would be.
18
18
  #
19
19
  # On the other hand, we want to monitor the performance of our real database
20
20
  # queries, not the performance of the access to the query cache.
@@ -17,29 +17,50 @@ module ActiveRecord
17
17
 
18
18
  def initialize(file)
19
19
  @file = file
20
- @rows = nil
21
20
  end
22
21
 
23
22
  def each(&block)
24
23
  rows.each(&block)
25
24
  end
26
25
 
26
+ def model_class
27
+ config_row['model_class']
28
+ end
27
29
 
28
30
  private
29
31
  def rows
30
- return @rows if @rows
32
+ @rows ||= raw_rows.reject { |fixture_name, _| fixture_name == '_fixture' }
33
+ end
31
34
 
32
- begin
35
+ def config_row
36
+ @config_row ||= begin
37
+ row = raw_rows.find { |fixture_name, _| fixture_name == '_fixture' }
38
+ if row
39
+ row.last
40
+ else
41
+ {'model_class': nil}
42
+ end
43
+ end
44
+ end
45
+
46
+ def raw_rows
47
+ @raw_rows ||= begin
33
48
  data = YAML.load(render(IO.read(@file)))
49
+ data ? validate(data).to_a : []
34
50
  rescue ArgumentError, Psych::SyntaxError => error
35
51
  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
52
  end
37
- @rows = data ? validate(data).to_a : []
53
+ end
54
+
55
+ def prepare_erb(content)
56
+ erb = ERB.new(content)
57
+ erb.filename = @file
58
+ erb
38
59
  end
39
60
 
40
61
  def render(content)
41
62
  context = ActiveRecord::FixtureSet::RenderContext.create_subclass.new
42
- ERB.new(content).result(context.get_binding)
63
+ prepare_erb(content).result(context.get_binding)
43
64
  end
44
65
 
45
66
  # Validate our unmarshalled data.
@@ -1,6 +1,7 @@
1
1
  require 'erb'
2
2
  require 'yaml'
3
3
  require 'zlib'
4
+ require 'set'
4
5
  require 'active_support/dependencies'
5
6
  require 'active_support/core_ext/digest/uuid'
6
7
  require 'active_record/fixture_set/file'
@@ -88,7 +89,7 @@ module ActiveRecord
88
89
  # end
89
90
  #
90
91
  # In order to use these methods to access fixtured data within your testcases, you must specify one of the
91
- # following in your <tt>ActiveSupport::TestCase</tt>-derived class:
92
+ # following in your ActiveSupport::TestCase-derived class:
92
93
  #
93
94
  # - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above)
94
95
  # self.use_instantiated_fixtures = true
@@ -109,7 +110,7 @@ module ActiveRecord
109
110
  # <% 1.upto(1000) do |i| %>
110
111
  # fix_<%= i %>:
111
112
  # id: <%= i %>
112
- # name: guy_<%= 1 %>
113
+ # name: guy_<%= i %>
113
114
  # <% end %>
114
115
  #
115
116
  # This will create 1000 very simple fixtures.
@@ -123,7 +124,7 @@ module ActiveRecord
123
124
  #
124
125
  # Helper methods defined in a fixture will not be available in other fixtures, to prevent against
125
126
  # unwanted inter-test dependencies. Methods used by multiple fixtures should be defined in a module
126
- # that is included in <tt>ActiveRecord::FixtureSet.context_class</tt>.
127
+ # that is included in ActiveRecord::FixtureSet.context_class.
127
128
  #
128
129
  # - define a helper method in `test_helper.rb`
129
130
  # module FixtureFileHelpers
@@ -131,20 +132,20 @@ module ActiveRecord
131
132
  # Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
132
133
  # end
133
134
  # end
134
- # ActiveRecord::FixtureSet.context_class.send :include, FixtureFileHelpers
135
+ # ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
135
136
  #
136
137
  # - use the helper method in a fixture
137
138
  # photo:
138
139
  # name: kitten.png
139
140
  # sha: <%= file_sha 'files/kitten.png' %>
140
141
  #
141
- # = Transactional Fixtures
142
+ # = Transactional Tests
142
143
  #
143
144
  # Test cases can use begin+rollback to isolate their changes to the database instead of having to
144
145
  # delete+insert for every test case.
145
146
  #
146
147
  # class FooTest < ActiveSupport::TestCase
147
- # self.use_transactional_fixtures = true
148
+ # self.use_transactional_tests = true
148
149
  #
149
150
  # test "godzilla" do
150
151
  # assert !Foo.all.empty?
@@ -158,14 +159,14 @@ module ActiveRecord
158
159
  # end
159
160
  #
160
161
  # If you preload your test database with all fixture data (probably in the rake task) and use
161
- # transactional fixtures, then you may omit all fixtures declarations in your test cases since
162
+ # transactional tests, then you may omit all fixtures declarations in your test cases since
162
163
  # all the data's already there and every case rolls back its changes.
163
164
  #
164
165
  # In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to
165
166
  # true. This will provide access to fixture data for every table that has been loaded through
166
167
  # fixtures (depending on the value of +use_instantiated_fixtures+).
167
168
  #
168
- # When *not* to use transactional fixtures:
169
+ # When *not* to use transactional tests:
169
170
  #
170
171
  # 1. You're testing whether a transaction works correctly. Nested transactions don't commit until
171
172
  # all parent transactions commit, particularly, the fixtures transaction which is begun in setup
@@ -394,6 +395,20 @@ module ActiveRecord
394
395
  # <<: *DEFAULTS
395
396
  #
396
397
  # Any fixture labeled "DEFAULTS" is safely ignored.
398
+ #
399
+ # == Configure the fixture model class
400
+ #
401
+ # It's possible to set the fixture's model class directly in the YAML file.
402
+ # This is helpful when fixtures are loaded outside tests and
403
+ # +set_fixture_class+ is not available (e.g.
404
+ # when running <tt>rails db:fixtures:load</tt>).
405
+ #
406
+ # _fixture:
407
+ # model_class: User
408
+ # david:
409
+ # name: David
410
+ #
411
+ # Any fixtures labeled "_fixture" are safely ignored.
397
412
  class FixtureSet
398
413
  #--
399
414
  # An instance of FixtureSet is normally stored in a single YAML file and
@@ -521,12 +536,16 @@ module ActiveRecord
521
536
  update_all_loaded_fixtures fixtures_map
522
537
 
523
538
  connection.transaction(:requires_new => true) do
539
+ deleted_tables = Set.new
524
540
  fixture_sets.each do |fs|
525
541
  conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
526
542
  table_rows = fs.table_rows
527
543
 
528
544
  table_rows.each_key do |table|
529
- conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
545
+ unless deleted_tables.include? table
546
+ conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
547
+ end
548
+ deleted_tables << table
530
549
  end
531
550
 
532
551
  table_rows.each do |fixture_set_name, rows|
@@ -573,21 +592,16 @@ module ActiveRecord
573
592
  @name = name
574
593
  @path = path
575
594
  @config = config
576
- @model_class = nil
577
595
 
578
- if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
579
- @model_class = class_name
580
- else
581
- @model_class = class_name.safe_constantize if class_name
582
- end
596
+ self.model_class = class_name
597
+
598
+ @fixtures = read_fixture_files(path)
583
599
 
584
600
  @connection = connection
585
601
 
586
602
  @table_name = ( model_class.respond_to?(:table_name) ?
587
603
  model_class.table_name :
588
604
  self.class.default_fixture_table_name(name, config) )
589
-
590
- @fixtures = read_fixture_files path, @model_class
591
605
  end
592
606
 
593
607
  def [](x)
@@ -610,7 +624,6 @@ module ActiveRecord
610
624
  # a list of rows to insert to that table.
611
625
  def table_rows
612
626
  now = config.default_timezone == :utc ? Time.now.utc : Time.now
613
- now = now.to_s(:db)
614
627
 
615
628
  # allow a standard key to be used for doing defaults in YAML
616
629
  fixtures.delete('DEFAULTS')
@@ -639,6 +652,13 @@ module ActiveRecord
639
652
  row[primary_key_name] = ActiveRecord::FixtureSet.identify(label, primary_key_type)
640
653
  end
641
654
 
655
+ # Resolve enums
656
+ model_class.defined_enums.each do |name, values|
657
+ if row.include?(name)
658
+ row[name] = values.fetch(row[name], row[name])
659
+ end
660
+ end
661
+
642
662
  # If STI is used, find the correct subclass for association reflection
643
663
  reflection_class =
644
664
  if row.include?(inheritance_column_name)
@@ -659,7 +679,7 @@ module ActiveRecord
659
679
  row[association.foreign_type] = $1
660
680
  end
661
681
 
662
- fk_type = reflection_class.columns_hash[fk_name].type
682
+ fk_type = reflection_class.type_for_attribute(fk_name).type
663
683
  row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
664
684
  end
665
685
  when :has_many
@@ -689,7 +709,7 @@ module ActiveRecord
689
709
  end
690
710
 
691
711
  def primary_key_type
692
- @association.klass.column_types[@association.klass.primary_key].type
712
+ @association.klass.type_for_attribute(@association.klass.primary_key).type
693
713
  end
694
714
  end
695
715
 
@@ -713,7 +733,7 @@ module ActiveRecord
713
733
  end
714
734
 
715
735
  def primary_key_type
716
- @primary_key_type ||= model_class && model_class.column_types[model_class.primary_key].type
736
+ @primary_key_type ||= model_class && model_class.type_for_attribute(model_class.primary_key).type
717
737
  end
718
738
 
719
739
  def add_join_records(rows, row, association)
@@ -747,16 +767,28 @@ module ActiveRecord
747
767
  end
748
768
 
749
769
  def column_names
750
- @column_names ||= @connection.columns(@table_name).collect { |c| c.name }
770
+ @column_names ||= @connection.columns(@table_name).collect(&:name)
771
+ end
772
+
773
+ def model_class=(class_name)
774
+ if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
775
+ @model_class = class_name
776
+ else
777
+ @model_class = class_name.safe_constantize if class_name
778
+ end
751
779
  end
752
780
 
753
- def read_fixture_files(path, model_class)
781
+ # Loads the fixtures from the YAML file at +path+.
782
+ # If the file sets the +model_class+ and current instance value is not set,
783
+ # it uses the file value.
784
+ def read_fixture_files(path)
754
785
  yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
755
786
  ::File.file?(f)
756
787
  } + [yaml_file_path(path)]
757
788
 
758
789
  yaml_files.each_with_object({}) do |file, fixtures|
759
790
  FixtureSet::File.open(file) do |fh|
791
+ self.model_class ||= fh.model_class if fh.model_class
760
792
  fh.each do |fixture_name, row|
761
793
  fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
762
794
  end
@@ -770,12 +802,6 @@ module ActiveRecord
770
802
 
771
803
  end
772
804
 
773
- #--
774
- # Deprecate 'Fixtures' in favor of 'FixtureSet'.
775
- #++
776
- # :nodoc:
777
- Fixtures = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActiveRecord::Fixtures', 'ActiveRecord::FixtureSet')
778
-
779
805
  class Fixture #:nodoc:
780
806
  include Enumerable
781
807
 
@@ -822,12 +848,12 @@ module ActiveRecord
822
848
  module TestFixtures
823
849
  extend ActiveSupport::Concern
824
850
 
825
- def before_setup
851
+ def before_setup # :nodoc:
826
852
  setup_fixtures
827
853
  super
828
854
  end
829
855
 
830
- def after_teardown
856
+ def after_teardown # :nodoc:
831
857
  super
832
858
  teardown_fixtures
833
859
  end
@@ -836,19 +862,29 @@ module ActiveRecord
836
862
  class_attribute :fixture_path, :instance_writer => false
837
863
  class_attribute :fixture_table_names
838
864
  class_attribute :fixture_class_names
865
+ class_attribute :use_transactional_tests
839
866
  class_attribute :use_transactional_fixtures
840
867
  class_attribute :use_instantiated_fixtures # true, false, or :no_instances
841
868
  class_attribute :pre_loaded_fixtures
842
869
  class_attribute :config
843
870
 
871
+ singleton_class.deprecate 'use_transactional_fixtures=' => 'use use_transactional_tests= instead'
872
+
844
873
  self.fixture_table_names = []
845
- self.use_transactional_fixtures = true
846
874
  self.use_instantiated_fixtures = false
847
875
  self.pre_loaded_fixtures = false
848
876
  self.config = ActiveRecord::Base
849
877
 
850
- self.fixture_class_names = Hash.new do |h, fixture_set_name|
851
- h[fixture_set_name] = ActiveRecord::FixtureSet.default_fixture_model_name(fixture_set_name, self.config)
878
+ self.fixture_class_names = {}
879
+
880
+ silence_warnings do
881
+ define_singleton_method :use_transactional_tests do
882
+ if use_transactional_fixtures.nil?
883
+ true
884
+ else
885
+ use_transactional_fixtures
886
+ end
887
+ end
852
888
  end
853
889
  end
854
890
 
@@ -870,7 +906,7 @@ module ActiveRecord
870
906
  fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
871
907
  fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
872
908
  else
873
- fixture_set_names = fixture_set_names.flatten.map { |n| n.to_s }
909
+ fixture_set_names = fixture_set_names.flatten.map(&:to_s)
874
910
  end
875
911
 
876
912
  self.fixture_table_names |= fixture_set_names
@@ -890,7 +926,7 @@ module ActiveRecord
890
926
  @fixture_cache[fs_name] ||= {}
891
927
 
892
928
  instances = fixture_names.map do |f_name|
893
- f_name = f_name.to_s
929
+ f_name = f_name.to_s if f_name.is_a?(Symbol)
894
930
  @fixture_cache[fs_name].delete(f_name) if force_reload
895
931
 
896
932
  if @loaded_fixtures[fs_name][f_name]
@@ -910,7 +946,7 @@ module ActiveRecord
910
946
 
911
947
  def uses_transaction(*methods)
912
948
  @uses_transaction = [] unless defined?(@uses_transaction)
913
- @uses_transaction.concat methods.map { |m| m.to_s }
949
+ @uses_transaction.concat methods.map(&:to_s)
914
950
  end
915
951
 
916
952
  def uses_transaction?(method)
@@ -920,13 +956,13 @@ module ActiveRecord
920
956
  end
921
957
 
922
958
  def run_in_transaction?
923
- use_transactional_fixtures &&
959
+ use_transactional_tests &&
924
960
  !self.class.uses_transaction?(method_name)
925
961
  end
926
962
 
927
963
  def setup_fixtures(config = ActiveRecord::Base)
928
- if pre_loaded_fixtures && !use_transactional_fixtures
929
- raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
964
+ if pre_loaded_fixtures && !use_transactional_tests
965
+ raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_tests'
930
966
  end
931
967
 
932
968
  @fixture_cache = {}
@@ -5,10 +5,10 @@ module ActiveRecord
5
5
  end
6
6
 
7
7
  module VERSION
8
- MAJOR = 4
9
- MINOR = 2
10
- TINY = 11
11
- PRE = "1"
8
+ MAJOR = 5
9
+ MINOR = 0
10
+ TINY = 0
11
+ PRE = nil
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
14
  end
@@ -51,11 +51,15 @@ module ActiveRecord
51
51
  end
52
52
 
53
53
  attrs = args.first
54
- if subclass_from_attributes?(attrs)
54
+ if has_attribute?(inheritance_column)
55
55
  subclass = subclass_from_attributes(attrs)
56
+
57
+ if subclass.nil? && base_class == self
58
+ subclass = subclass_from_attributes(column_defaults)
59
+ end
56
60
  end
57
61
 
58
- if subclass
62
+ if subclass && subclass != self
59
63
  subclass.new(*args, &block)
60
64
  else
61
65
  super
@@ -79,20 +83,10 @@ module ActiveRecord
79
83
  :true == (@finder_needs_type_condition ||= descends_from_active_record? ? :false : :true)
80
84
  end
81
85
 
82
- def symbolized_base_class
83
- ActiveSupport::Deprecation.warn('`ActiveRecord::Base.symbolized_base_class` is deprecated and will be removed without replacement.')
84
- @symbolized_base_class ||= base_class.to_s.to_sym
85
- end
86
-
87
- def symbolized_sti_name
88
- ActiveSupport::Deprecation.warn('`ActiveRecord::Base.symbolized_sti_name` is deprecated and will be removed without replacement.')
89
- @symbolized_sti_name ||= sti_name.present? ? sti_name.to_sym : symbolized_base_class
90
- end
91
-
92
86
  # Returns the class descending directly from ActiveRecord::Base, or
93
87
  # an abstract class, if any, in the inheritance hierarchy.
94
88
  #
95
- # If A extends AR::Base, A.base_class will return A. If B descends from A
89
+ # If A extends ActiveRecord::Base, A.base_class will return A. If B descends from A
96
90
  # through some arbitrarily deep hierarchy, B.base_class will return A.
97
91
  #
98
92
  # If B < A and C < B and if A is an abstract_class then both B.base_class
@@ -173,49 +167,47 @@ module ActiveRecord
173
167
  end
174
168
 
175
169
  def using_single_table_inheritance?(record)
176
- record[inheritance_column].present? && columns_hash.include?(inheritance_column)
170
+ record[inheritance_column].present? && has_attribute?(inheritance_column)
177
171
  end
178
172
 
179
173
  def find_sti_class(type_name)
180
- if store_full_sti_class
181
- ActiveSupport::Dependencies.constantize(type_name)
182
- else
183
- compute_type(type_name)
174
+ type_name = base_class.type_for_attribute(inheritance_column).cast(type_name)
175
+ subclass = begin
176
+ if store_full_sti_class
177
+ ActiveSupport::Dependencies.constantize(type_name)
178
+ else
179
+ compute_type(type_name)
180
+ end
181
+ rescue NameError
182
+ raise SubclassNotFound,
183
+ "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
184
+ "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
185
+ "Please rename this column if you didn't intend it to be used for storing the inheritance class " \
186
+ "or overwrite #{name}.inheritance_column to use another column for that information."
184
187
  end
185
- rescue NameError
186
- raise SubclassNotFound,
187
- "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " +
188
- "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " +
189
- "Please rename this column if you didn't intend it to be used for storing the inheritance class " +
190
- "or overwrite #{name}.inheritance_column to use another column for that information."
188
+ unless subclass == self || descendants.include?(subclass)
189
+ raise SubclassNotFound, "Invalid single-table inheritance type: #{subclass.name} is not a subclass of #{name}"
190
+ end
191
+ subclass
191
192
  end
192
193
 
193
194
  def type_condition(table = arel_table)
194
- sti_column = table[inheritance_column]
195
- sti_names = ([self] + descendants).map { |model| model.sti_name }
195
+ sti_column = arel_attribute(inheritance_column, table)
196
+ sti_names = ([self] + descendants).map(&:sti_name)
196
197
 
197
198
  sti_column.in(sti_names)
198
199
  end
199
200
 
200
201
  # Detect the subclass from the inheritance column of attrs. If the inheritance column value
201
202
  # is not self or a valid subclass, raises ActiveRecord::SubclassNotFound
202
- # If this is a StrongParameters hash, and access to inheritance_column is not permitted,
203
- # this will ignore the inheritance column and return nil
204
- def subclass_from_attributes?(attrs)
205
- columns_hash.include?(inheritance_column) && attrs.is_a?(Hash)
206
- end
207
-
208
203
  def subclass_from_attributes(attrs)
209
- subclass_name = attrs.with_indifferent_access[inheritance_column]
210
-
211
- if subclass_name.present? && subclass_name != self.name
212
- subclass = subclass_name.safe_constantize
204
+ attrs = attrs.to_h if attrs.respond_to?(:permitted?)
205
+ if attrs.is_a?(Hash)
206
+ subclass_name = attrs.with_indifferent_access[inheritance_column]
213
207
 
214
- unless descendants.include?(subclass)
215
- raise ActiveRecord::SubclassNotFound.new("Invalid single-table inheritance type: #{subclass_name} is not a subclass of #{name}")
208
+ if subclass_name.present?
209
+ find_sti_class(subclass_name)
216
210
  end
217
-
218
- subclass
219
211
  end
220
212
  end
221
213
  end