activerecord 4.2.11 → 5.2.4.1

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 (274) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +580 -1626
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -11
  5. data/examples/performance.rb +32 -31
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +263 -249
  8. data/lib/active_record/association_relation.rb +11 -6
  9. data/lib/active_record/associations/alias_tracker.rb +29 -35
  10. data/lib/active_record/associations/association.rb +77 -43
  11. data/lib/active_record/associations/association_scope.rb +106 -133
  12. data/lib/active_record/associations/belongs_to_association.rb +52 -41
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  14. data/lib/active_record/associations/builder/association.rb +29 -38
  15. data/lib/active_record/associations/builder/belongs_to.rb +77 -30
  16. data/lib/active_record/associations/builder/collection_association.rb +9 -22
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -35
  18. data/lib/active_record/associations/builder/has_many.rb +6 -4
  19. data/lib/active_record/associations/builder/has_one.rb +13 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +15 -11
  21. data/lib/active_record/associations/collection_association.rb +139 -280
  22. data/lib/active_record/associations/collection_proxy.rb +231 -133
  23. data/lib/active_record/associations/foreign_association.rb +3 -1
  24. data/lib/active_record/associations/has_many_association.rb +34 -89
  25. data/lib/active_record/associations/has_many_through_association.rb +49 -76
  26. data/lib/active_record/associations/has_one_association.rb +38 -24
  27. data/lib/active_record/associations/has_one_through_association.rb +18 -9
  28. data/lib/active_record/associations/join_dependency/join_association.rb +40 -87
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  31. data/lib/active_record/associations/join_dependency.rb +133 -159
  32. data/lib/active_record/associations/preloader/association.rb +85 -120
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -74
  34. data/lib/active_record/associations/preloader.rb +81 -91
  35. data/lib/active_record/associations/singular_association.rb +27 -34
  36. data/lib/active_record/associations/through_association.rb +38 -18
  37. data/lib/active_record/associations.rb +1732 -1597
  38. data/lib/active_record/attribute_assignment.rb +58 -182
  39. data/lib/active_record/attribute_decorators.rb +39 -15
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +10 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +94 -135
  42. data/lib/active_record/attribute_methods/primary_key.rb +86 -71
  43. data/lib/active_record/attribute_methods/query.rb +4 -2
  44. data/lib/active_record/attribute_methods/read.rb +45 -63
  45. data/lib/active_record/attribute_methods/serialization.rb +40 -20
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
  47. data/lib/active_record/attribute_methods/write.rb +30 -45
  48. data/lib/active_record/attribute_methods.rb +166 -109
  49. data/lib/active_record/attributes.rb +201 -82
  50. data/lib/active_record/autosave_association.rb +94 -36
  51. data/lib/active_record/base.rb +57 -44
  52. data/lib/active_record/callbacks.rb +97 -57
  53. data/lib/active_record/coders/json.rb +3 -1
  54. data/lib/active_record/coders/yaml_column.rb +24 -12
  55. data/lib/active_record/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -290
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +237 -90
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +71 -21
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +118 -52
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +318 -217
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +570 -228
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +138 -70
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +325 -202
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +542 -601
  69. data/lib/active_record/connection_adapters/column.rb +50 -41
  70. data/lib/active_record/connection_adapters/connection_specification.rb +147 -135
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +41 -180
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +45 -114
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +10 -6
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -7
  99. data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +55 -53
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +107 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +144 -90
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -284
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +432 -323
  117. data/lib/active_record/connection_adapters/schema_cache.rb +48 -24
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +269 -308
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +40 -27
  128. data/lib/active_record/core.rb +178 -198
  129. data/lib/active_record/counter_cache.rb +79 -36
  130. data/lib/active_record/define_callbacks.rb +22 -0
  131. data/lib/active_record/dynamic_matchers.rb +87 -105
  132. data/lib/active_record/enum.rb +135 -88
  133. data/lib/active_record/errors.rb +179 -52
  134. data/lib/active_record/explain.rb +23 -11
  135. data/lib/active_record/explain_registry.rb +4 -2
  136. data/lib/active_record/explain_subscriber.rb +10 -5
  137. data/lib/active_record/fixture_set/file.rb +35 -9
  138. data/lib/active_record/fixtures.rb +188 -132
  139. data/lib/active_record/gem_version.rb +5 -3
  140. data/lib/active_record/inheritance.rb +148 -112
  141. data/lib/active_record/integration.rb +70 -28
  142. data/lib/active_record/internal_metadata.rb +45 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +21 -3
  144. data/lib/active_record/locale/en.yml +3 -2
  145. data/lib/active_record/locking/optimistic.rb +88 -96
  146. data/lib/active_record/locking/pessimistic.rb +15 -3
  147. data/lib/active_record/log_subscriber.rb +95 -33
  148. data/lib/active_record/migration/command_recorder.rb +133 -90
  149. data/lib/active_record/migration/compatibility.rb +217 -0
  150. data/lib/active_record/migration/join_table.rb +8 -6
  151. data/lib/active_record/migration.rb +581 -282
  152. data/lib/active_record/model_schema.rb +290 -111
  153. data/lib/active_record/nested_attributes.rb +264 -222
  154. data/lib/active_record/no_touching.rb +7 -1
  155. data/lib/active_record/null_relation.rb +24 -37
  156. data/lib/active_record/persistence.rb +347 -119
  157. data/lib/active_record/query_cache.rb +13 -24
  158. data/lib/active_record/querying.rb +19 -17
  159. data/lib/active_record/railtie.rb +94 -32
  160. data/lib/active_record/railties/console_sandbox.rb +2 -0
  161. data/lib/active_record/railties/controller_runtime.rb +9 -3
  162. data/lib/active_record/railties/databases.rake +149 -156
  163. data/lib/active_record/readonly_attributes.rb +5 -4
  164. data/lib/active_record/reflection.rb +414 -267
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  166. data/lib/active_record/relation/batches.rb +204 -55
  167. data/lib/active_record/relation/calculations.rb +256 -248
  168. data/lib/active_record/relation/delegation.rb +67 -60
  169. data/lib/active_record/relation/finder_methods.rb +288 -239
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +86 -86
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -24
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  174. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  179. data/lib/active_record/relation/predicate_builder.rb +116 -119
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +448 -393
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +11 -13
  184. data/lib/active_record/relation/where_clause.rb +186 -0
  185. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  186. data/lib/active_record/relation.rb +287 -340
  187. data/lib/active_record/result.rb +54 -36
  188. data/lib/active_record/runtime_registry.rb +6 -4
  189. data/lib/active_record/sanitization.rb +155 -124
  190. data/lib/active_record/schema.rb +30 -24
  191. data/lib/active_record/schema_dumper.rb +91 -87
  192. data/lib/active_record/schema_migration.rb +19 -16
  193. data/lib/active_record/scoping/default.rb +102 -85
  194. data/lib/active_record/scoping/named.rb +81 -32
  195. data/lib/active_record/scoping.rb +45 -26
  196. data/lib/active_record/secure_token.rb +40 -0
  197. data/lib/active_record/serialization.rb +5 -5
  198. data/lib/active_record/statement_cache.rb +45 -35
  199. data/lib/active_record/store.rb +42 -36
  200. data/lib/active_record/suppressor.rb +61 -0
  201. data/lib/active_record/table_metadata.rb +82 -0
  202. data/lib/active_record/tasks/database_tasks.rb +134 -96
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +56 -100
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +83 -41
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -16
  206. data/lib/active_record/timestamp.rb +70 -38
  207. data/lib/active_record/touch_later.rb +64 -0
  208. data/lib/active_record/transactions.rb +199 -124
  209. data/lib/active_record/translation.rb +2 -0
  210. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  211. data/lib/active_record/type/date.rb +4 -45
  212. data/lib/active_record/type/date_time.rb +4 -49
  213. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  214. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  215. data/lib/active_record/type/internal/timezone.rb +17 -0
  216. data/lib/active_record/type/json.rb +30 -0
  217. data/lib/active_record/type/serialized.rb +24 -15
  218. data/lib/active_record/type/text.rb +2 -2
  219. data/lib/active_record/type/time.rb +11 -16
  220. data/lib/active_record/type/type_map.rb +15 -17
  221. data/lib/active_record/type/unsigned_integer.rb +9 -7
  222. data/lib/active_record/type.rb +79 -23
  223. data/lib/active_record/type_caster/connection.rb +33 -0
  224. data/lib/active_record/type_caster/map.rb +23 -0
  225. data/lib/active_record/type_caster.rb +9 -0
  226. data/lib/active_record/validations/absence.rb +25 -0
  227. data/lib/active_record/validations/associated.rb +13 -4
  228. data/lib/active_record/validations/length.rb +26 -0
  229. data/lib/active_record/validations/presence.rb +14 -13
  230. data/lib/active_record/validations/uniqueness.rb +40 -41
  231. data/lib/active_record/validations.rb +38 -35
  232. data/lib/active_record/version.rb +3 -1
  233. data/lib/active_record.rb +34 -22
  234. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  235. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  236. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -35
  237. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +8 -3
  238. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -1
  239. data/lib/rails/generators/active_record/migration.rb +18 -1
  240. data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
  241. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +3 -0
  242. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  243. data/lib/rails/generators/active_record.rb +7 -5
  244. metadata +72 -50
  245. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  246. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  247. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  248. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  249. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  250. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  251. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  252. data/lib/active_record/attribute.rb +0 -163
  253. data/lib/active_record/attribute_set/builder.rb +0 -106
  254. data/lib/active_record/attribute_set.rb +0 -81
  255. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  256. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  257. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  258. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  259. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  260. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  261. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  262. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  263. data/lib/active_record/type/big_integer.rb +0 -13
  264. data/lib/active_record/type/binary.rb +0 -50
  265. data/lib/active_record/type/boolean.rb +0 -31
  266. data/lib/active_record/type/decimal.rb +0 -64
  267. data/lib/active_record/type/decorator.rb +0 -14
  268. data/lib/active_record/type/float.rb +0 -19
  269. data/lib/active_record/type/integer.rb +0 -59
  270. data/lib/active_record/type/mutable.rb +0 -16
  271. data/lib/active_record/type/numeric.rb +0 -36
  272. data/lib/active_record/type/string.rb +0 -40
  273. data/lib/active_record/type/time_value.rb +0 -38
  274. data/lib/active_record/type/value.rb +0 -110
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module TypeCaster
5
+ class Map # :nodoc:
6
+ def initialize(types)
7
+ @types = types
8
+ end
9
+
10
+ def type_cast_for_database(attr_name, value)
11
+ return value if value.is_a?(Arel::Nodes::BindParam)
12
+ type = types.type_for_attribute(attr_name)
13
+ type.serialize(value)
14
+ end
15
+
16
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
17
+ # Workaround for Ruby 2.2 "private attribute?" warning.
18
+ protected
19
+
20
+ attr_reader :types
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/type_caster/map"
4
+ require "active_record/type_caster/connection"
5
+
6
+ module ActiveRecord
7
+ module TypeCaster # :nodoc:
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Validations
5
+ class AbsenceValidator < ActiveModel::Validations::AbsenceValidator # :nodoc:
6
+ def validate_each(record, attribute, association_or_value)
7
+ if record.class._reflect_on_association(attribute)
8
+ association_or_value = Array.wrap(association_or_value).reject(&:marked_for_destruction?)
9
+ end
10
+ super
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ # Validates that the specified attributes are not present (as defined by
16
+ # Object#present?). If the attribute is an association, the associated object
17
+ # is considered absent if it was marked for destruction.
18
+ #
19
+ # See ActiveModel::Validations::HelperMethods.validates_absence_of for more information.
20
+ def validates_absence_of(*attr_names)
21
+ validates_with AbsenceValidator, _merge_attributes(attr_names)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,11 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Validations
3
5
  class AssociatedValidator < ActiveModel::EachValidator #:nodoc:
4
6
  def validate_each(record, attribute, value)
5
- if Array.wrap(value).reject {|r| r.marked_for_destruction? || r.valid?}.any?
6
- record.errors.add(attribute, :invalid, options.merge(:value => value))
7
+ if Array(value).reject { |r| valid_object?(r) }.any?
8
+ record.errors.add(attribute, :invalid, options.merge(value: value))
7
9
  end
8
10
  end
11
+
12
+ private
13
+
14
+ def valid_object?(record)
15
+ (record.respond_to?(:marked_for_destruction?) && record.marked_for_destruction?) || record.valid?
16
+ end
9
17
  end
10
18
 
11
19
  module ClassMethods
@@ -24,13 +32,14 @@ module ActiveRecord
24
32
  #
25
33
  # NOTE: This validation will not fail if the association hasn't been
26
34
  # assigned. If you want to ensure that the association is both present and
27
- # guaranteed to be valid, you also need to use +validates_presence_of+.
35
+ # guaranteed to be valid, you also need to use
36
+ # {validates_presence_of}[rdoc-ref:Validations::ClassMethods#validates_presence_of].
28
37
  #
29
38
  # Configuration options:
30
39
  #
31
40
  # * <tt>:message</tt> - A custom error message (default is: "is invalid").
32
41
  # * <tt>:on</tt> - Specifies the contexts where this validation is active.
33
- # Runs in all validation contexts by default (nil). You can pass a symbol
42
+ # Runs in all validation contexts by default +nil+. You can pass a symbol
34
43
  # or an array of symbols. (e.g. <tt>on: :create</tt> or
35
44
  # <tt>on: :custom_validation_context</tt> or
36
45
  # <tt>on: [:create, :custom_validation_context]</tt>)
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Validations
5
+ class LengthValidator < ActiveModel::Validations::LengthValidator # :nodoc:
6
+ def validate_each(record, attribute, association_or_value)
7
+ if association_or_value.respond_to?(:loaded?) && association_or_value.loaded?
8
+ association_or_value = association_or_value.target.reject(&:marked_for_destruction?)
9
+ end
10
+ super
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ # Validates that the specified attributes match the length restrictions supplied.
16
+ # If the attribute is an association, records that are marked for destruction are not counted.
17
+ #
18
+ # See ActiveModel::Validations::HelperMethods.validates_length_of for more information.
19
+ def validates_length_of(*attr_names)
20
+ validates_with LengthValidator, _merge_attributes(attr_names)
21
+ end
22
+
23
+ alias_method :validates_size_of, :validates_length_of
24
+ end
25
+ end
26
+ end
@@ -1,17 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Validations
3
5
  class PresenceValidator < ActiveModel::Validations::PresenceValidator # :nodoc:
4
- def validate(record)
5
- super
6
- attributes.each do |attribute|
7
- next unless record.class._reflect_on_association(attribute)
8
- associated_records = Array.wrap(record.send(attribute))
9
-
10
- # Superclass validates presence. Ensure present records aren't about to be destroyed.
11
- if associated_records.present? && associated_records.all? { |r| r.marked_for_destruction? }
12
- record.errors.add(attribute, :blank, options)
13
- end
6
+ def validate_each(record, attribute, association_or_value)
7
+ if record.class._reflect_on_association(attribute)
8
+ association_or_value = Array.wrap(association_or_value).reject(&:marked_for_destruction?)
14
9
  end
10
+ super
15
11
  end
16
12
  end
17
13
 
@@ -36,16 +32,21 @@ module ActiveRecord
36
32
  # This is due to the way Object#blank? handles boolean values:
37
33
  # <tt>false.blank? # => true</tt>.
38
34
  #
39
- # This validator defers to the ActiveModel validation for presence, adding the
35
+ # This validator defers to the Active Model validation for presence, adding the
40
36
  # check to see that an associated object is not marked for destruction. This
41
37
  # prevents the parent object from validating successfully and saving, which then
42
38
  # deletes the associated object, thus putting the parent object into an invalid
43
39
  # state.
44
40
  #
41
+ # NOTE: This validation will not fail while using it with an association
42
+ # if the latter was assigned but not valid. If you want to ensure that
43
+ # it is both present and valid, you also need to use
44
+ # {validates_associated}[rdoc-ref:Validations::ClassMethods#validates_associated].
45
+ #
45
46
  # Configuration options:
46
47
  # * <tt>:message</tt> - A custom error message (default is: "can't be blank").
47
48
  # * <tt>:on</tt> - Specifies the contexts where this validation is active.
48
- # Runs in all validation contexts by default (nil). You can pass a symbol
49
+ # Runs in all validation contexts by default +nil+. You can pass a symbol
49
50
  # or an array of symbols. (e.g. <tt>on: :create</tt> or
50
51
  # <tt>on: :custom_validation_context</tt> or
51
52
  # <tt>on: [:create, :custom_validation_context]</tt>)
@@ -58,7 +59,7 @@ module ActiveRecord
58
59
  # or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The method,
59
60
  # proc or string should return or evaluate to a +true+ or +false+ value.
60
61
  # * <tt>:strict</tt> - Specifies whether validation should be strict.
61
- # See <tt>ActiveModel::Validation#validates!</tt> for more information.
62
+ # See ActiveModel::Validations#validates! for more information.
62
63
  def validates_presence_of(*attr_names)
63
64
  validates_with PresenceValidator, _merge_attributes(attr_names)
64
65
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Validations
3
5
  class UniquenessValidator < ActiveModel::EachValidator # :nodoc:
@@ -6,30 +8,28 @@ module ActiveRecord
6
8
  raise ArgumentError, "#{options[:conditions]} was passed as :conditions but is not callable. " \
7
9
  "Pass a callable instead: `conditions: -> { where(approved: true) }`"
8
10
  end
11
+ unless Array(options[:scope]).all? { |scope| scope.respond_to?(:to_sym) }
12
+ raise ArgumentError, "#{options[:scope]} is not supported format for :scope option. " \
13
+ "Pass a symbol or an array of symbols instead: `scope: :user_id`"
14
+ end
9
15
  super({ case_sensitive: true }.merge!(options))
10
16
  @klass = options[:class]
11
17
  end
12
18
 
13
19
  def validate_each(record, attribute, value)
14
20
  finder_class = find_finder_class_for(record)
15
- table = finder_class.arel_table
16
21
  value = map_enum_attribute(finder_class, attribute, value)
17
22
 
18
- begin
19
- relation = build_relation(finder_class, table, attribute, value)
20
- if record.persisted?
21
- if finder_class.primary_key
22
- relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id))
23
- else
24
- raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
25
- end
23
+ relation = build_relation(finder_class, attribute, value)
24
+ if record.persisted?
25
+ if finder_class.primary_key
26
+ relation = relation.where.not(finder_class.primary_key => record.id_in_database)
27
+ else
28
+ raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
26
29
  end
27
- relation = scope_relation(record, table, relation)
28
- relation = finder_class.unscoped.where(relation)
29
- relation = relation.merge(options[:conditions]) if options[:conditions]
30
- rescue RangeError
31
- relation = finder_class.none
32
30
  end
31
+ relation = scope_relation(record, relation)
32
+ relation = relation.merge(options[:conditions]) if options[:conditions]
33
33
 
34
34
  if relation.exists?
35
35
  error_options = options.except(:case_sensitive, :scope, :conditions)
@@ -39,13 +39,13 @@ module ActiveRecord
39
39
  end
40
40
  end
41
41
 
42
- protected
42
+ private
43
43
  # The check for an existing value should be run from a class that
44
44
  # isn't abstract. This means working down from the current class
45
45
  # (self), to the first non-abstract class. Since classes don't know
46
46
  # their subclasses, we have to build the hierarchy between self and
47
47
  # the record's class.
48
- def find_finder_class_for(record) #:nodoc:
48
+ def find_finder_class_for(record)
49
49
  class_hierarchy = [record.class]
50
50
 
51
51
  while class_hierarchy.first != @klass
@@ -55,43 +55,44 @@ module ActiveRecord
55
55
  class_hierarchy.detect { |klass| !klass.abstract_class? }
56
56
  end
57
57
 
58
- def build_relation(klass, table, attribute, value) #:nodoc:
58
+ def build_relation(klass, attribute, value)
59
59
  if reflection = klass._reflect_on_association(attribute)
60
60
  attribute = reflection.foreign_key
61
61
  value = value.attributes[reflection.klass.primary_key] unless value.nil?
62
62
  end
63
63
 
64
- attribute_name = attribute.to_s
64
+ if value.nil?
65
+ return klass.unscoped.where!(attribute => value)
66
+ end
65
67
 
66
68
  # the attribute may be an aliased attribute
67
- if klass.attribute_aliases[attribute_name]
68
- attribute = klass.attribute_aliases[attribute_name]
69
- attribute_name = attribute.to_s
69
+ if klass.attribute_alias?(attribute)
70
+ attribute = klass.attribute_alias(attribute)
70
71
  end
71
72
 
73
+ attribute_name = attribute.to_s
74
+ value = klass.predicate_builder.build_bind_attribute(attribute_name, value)
75
+
76
+ table = klass.arel_table
72
77
  column = klass.columns_hash[attribute_name]
73
- value = klass.connection.type_cast(value, column)
74
- if value.is_a?(String) && column.limit
75
- value = value.to_s[0, column.limit]
76
- end
77
78
 
78
- if !options[:case_sensitive] && value && column.text?
79
+ comparison = if !options[:case_sensitive]
79
80
  # will use SQL LOWER function before comparison, unless it detects a case insensitive collation
80
81
  klass.connection.case_insensitive_comparison(table, attribute, column, value)
81
82
  else
82
83
  klass.connection.case_sensitive_comparison(table, attribute, column, value)
83
84
  end
85
+ klass.unscoped.where!(comparison)
84
86
  end
85
87
 
86
- def scope_relation(record, table, relation)
88
+ def scope_relation(record, relation)
87
89
  Array(options[:scope]).each do |scope_item|
88
- if reflection = record.class._reflect_on_association(scope_item)
89
- scope_value = record.send(reflection.foreign_key)
90
- scope_item = reflection.foreign_key
90
+ scope_value = if record.class._reflect_on_association(scope_item)
91
+ record.association(scope_item).reader
91
92
  else
92
- scope_value = record._read_attribute(scope_item)
93
+ record._read_attribute(scope_item)
93
94
  end
94
- relation = relation.and(table[scope_item].eq(scope_value))
95
+ relation = relation.where(scope_item => scope_value)
95
96
  end
96
97
 
97
98
  relation
@@ -169,7 +170,8 @@ module ActiveRecord
169
170
  #
170
171
  # === Concurrency and integrity
171
172
  #
172
- # Using this validation method in conjunction with ActiveRecord::Base#save
173
+ # Using this validation method in conjunction with
174
+ # {ActiveRecord::Base#save}[rdoc-ref:Persistence#save]
173
175
  # does not guarantee the absence of duplicate record insertions, because
174
176
  # uniqueness checks on the application level are inherently prone to race
175
177
  # conditions. For example, suppose that two users try to post a Comment at
@@ -203,21 +205,19 @@ module ActiveRecord
203
205
  # | # Boom! We now have a duplicate
204
206
  # | # title!
205
207
  #
206
- # This could even happen if you use transactions with the 'serializable'
207
- # isolation level. The best way to work around this problem is to add a unique
208
- # index to the database table using
209
- # ActiveRecord::ConnectionAdapters::SchemaStatements#add_index. In the
210
- # rare case that a race condition occurs, the database will guarantee
208
+ # The best way to work around this problem is to add a unique index to the database table using
209
+ # {connection.add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index].
210
+ # In the rare case that a race condition occurs, the database will guarantee
211
211
  # the field's uniqueness.
212
212
  #
213
213
  # When the database catches such a duplicate insertion,
214
- # ActiveRecord::Base#save will raise an ActiveRecord::StatementInvalid
214
+ # {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] will raise an ActiveRecord::StatementInvalid
215
215
  # exception. You can either choose to let this error propagate (which
216
216
  # will result in the default Rails exception page being shown), or you
217
217
  # can catch it and restart the transaction (e.g. by telling the user
218
218
  # that the title already exists, and asking them to re-enter the title).
219
219
  # This technique is also known as
220
- # {optimistic concurrency control}[http://en.wikipedia.org/wiki/Optimistic_concurrency_control].
220
+ # {optimistic concurrency control}[https://en.wikipedia.org/wiki/Optimistic_concurrency_control].
221
221
  #
222
222
  # The bundled ActiveRecord::ConnectionAdapters distinguish unique index
223
223
  # constraint errors from other types of database errors by throwing an
@@ -227,7 +227,6 @@ module ActiveRecord
227
227
  #
228
228
  # The following bundled adapters throw the ActiveRecord::RecordNotUnique exception:
229
229
  #
230
- # * ActiveRecord::ConnectionAdapters::MysqlAdapter.
231
230
  # * ActiveRecord::ConnectionAdapters::Mysql2Adapter.
232
231
  # * ActiveRecord::ConnectionAdapters::SQLite3Adapter.
233
232
  # * ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
- # = Active Record RecordInvalid
4
+ # = Active Record \RecordInvalid
3
5
  #
4
- # Raised by <tt>save!</tt> and <tt>create!</tt> when the record is invalid. Use the
5
- # +record+ method to retrieve the record which did not validate.
6
+ # Raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
7
+ # {ActiveRecord::Base#create!}[rdoc-ref:Persistence::ClassMethods#create!] when the record is invalid.
8
+ # Use the #record method to retrieve the record which did not validate.
6
9
  #
7
10
  # begin
8
11
  # complex_operation_that_internally_calls_save!
@@ -12,74 +15,72 @@ module ActiveRecord
12
15
  class RecordInvalid < ActiveRecordError
13
16
  attr_reader :record
14
17
 
15
- def initialize(record)
16
- @record = record
17
- errors = @record.errors.full_messages.join(", ")
18
- super(I18n.t(:"#{@record.class.i18n_scope}.errors.messages.record_invalid", :errors => errors, :default => :"errors.messages.record_invalid"))
18
+ def initialize(record = nil)
19
+ if record
20
+ @record = record
21
+ errors = @record.errors.full_messages.join(", ")
22
+ message = I18n.t(:"#{@record.class.i18n_scope}.errors.messages.record_invalid", errors: errors, default: :"errors.messages.record_invalid")
23
+ else
24
+ message = "Record invalid"
25
+ end
26
+
27
+ super(message)
19
28
  end
20
29
  end
21
30
 
22
- # = Active Record Validations
31
+ # = Active Record \Validations
23
32
  #
24
- # Active Record includes the majority of its validations from <tt>ActiveModel::Validations</tt>
33
+ # Active Record includes the majority of its validations from ActiveModel::Validations
25
34
  # all of which accept the <tt>:on</tt> argument to define the context where the
26
35
  # validations are active. Active Record will always supply either the context of
27
36
  # <tt>:create</tt> or <tt>:update</tt> dependent on whether the model is a
28
- # <tt>new_record?</tt>.
37
+ # {new_record?}[rdoc-ref:Persistence#new_record?].
29
38
  module Validations
30
39
  extend ActiveSupport::Concern
31
40
  include ActiveModel::Validations
32
41
 
33
42
  # The validation process on save can be skipped by passing <tt>validate: false</tt>.
34
- # The regular Base#save method is replaced with this when the validations
35
- # module is mixed in, which it is by default.
36
- def save(options={})
43
+ # The regular {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] method is replaced
44
+ # with this when the validations module is mixed in, which it is by default.
45
+ def save(options = {})
37
46
  perform_validations(options) ? super : false
38
47
  end
39
48
 
40
- # Attempts to save the record just like Base#save but will raise a +RecordInvalid+
41
- # exception instead of returning +false+ if the record is not valid.
42
- def save!(options={})
43
- perform_validations(options) ? super : raise_record_invalid
49
+ # Attempts to save the record just like {ActiveRecord::Base#save}[rdoc-ref:Base#save] but
50
+ # will raise an ActiveRecord::RecordInvalid exception instead of returning +false+ if the record is not valid.
51
+ def save!(options = {})
52
+ perform_validations(options) ? super : raise_validation_error
44
53
  end
45
54
 
46
55
  # Runs all the validations within the specified context. Returns +true+ if
47
56
  # no errors are found, +false+ otherwise.
48
57
  #
49
- # Aliased as validate.
58
+ # Aliased as #validate.
50
59
  #
51
60
  # If the argument is +false+ (default is +nil+), the context is set to <tt>:create</tt> if
52
- # <tt>new_record?</tt> is +true+, and to <tt>:update</tt> if it is not.
61
+ # {new_record?}[rdoc-ref:Persistence#new_record?] is +true+, and to <tt>:update</tt> if it is not.
53
62
  #
54
- # Validations with no <tt>:on</tt> option will run no matter the context. Validations with
63
+ # \Validations with no <tt>:on</tt> option will run no matter the context. \Validations with
55
64
  # some <tt>:on</tt> option will only run in the specified context.
56
65
  def valid?(context = nil)
57
- context ||= (new_record? ? :create : :update)
66
+ context ||= default_validation_context
58
67
  output = super(context)
59
68
  errors.empty? && output
60
69
  end
61
70
 
62
71
  alias_method :validate, :valid?
63
72
 
64
- # Runs all the validations within the specified context. Returns +true+ if
65
- # no errors are found, raises +RecordInvalid+ otherwise.
66
- #
67
- # If the argument is +false+ (default is +nil+), the context is set to <tt>:create</tt> if
68
- # <tt>new_record?</tt> is +true+, and to <tt>:update</tt> if it is not.
69
- #
70
- # Validations with no <tt>:on</tt> option will run no matter the context. Validations with
71
- # some <tt>:on</tt> option will only run in the specified context.
72
- def validate!(context = nil)
73
- valid?(context) || raise_record_invalid
74
- end
73
+ private
75
74
 
76
- protected
75
+ def default_validation_context
76
+ new_record? ? :create : :update
77
+ end
77
78
 
78
- def raise_record_invalid
79
+ def raise_validation_error
79
80
  raise(RecordInvalid.new(self))
80
81
  end
81
82
 
82
- def perform_validations(options={}) # :nodoc:
83
+ def perform_validations(options = {})
83
84
  options[:validate] == false || valid?(options[:context])
84
85
  end
85
86
  end
@@ -88,3 +89,5 @@ end
88
89
  require "active_record/validations/associated"
89
90
  require "active_record/validations/uniqueness"
90
91
  require "active_record/validations/presence"
92
+ require "active_record/validations/absence"
93
+ require "active_record/validations/length"
@@ -1,4 +1,6 @@
1
- require_relative 'gem_version'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "gem_version"
2
4
 
3
5
  module ActiveRecord
4
6
  # Returns the version of the currently loaded ActiveRecord as a <tt>Gem::Version</tt>
data/lib/active_record.rb CHANGED
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #--
2
- # Copyright (c) 2004-2014 David Heinemeier Hansson
4
+ # Copyright (c) 2004-2018 David Heinemeier Hansson
3
5
  #
4
6
  # Permission is hereby granted, free of charge, to any person obtaining
5
7
  # a copy of this software and associated documentation files (the
@@ -21,18 +23,18 @@
21
23
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
24
  #++
23
25
 
24
- require 'active_support'
25
- require 'active_support/rails'
26
- require 'active_model'
27
- require 'arel'
26
+ require "active_support"
27
+ require "active_support/rails"
28
+ require "active_model"
29
+ require "arel"
30
+ require "yaml"
28
31
 
29
- require 'active_record/version'
30
- require 'active_record/attribute_set'
32
+ require "active_record/version"
33
+ require "active_model/attribute_set"
31
34
 
32
35
  module ActiveRecord
33
36
  extend ActiveSupport::Autoload
34
37
 
35
- autoload :Attribute
36
38
  autoload :Base
37
39
  autoload :Callbacks
38
40
  autoload :Core
@@ -40,19 +42,22 @@ module ActiveRecord
40
42
  autoload :CounterCache
41
43
  autoload :DynamicMatchers
42
44
  autoload :Enum
45
+ autoload :InternalMetadata
43
46
  autoload :Explain
44
47
  autoload :Inheritance
45
48
  autoload :Integration
46
49
  autoload :Migration
47
- autoload :Migrator, 'active_record/migration'
50
+ autoload :Migrator, "active_record/migration"
48
51
  autoload :ModelSchema
49
52
  autoload :NestedAttributes
50
53
  autoload :NoTouching
54
+ autoload :TouchLater
51
55
  autoload :Persistence
52
56
  autoload :QueryCache
53
57
  autoload :Querying
58
+ autoload :CollectionCacheKey
54
59
  autoload :ReadonlyAttributes
55
- autoload :RecordInvalid, 'active_record/validations'
60
+ autoload :RecordInvalid, "active_record/validations"
56
61
  autoload :Reflection
57
62
  autoload :RuntimeRegistry
58
63
  autoload :Sanitization
@@ -63,15 +68,17 @@ module ActiveRecord
63
68
  autoload :Serialization
64
69
  autoload :StatementCache
65
70
  autoload :Store
71
+ autoload :Suppressor
66
72
  autoload :Timestamp
67
73
  autoload :Transactions
68
74
  autoload :Translation
69
75
  autoload :Validations
76
+ autoload :SecureToken
70
77
 
71
78
  eager_autoload do
72
- autoload :ActiveRecordError, 'active_record/errors'
73
- autoload :ConnectionNotEstablished, 'active_record/errors'
74
- autoload :ConnectionAdapters, 'active_record/connection_adapters/abstract_adapter'
79
+ autoload :ActiveRecordError, "active_record/errors"
80
+ autoload :ConnectionNotEstablished, "active_record/errors"
81
+ autoload :ConnectionAdapters, "active_record/connection_adapters/abstract_adapter"
75
82
 
76
83
  autoload :Aggregations
77
84
  autoload :Associations
@@ -85,7 +92,7 @@ module ActiveRecord
85
92
  autoload :AssociationRelation
86
93
  autoload :NullRelation
87
94
 
88
- autoload_under 'relation' do
95
+ autoload_under "relation" do
89
96
  autoload :QueryMethods
90
97
  autoload :FinderMethods
91
98
  autoload :Calculations
@@ -96,11 +103,13 @@ module ActiveRecord
96
103
  end
97
104
 
98
105
  autoload :Result
106
+ autoload :TableMetadata
107
+ autoload :Type
99
108
  end
100
109
 
101
110
  module Coders
102
- autoload :YAMLColumn, 'active_record/coders/yaml_column'
103
- autoload :JSON, 'active_record/coders/json'
111
+ autoload :YAMLColumn, "active_record/coders/yaml_column"
112
+ autoload :JSON, "active_record/coders/json"
104
113
  end
105
114
 
106
115
  module AttributeMethods
@@ -132,7 +141,6 @@ module ActiveRecord
132
141
 
133
142
  eager_autoload do
134
143
  autoload :AbstractAdapter
135
- autoload :ConnectionManagement, "active_record/connection_adapters/abstract/connection_pool"
136
144
  end
137
145
  end
138
146
 
@@ -149,13 +157,13 @@ module ActiveRecord
149
157
  extend ActiveSupport::Autoload
150
158
 
151
159
  autoload :DatabaseTasks
152
- autoload :SQLiteDatabaseTasks, 'active_record/tasks/sqlite_database_tasks'
153
- autoload :MySQLDatabaseTasks, 'active_record/tasks/mysql_database_tasks'
160
+ autoload :SQLiteDatabaseTasks, "active_record/tasks/sqlite_database_tasks"
161
+ autoload :MySQLDatabaseTasks, "active_record/tasks/mysql_database_tasks"
154
162
  autoload :PostgreSQLDatabaseTasks,
155
- 'active_record/tasks/postgresql_database_tasks'
163
+ "active_record/tasks/postgresql_database_tasks"
156
164
  end
157
165
 
158
- autoload :TestFixtures, 'active_record/fixtures'
166
+ autoload :TestFixtures, "active_record/fixtures"
159
167
 
160
168
  def self.eager_load!
161
169
  super
@@ -172,5 +180,9 @@ ActiveSupport.on_load(:active_record) do
172
180
  end
173
181
 
174
182
  ActiveSupport.on_load(:i18n) do
175
- I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
183
+ I18n.load_path << File.expand_path("active_record/locale/en.yml", __dir__)
176
184
  end
185
+
186
+ YAML.load_tags["!ruby/object:ActiveRecord::AttributeSet"] = "ActiveModel::AttributeSet"
187
+ YAML.load_tags["!ruby/object:ActiveRecord::Attribute::FromDatabase"] = "ActiveModel::Attribute::FromDatabase"
188
+ YAML.load_tags["!ruby/object:ActiveRecord::LazyAttributeHash"] = "ActiveModel::LazyAttributeHash"
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/active_record"
4
+
5
+ module ActiveRecord
6
+ module Generators # :nodoc:
7
+ class ApplicationRecordGenerator < ::Rails::Generators::Base # :nodoc:
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ # FIXME: Change this file to a symlink once RubyGems 2.5.0 is required.
11
+ def create_application_record
12
+ template "application_record.rb", application_record_file_name
13
+ end
14
+
15
+ private
16
+
17
+ def application_record_file_name
18
+ @application_record_file_name ||=
19
+ if namespaced?
20
+ "app/models/#{namespaced_path}/application_record.rb"
21
+ else
22
+ "app/models/application_record.rb"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ <% module_namespacing do -%>
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ <% end -%>