activerecord 5.2.3

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 (244) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +937 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +217 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record.rb +188 -0
  8. data/lib/active_record/aggregations.rb +283 -0
  9. data/lib/active_record/association_relation.rb +40 -0
  10. data/lib/active_record/associations.rb +1860 -0
  11. data/lib/active_record/associations/alias_tracker.rb +81 -0
  12. data/lib/active_record/associations/association.rb +299 -0
  13. data/lib/active_record/associations/association_scope.rb +168 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +130 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +40 -0
  16. data/lib/active_record/associations/builder/association.rb +140 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +163 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +82 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +135 -0
  20. data/lib/active_record/associations/builder/has_many.rb +17 -0
  21. data/lib/active_record/associations/builder/has_one.rb +30 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +42 -0
  23. data/lib/active_record/associations/collection_association.rb +513 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1131 -0
  25. data/lib/active_record/associations/foreign_association.rb +13 -0
  26. data/lib/active_record/associations/has_many_association.rb +144 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +227 -0
  28. data/lib/active_record/associations/has_one_association.rb +120 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency.rb +262 -0
  31. data/lib/active_record/associations/join_dependency/join_association.rb +60 -0
  32. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  33. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  34. data/lib/active_record/associations/preloader.rb +193 -0
  35. data/lib/active_record/associations/preloader/association.rb +131 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +107 -0
  37. data/lib/active_record/associations/singular_association.rb +73 -0
  38. data/lib/active_record/associations/through_association.rb +121 -0
  39. data/lib/active_record/attribute_assignment.rb +88 -0
  40. data/lib/active_record/attribute_decorators.rb +90 -0
  41. data/lib/active_record/attribute_methods.rb +492 -0
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +78 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +150 -0
  44. data/lib/active_record/attribute_methods/primary_key.rb +143 -0
  45. data/lib/active_record/attribute_methods/query.rb +42 -0
  46. data/lib/active_record/attribute_methods/read.rb +85 -0
  47. data/lib/active_record/attribute_methods/serialization.rb +90 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +91 -0
  49. data/lib/active_record/attribute_methods/write.rb +68 -0
  50. data/lib/active_record/attributes.rb +266 -0
  51. data/lib/active_record/autosave_association.rb +498 -0
  52. data/lib/active_record/base.rb +329 -0
  53. data/lib/active_record/callbacks.rb +353 -0
  54. data/lib/active_record/coders/json.rb +15 -0
  55. data/lib/active_record/coders/yaml_column.rb +50 -0
  56. data/lib/active_record/collection_cache_key.rb +53 -0
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1068 -0
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +72 -0
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +540 -0
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +145 -0
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +200 -0
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +146 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +685 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +95 -0
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1396 -0
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +283 -0
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +628 -0
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +887 -0
  70. data/lib/active_record/connection_adapters/column.rb +91 -0
  71. data/lib/active_record/connection_adapters/connection_specification.rb +287 -0
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  73. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  81. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  82. data/lib/active_record/connection_adapters/mysql2_adapter.rb +129 -0
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -0
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +163 -0
  85. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +56 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +111 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  109. data/lib/active_record/connection_adapters/postgresql/quoting.rb +168 -0
  110. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +206 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +774 -0
  115. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  116. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  117. data/lib/active_record/connection_adapters/postgresql_adapter.rb +863 -0
  118. data/lib/active_record/connection_adapters/schema_cache.rb +118 -0
  119. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +573 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +145 -0
  129. data/lib/active_record/core.rb +559 -0
  130. data/lib/active_record/counter_cache.rb +218 -0
  131. data/lib/active_record/define_callbacks.rb +22 -0
  132. data/lib/active_record/dynamic_matchers.rb +122 -0
  133. data/lib/active_record/enum.rb +244 -0
  134. data/lib/active_record/errors.rb +380 -0
  135. data/lib/active_record/explain.rb +50 -0
  136. data/lib/active_record/explain_registry.rb +32 -0
  137. data/lib/active_record/explain_subscriber.rb +34 -0
  138. data/lib/active_record/fixture_set/file.rb +82 -0
  139. data/lib/active_record/fixtures.rb +1065 -0
  140. data/lib/active_record/gem_version.rb +17 -0
  141. data/lib/active_record/inheritance.rb +283 -0
  142. data/lib/active_record/integration.rb +155 -0
  143. data/lib/active_record/internal_metadata.rb +45 -0
  144. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  145. data/lib/active_record/locale/en.yml +48 -0
  146. data/lib/active_record/locking/optimistic.rb +198 -0
  147. data/lib/active_record/locking/pessimistic.rb +89 -0
  148. data/lib/active_record/log_subscriber.rb +137 -0
  149. data/lib/active_record/migration.rb +1378 -0
  150. data/lib/active_record/migration/command_recorder.rb +240 -0
  151. data/lib/active_record/migration/compatibility.rb +217 -0
  152. data/lib/active_record/migration/join_table.rb +17 -0
  153. data/lib/active_record/model_schema.rb +521 -0
  154. data/lib/active_record/nested_attributes.rb +600 -0
  155. data/lib/active_record/no_touching.rb +58 -0
  156. data/lib/active_record/null_relation.rb +68 -0
  157. data/lib/active_record/persistence.rb +763 -0
  158. data/lib/active_record/query_cache.rb +45 -0
  159. data/lib/active_record/querying.rb +70 -0
  160. data/lib/active_record/railtie.rb +226 -0
  161. data/lib/active_record/railties/console_sandbox.rb +7 -0
  162. data/lib/active_record/railties/controller_runtime.rb +56 -0
  163. data/lib/active_record/railties/databases.rake +377 -0
  164. data/lib/active_record/readonly_attributes.rb +24 -0
  165. data/lib/active_record/reflection.rb +1044 -0
  166. data/lib/active_record/relation.rb +629 -0
  167. data/lib/active_record/relation/batches.rb +287 -0
  168. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  169. data/lib/active_record/relation/calculations.rb +417 -0
  170. data/lib/active_record/relation/delegation.rb +147 -0
  171. data/lib/active_record/relation/finder_methods.rb +565 -0
  172. data/lib/active_record/relation/from_clause.rb +26 -0
  173. data/lib/active_record/relation/merger.rb +193 -0
  174. data/lib/active_record/relation/predicate_builder.rb +152 -0
  175. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  177. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  178. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  179. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  180. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  181. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  182. data/lib/active_record/relation/query_attribute.rb +45 -0
  183. data/lib/active_record/relation/query_methods.rb +1231 -0
  184. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  185. data/lib/active_record/relation/spawn_methods.rb +77 -0
  186. data/lib/active_record/relation/where_clause.rb +186 -0
  187. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  188. data/lib/active_record/result.rb +149 -0
  189. data/lib/active_record/runtime_registry.rb +24 -0
  190. data/lib/active_record/sanitization.rb +222 -0
  191. data/lib/active_record/schema.rb +70 -0
  192. data/lib/active_record/schema_dumper.rb +255 -0
  193. data/lib/active_record/schema_migration.rb +56 -0
  194. data/lib/active_record/scoping.rb +106 -0
  195. data/lib/active_record/scoping/default.rb +152 -0
  196. data/lib/active_record/scoping/named.rb +213 -0
  197. data/lib/active_record/secure_token.rb +40 -0
  198. data/lib/active_record/serialization.rb +22 -0
  199. data/lib/active_record/statement_cache.rb +121 -0
  200. data/lib/active_record/store.rb +211 -0
  201. data/lib/active_record/suppressor.rb +61 -0
  202. data/lib/active_record/table_metadata.rb +82 -0
  203. data/lib/active_record/tasks/database_tasks.rb +337 -0
  204. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  205. data/lib/active_record/tasks/postgresql_database_tasks.rb +143 -0
  206. data/lib/active_record/tasks/sqlite_database_tasks.rb +83 -0
  207. data/lib/active_record/timestamp.rb +153 -0
  208. data/lib/active_record/touch_later.rb +64 -0
  209. data/lib/active_record/transactions.rb +502 -0
  210. data/lib/active_record/translation.rb +24 -0
  211. data/lib/active_record/type.rb +79 -0
  212. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  213. data/lib/active_record/type/date.rb +9 -0
  214. data/lib/active_record/type/date_time.rb +9 -0
  215. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  216. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  217. data/lib/active_record/type/internal/timezone.rb +17 -0
  218. data/lib/active_record/type/json.rb +30 -0
  219. data/lib/active_record/type/serialized.rb +71 -0
  220. data/lib/active_record/type/text.rb +11 -0
  221. data/lib/active_record/type/time.rb +21 -0
  222. data/lib/active_record/type/type_map.rb +62 -0
  223. data/lib/active_record/type/unsigned_integer.rb +17 -0
  224. data/lib/active_record/type_caster.rb +9 -0
  225. data/lib/active_record/type_caster/connection.rb +33 -0
  226. data/lib/active_record/type_caster/map.rb +23 -0
  227. data/lib/active_record/validations.rb +93 -0
  228. data/lib/active_record/validations/absence.rb +25 -0
  229. data/lib/active_record/validations/associated.rb +60 -0
  230. data/lib/active_record/validations/length.rb +26 -0
  231. data/lib/active_record/validations/presence.rb +68 -0
  232. data/lib/active_record/validations/uniqueness.rb +238 -0
  233. data/lib/active_record/version.rb +10 -0
  234. data/lib/rails/generators/active_record.rb +19 -0
  235. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  236. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  237. data/lib/rails/generators/active_record/migration.rb +35 -0
  238. data/lib/rails/generators/active_record/migration/migration_generator.rb +78 -0
  239. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  240. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +46 -0
  241. data/lib/rails/generators/active_record/model/model_generator.rb +48 -0
  242. data/lib/rails/generators/active_record/model/templates/model.rb.tt +13 -0
  243. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  244. metadata +333 -0
@@ -0,0 +1,329 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "active_support/benchmarkable"
5
+ require "active_support/dependencies"
6
+ require "active_support/descendants_tracker"
7
+ require "active_support/time"
8
+ require "active_support/core_ext/module/attribute_accessors"
9
+ require "active_support/core_ext/array/extract_options"
10
+ require "active_support/core_ext/hash/deep_merge"
11
+ require "active_support/core_ext/hash/slice"
12
+ require "active_support/core_ext/hash/transform_values"
13
+ require "active_support/core_ext/string/behavior"
14
+ require "active_support/core_ext/kernel/singleton_class"
15
+ require "active_support/core_ext/module/introspection"
16
+ require "active_support/core_ext/object/duplicable"
17
+ require "active_support/core_ext/class/subclasses"
18
+ require "active_record/attribute_decorators"
19
+ require "active_record/define_callbacks"
20
+ require "active_record/errors"
21
+ require "active_record/log_subscriber"
22
+ require "active_record/explain_subscriber"
23
+ require "active_record/relation/delegation"
24
+ require "active_record/attributes"
25
+ require "active_record/type_caster"
26
+
27
+ module ActiveRecord #:nodoc:
28
+ # = Active Record
29
+ #
30
+ # Active Record objects don't specify their attributes directly, but rather infer them from
31
+ # the table definition with which they're linked. Adding, removing, and changing attributes
32
+ # and their type is done directly in the database. Any change is instantly reflected in the
33
+ # Active Record objects. The mapping that binds a given Active Record class to a certain
34
+ # database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.
35
+ #
36
+ # See the mapping rules in table_name and the full example in link:files/activerecord/README_rdoc.html for more insight.
37
+ #
38
+ # == Creation
39
+ #
40
+ # Active Records accept constructor parameters either in a hash or as a block. The hash
41
+ # method is especially useful when you're receiving the data from somewhere else, like an
42
+ # HTTP request. It works like this:
43
+ #
44
+ # user = User.new(name: "David", occupation: "Code Artist")
45
+ # user.name # => "David"
46
+ #
47
+ # You can also use block initialization:
48
+ #
49
+ # user = User.new do |u|
50
+ # u.name = "David"
51
+ # u.occupation = "Code Artist"
52
+ # end
53
+ #
54
+ # And of course you can just create a bare object and specify the attributes after the fact:
55
+ #
56
+ # user = User.new
57
+ # user.name = "David"
58
+ # user.occupation = "Code Artist"
59
+ #
60
+ # == Conditions
61
+ #
62
+ # Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement.
63
+ # The array form is to be used when the condition input is tainted and requires sanitization. The string form can
64
+ # be used for statements that don't involve tainted data. The hash form works much like the array form, except
65
+ # only equality and range is possible. Examples:
66
+ #
67
+ # class User < ActiveRecord::Base
68
+ # def self.authenticate_unsafely(user_name, password)
69
+ # where("user_name = '#{user_name}' AND password = '#{password}'").first
70
+ # end
71
+ #
72
+ # def self.authenticate_safely(user_name, password)
73
+ # where("user_name = ? AND password = ?", user_name, password).first
74
+ # end
75
+ #
76
+ # def self.authenticate_safely_simply(user_name, password)
77
+ # where(user_name: user_name, password: password).first
78
+ # end
79
+ # end
80
+ #
81
+ # The <tt>authenticate_unsafely</tt> method inserts the parameters directly into the query
82
+ # and is thus susceptible to SQL-injection attacks if the <tt>user_name</tt> and +password+
83
+ # parameters come directly from an HTTP request. The <tt>authenticate_safely</tt> and
84
+ # <tt>authenticate_safely_simply</tt> both will sanitize the <tt>user_name</tt> and +password+
85
+ # before inserting them in the query, which will ensure that an attacker can't escape the
86
+ # query and fake the login (or worse).
87
+ #
88
+ # When using multiple parameters in the conditions, it can easily become hard to read exactly
89
+ # what the fourth or fifth question mark is supposed to represent. In those cases, you can
90
+ # resort to named bind variables instead. That's done by replacing the question marks with
91
+ # symbols and supplying a hash with values for the matching symbol keys:
92
+ #
93
+ # Company.where(
94
+ # "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
95
+ # { id: 3, name: "37signals", division: "First", accounting_date: '2005-01-01' }
96
+ # ).first
97
+ #
98
+ # Similarly, a simple hash without a statement will generate conditions based on equality with the SQL AND
99
+ # operator. For instance:
100
+ #
101
+ # Student.where(first_name: "Harvey", status: 1)
102
+ # Student.where(params[:student])
103
+ #
104
+ # A range may be used in the hash to use the SQL BETWEEN operator:
105
+ #
106
+ # Student.where(grade: 9..12)
107
+ #
108
+ # An array may be used in the hash to use the SQL IN operator:
109
+ #
110
+ # Student.where(grade: [9,11,12])
111
+ #
112
+ # When joining tables, nested hashes or keys written in the form 'table_name.column_name'
113
+ # can be used to qualify the table name of a particular condition. For instance:
114
+ #
115
+ # Student.joins(:schools).where(schools: { category: 'public' })
116
+ # Student.joins(:schools).where('schools.category' => 'public' )
117
+ #
118
+ # == Overwriting default accessors
119
+ #
120
+ # All column values are automatically available through basic accessors on the Active Record
121
+ # object, but sometimes you want to specialize this behavior. This can be done by overwriting
122
+ # the default accessors (using the same name as the attribute) and calling
123
+ # +super+ to actually change things.
124
+ #
125
+ # class Song < ActiveRecord::Base
126
+ # # Uses an integer of seconds to hold the length of the song
127
+ #
128
+ # def length=(minutes)
129
+ # super(minutes.to_i * 60)
130
+ # end
131
+ #
132
+ # def length
133
+ # super / 60
134
+ # end
135
+ # end
136
+ #
137
+ # == Attribute query methods
138
+ #
139
+ # In addition to the basic accessors, query methods are also automatically available on the Active Record object.
140
+ # Query methods allow you to test whether an attribute value is present.
141
+ # Additionally, when dealing with numeric values, a query method will return false if the value is zero.
142
+ #
143
+ # For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
144
+ # to determine whether the user has a name:
145
+ #
146
+ # user = User.new(name: "David")
147
+ # user.name? # => true
148
+ #
149
+ # anonymous = User.new(name: "")
150
+ # anonymous.name? # => false
151
+ #
152
+ # == Accessing attributes before they have been typecasted
153
+ #
154
+ # Sometimes you want to be able to read the raw attribute data without having the column-determined
155
+ # typecast run its course first. That can be done by using the <tt><attribute>_before_type_cast</tt>
156
+ # accessors that all attributes have. For example, if your Account model has a <tt>balance</tt> attribute,
157
+ # you can call <tt>account.balance_before_type_cast</tt> or <tt>account.id_before_type_cast</tt>.
158
+ #
159
+ # This is especially useful in validation situations where the user might supply a string for an
160
+ # integer field and you want to display the original string back in an error message. Accessing the
161
+ # attribute normally would typecast the string to 0, which isn't what you want.
162
+ #
163
+ # == Dynamic attribute-based finders
164
+ #
165
+ # Dynamic attribute-based finders are a mildly deprecated way of getting (and/or creating) objects
166
+ # by simple queries without turning to SQL. They work by appending the name of an attribute
167
+ # to <tt>find_by_</tt> like <tt>Person.find_by_user_name</tt>.
168
+ # Instead of writing <tt>Person.find_by(user_name: user_name)</tt>, you can use
169
+ # <tt>Person.find_by_user_name(user_name)</tt>.
170
+ #
171
+ # It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
172
+ # ActiveRecord::RecordNotFound error if they do not return any records,
173
+ # like <tt>Person.find_by_last_name!</tt>.
174
+ #
175
+ # It's also possible to use multiple attributes in the same <tt>find_by_</tt> by separating them with
176
+ # "_and_".
177
+ #
178
+ # Person.find_by(user_name: user_name, password: password)
179
+ # Person.find_by_user_name_and_password(user_name, password) # with dynamic finder
180
+ #
181
+ # It's even possible to call these dynamic finder methods on relations and named scopes.
182
+ #
183
+ # Payment.order("created_on").find_by_amount(50)
184
+ #
185
+ # == Saving arrays, hashes, and other non-mappable objects in text columns
186
+ #
187
+ # Active Record can serialize any object in text columns using YAML. To do so, you must
188
+ # specify this with a call to the class method
189
+ # {serialize}[rdoc-ref:AttributeMethods::Serialization::ClassMethods#serialize].
190
+ # This makes it possible to store arrays, hashes, and other non-mappable objects without doing
191
+ # any additional work.
192
+ #
193
+ # class User < ActiveRecord::Base
194
+ # serialize :preferences
195
+ # end
196
+ #
197
+ # user = User.create(preferences: { "background" => "black", "display" => large })
198
+ # User.find(user.id).preferences # => { "background" => "black", "display" => large }
199
+ #
200
+ # You can also specify a class option as the second parameter that'll raise an exception
201
+ # if a serialized object is retrieved as a descendant of a class not in the hierarchy.
202
+ #
203
+ # class User < ActiveRecord::Base
204
+ # serialize :preferences, Hash
205
+ # end
206
+ #
207
+ # user = User.create(preferences: %w( one two three ))
208
+ # User.find(user.id).preferences # raises SerializationTypeMismatch
209
+ #
210
+ # When you specify a class option, the default value for that attribute will be a new
211
+ # instance of that class.
212
+ #
213
+ # class User < ActiveRecord::Base
214
+ # serialize :preferences, OpenStruct
215
+ # end
216
+ #
217
+ # user = User.new
218
+ # user.preferences.theme_color = "red"
219
+ #
220
+ #
221
+ # == Single table inheritance
222
+ #
223
+ # Active Record allows inheritance by storing the name of the class in a
224
+ # column that is named "type" by default. See ActiveRecord::Inheritance for
225
+ # more details.
226
+ #
227
+ # == Connection to multiple databases in different models
228
+ #
229
+ # Connections are usually created through
230
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] and retrieved
231
+ # by ActiveRecord::Base.connection. All classes inheriting from ActiveRecord::Base will use this
232
+ # connection. But you can also set a class-specific connection. For example, if Course is an
233
+ # ActiveRecord::Base, but resides in a different database, you can just say <tt>Course.establish_connection</tt>
234
+ # and Course and all of its subclasses will use this connection instead.
235
+ #
236
+ # This feature is implemented by keeping a connection pool in ActiveRecord::Base that is
237
+ # a hash indexed by the class. If a connection is requested, the
238
+ # {ActiveRecord::Base.retrieve_connection}[rdoc-ref:ConnectionHandling#retrieve_connection] method
239
+ # will go up the class-hierarchy until a connection is found in the connection pool.
240
+ #
241
+ # == Exceptions
242
+ #
243
+ # * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
244
+ # * AdapterNotSpecified - The configuration hash used in
245
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
246
+ # didn't include an <tt>:adapter</tt> key.
247
+ # * AdapterNotFound - The <tt>:adapter</tt> key used in
248
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
249
+ # specified a non-existent adapter
250
+ # (or a bad spelling of an existing one).
251
+ # * AssociationTypeMismatch - The object assigned to the association wasn't of the type
252
+ # specified in the association definition.
253
+ # * AttributeAssignmentError - An error occurred while doing a mass assignment through the
254
+ # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
255
+ # You can inspect the +attribute+ property of the exception object to determine which attribute
256
+ # triggered the error.
257
+ # * ConnectionNotEstablished - No connection has been established.
258
+ # Use {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] before querying.
259
+ # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
260
+ # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
261
+ # The +errors+ property of this exception contains an array of
262
+ # AttributeAssignmentError
263
+ # objects that should be inspected to determine which attributes triggered the errors.
264
+ # * RecordInvalid - raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
265
+ # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
266
+ # when the record is invalid.
267
+ # * RecordNotFound - No record responded to the {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] method.
268
+ # Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions.
269
+ # Some {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] calls do not raise this exception to signal
270
+ # nothing was found, please check its documentation for further details.
271
+ # * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
272
+ # * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
273
+ #
274
+ # *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level).
275
+ # So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all
276
+ # instances in the current object space.
277
+ class Base
278
+ extend ActiveModel::Naming
279
+
280
+ extend ActiveSupport::Benchmarkable
281
+ extend ActiveSupport::DescendantsTracker
282
+
283
+ extend ConnectionHandling
284
+ extend QueryCache::ClassMethods
285
+ extend Querying
286
+ extend Translation
287
+ extend DynamicMatchers
288
+ extend Explain
289
+ extend Enum
290
+ extend Delegation::DelegateCache
291
+ extend CollectionCacheKey
292
+
293
+ include Core
294
+ include Persistence
295
+ include ReadonlyAttributes
296
+ include ModelSchema
297
+ include Inheritance
298
+ include Scoping
299
+ include Sanitization
300
+ include AttributeAssignment
301
+ include ActiveModel::Conversion
302
+ include Integration
303
+ include Validations
304
+ include CounterCache
305
+ include Attributes
306
+ include AttributeDecorators
307
+ include Locking::Optimistic
308
+ include Locking::Pessimistic
309
+ include DefineCallbacks
310
+ include AttributeMethods
311
+ include Callbacks
312
+ include Timestamp
313
+ include Associations
314
+ include ActiveModel::SecurePassword
315
+ include AutosaveAssociation
316
+ include NestedAttributes
317
+ include Aggregations
318
+ include Transactions
319
+ include TouchLater
320
+ include NoTouching
321
+ include Reflection
322
+ include Serialization
323
+ include Store
324
+ include SecureToken
325
+ include Suppressor
326
+ end
327
+
328
+ ActiveSupport.run_load_hooks(:active_record, Base)
329
+ end
@@ -0,0 +1,353 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ # = Active Record \Callbacks
5
+ #
6
+ # \Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic
7
+ # before or after an alteration of the object state. This can be used to make sure that associated and
8
+ # dependent objects are deleted when {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] is called (by overwriting +before_destroy+) or
9
+ # to massage attributes before they're validated (by overwriting +before_validation+).
10
+ # As an example of the callbacks initiated, consider the {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] call for a new record:
11
+ #
12
+ # * (-) <tt>save</tt>
13
+ # * (-) <tt>valid</tt>
14
+ # * (1) <tt>before_validation</tt>
15
+ # * (-) <tt>validate</tt>
16
+ # * (2) <tt>after_validation</tt>
17
+ # * (3) <tt>before_save</tt>
18
+ # * (4) <tt>before_create</tt>
19
+ # * (-) <tt>create</tt>
20
+ # * (5) <tt>after_create</tt>
21
+ # * (6) <tt>after_save</tt>
22
+ # * (7) <tt>after_commit</tt>
23
+ #
24
+ # Also, an <tt>after_rollback</tt> callback can be configured to be triggered whenever a rollback is issued.
25
+ # Check out ActiveRecord::Transactions for more details about <tt>after_commit</tt> and
26
+ # <tt>after_rollback</tt>.
27
+ #
28
+ # Additionally, an <tt>after_touch</tt> callback is triggered whenever an
29
+ # object is touched.
30
+ #
31
+ # Lastly an <tt>after_find</tt> and <tt>after_initialize</tt> callback is triggered for each object that
32
+ # is found and instantiated by a finder, with <tt>after_initialize</tt> being triggered after new objects
33
+ # are instantiated as well.
34
+ #
35
+ # There are nineteen callbacks in total, which give you immense power to react and prepare for each state in the
36
+ # Active Record life cycle. The sequence for calling {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] for an existing record is similar,
37
+ # except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
38
+ #
39
+ # Examples:
40
+ # class CreditCard < ActiveRecord::Base
41
+ # # Strip everything but digits, so the user can specify "555 234 34" or
42
+ # # "5552-3434" and both will mean "55523434"
43
+ # before_validation(on: :create) do
44
+ # self.number = number.gsub(/[^0-9]/, "") if attribute_present?("number")
45
+ # end
46
+ # end
47
+ #
48
+ # class Subscription < ActiveRecord::Base
49
+ # before_create :record_signup
50
+ #
51
+ # private
52
+ # def record_signup
53
+ # self.signed_up_on = Date.today
54
+ # end
55
+ # end
56
+ #
57
+ # class Firm < ActiveRecord::Base
58
+ # # Disables access to the system, for associated clients and people when the firm is destroyed
59
+ # before_destroy { |record| Person.where(firm_id: record.id).update_all(access: 'disabled') }
60
+ # before_destroy { |record| Client.where(client_of: record.id).update_all(access: 'disabled') }
61
+ # end
62
+ #
63
+ # == Inheritable callback queues
64
+ #
65
+ # Besides the overwritable callback methods, it's also possible to register callbacks through the
66
+ # use of the callback macros. Their main advantage is that the macros add behavior into a callback
67
+ # queue that is kept intact down through an inheritance hierarchy.
68
+ #
69
+ # class Topic < ActiveRecord::Base
70
+ # before_destroy :destroy_author
71
+ # end
72
+ #
73
+ # class Reply < Topic
74
+ # before_destroy :destroy_readers
75
+ # end
76
+ #
77
+ # Now, when <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
78
+ # run, both +destroy_author+ and +destroy_readers+ are called. Contrast this to the following situation
79
+ # where the +before_destroy+ method is overridden:
80
+ #
81
+ # class Topic < ActiveRecord::Base
82
+ # def before_destroy() destroy_author end
83
+ # end
84
+ #
85
+ # class Reply < Topic
86
+ # def before_destroy() destroy_readers end
87
+ # end
88
+ #
89
+ # In that case, <tt>Reply#destroy</tt> would only run +destroy_readers+ and _not_ +destroy_author+.
90
+ # So, use the callback macros when you want to ensure that a certain callback is called for the entire
91
+ # hierarchy, and use the regular overwritable methods when you want to leave it up to each descendant
92
+ # to decide whether they want to call +super+ and trigger the inherited callbacks.
93
+ #
94
+ # *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
95
+ # callbacks before specifying the associations. Otherwise, you might trigger the loading of a
96
+ # child before the parent has registered the callbacks and they won't be inherited.
97
+ #
98
+ # == Types of callbacks
99
+ #
100
+ # There are four types of callbacks accepted by the callback macros: Method references (symbol), callback objects,
101
+ # inline methods (using a proc). Method references and callback objects
102
+ # are the recommended approaches, inline methods using a proc are sometimes appropriate (such as for
103
+ # creating mix-ins).
104
+ #
105
+ # The method reference callbacks work by specifying a protected or private method available in the object, like this:
106
+ #
107
+ # class Topic < ActiveRecord::Base
108
+ # before_destroy :delete_parents
109
+ #
110
+ # private
111
+ # def delete_parents
112
+ # self.class.delete_all "parent_id = #{id}"
113
+ # end
114
+ # end
115
+ #
116
+ # The callback objects have methods named after the callback called with the record as the only parameter, such as:
117
+ #
118
+ # class BankAccount < ActiveRecord::Base
119
+ # before_save EncryptionWrapper.new
120
+ # after_save EncryptionWrapper.new
121
+ # after_initialize EncryptionWrapper.new
122
+ # end
123
+ #
124
+ # class EncryptionWrapper
125
+ # def before_save(record)
126
+ # record.credit_card_number = encrypt(record.credit_card_number)
127
+ # end
128
+ #
129
+ # def after_save(record)
130
+ # record.credit_card_number = decrypt(record.credit_card_number)
131
+ # end
132
+ #
133
+ # alias_method :after_initialize, :after_save
134
+ #
135
+ # private
136
+ # def encrypt(value)
137
+ # # Secrecy is committed
138
+ # end
139
+ #
140
+ # def decrypt(value)
141
+ # # Secrecy is unveiled
142
+ # end
143
+ # end
144
+ #
145
+ # So you specify the object you want messaged on a given callback. When that callback is triggered, the object has
146
+ # a method by the name of the callback messaged. You can make these callbacks more flexible by passing in other
147
+ # initialization data such as the name of the attribute to work with:
148
+ #
149
+ # class BankAccount < ActiveRecord::Base
150
+ # before_save EncryptionWrapper.new("credit_card_number")
151
+ # after_save EncryptionWrapper.new("credit_card_number")
152
+ # after_initialize EncryptionWrapper.new("credit_card_number")
153
+ # end
154
+ #
155
+ # class EncryptionWrapper
156
+ # def initialize(attribute)
157
+ # @attribute = attribute
158
+ # end
159
+ #
160
+ # def before_save(record)
161
+ # record.send("#{@attribute}=", encrypt(record.send("#{@attribute}")))
162
+ # end
163
+ #
164
+ # def after_save(record)
165
+ # record.send("#{@attribute}=", decrypt(record.send("#{@attribute}")))
166
+ # end
167
+ #
168
+ # alias_method :after_initialize, :after_save
169
+ #
170
+ # private
171
+ # def encrypt(value)
172
+ # # Secrecy is committed
173
+ # end
174
+ #
175
+ # def decrypt(value)
176
+ # # Secrecy is unveiled
177
+ # end
178
+ # end
179
+ #
180
+ # == <tt>before_validation*</tt> returning statements
181
+ #
182
+ # If the +before_validation+ callback throws +:abort+, the process will be
183
+ # aborted and {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] will return +false+.
184
+ # If {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] is called it will raise an ActiveRecord::RecordInvalid exception.
185
+ # Nothing will be appended to the errors object.
186
+ #
187
+ # == Canceling callbacks
188
+ #
189
+ # If a <tt>before_*</tt> callback throws +:abort+, all the later callbacks and
190
+ # the associated action are cancelled.
191
+ # Callbacks are generally run in the order they are defined, with the exception of callbacks defined as
192
+ # methods on the model, which are called last.
193
+ #
194
+ # == Ordering callbacks
195
+ #
196
+ # Sometimes the code needs that the callbacks execute in a specific order. For example, a +before_destroy+
197
+ # callback (+log_children+ in this case) should be executed before the children get destroyed by the
198
+ # <tt>dependent: :destroy</tt> option.
199
+ #
200
+ # Let's look at the code below:
201
+ #
202
+ # class Topic < ActiveRecord::Base
203
+ # has_many :children, dependent: :destroy
204
+ #
205
+ # before_destroy :log_children
206
+ #
207
+ # private
208
+ # def log_children
209
+ # # Child processing
210
+ # end
211
+ # end
212
+ #
213
+ # In this case, the problem is that when the +before_destroy+ callback is executed, the children are not available
214
+ # because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback gets executed first.
215
+ # You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
216
+ #
217
+ # class Topic < ActiveRecord::Base
218
+ # has_many :children, dependent: :destroy
219
+ #
220
+ # before_destroy :log_children, prepend: true
221
+ #
222
+ # private
223
+ # def log_children
224
+ # # Child processing
225
+ # end
226
+ # end
227
+ #
228
+ # This way, the +before_destroy+ gets executed before the <tt>dependent: :destroy</tt> is called, and the data is still available.
229
+ #
230
+ # Also, there are cases when you want several callbacks of the same type to
231
+ # be executed in order.
232
+ #
233
+ # For example:
234
+ #
235
+ # class Topic < ActiveRecord::Base
236
+ # has_many :children
237
+ #
238
+ # after_save :log_children
239
+ # after_save :do_something_else
240
+ #
241
+ # private
242
+ #
243
+ # def log_children
244
+ # # Child processing
245
+ # end
246
+ #
247
+ # def do_something_else
248
+ # # Something else
249
+ # end
250
+ # end
251
+ #
252
+ # In this case the +log_children+ gets executed before +do_something_else+.
253
+ # The same applies to all non-transactional callbacks.
254
+ #
255
+ # In case there are multiple transactional callbacks as seen below, the order
256
+ # is reversed.
257
+ #
258
+ # For example:
259
+ #
260
+ # class Topic < ActiveRecord::Base
261
+ # has_many :children
262
+ #
263
+ # after_commit :log_children
264
+ # after_commit :do_something_else
265
+ #
266
+ # private
267
+ #
268
+ # def log_children
269
+ # # Child processing
270
+ # end
271
+ #
272
+ # def do_something_else
273
+ # # Something else
274
+ # end
275
+ # end
276
+ #
277
+ # In this case the +do_something_else+ gets executed before +log_children+.
278
+ #
279
+ # == \Transactions
280
+ #
281
+ # The entire callback chain of a {#save}[rdoc-ref:Persistence#save], {#save!}[rdoc-ref:Persistence#save!],
282
+ # or {#destroy}[rdoc-ref:Persistence#destroy] call runs within a transaction. That includes <tt>after_*</tt> hooks.
283
+ # If everything goes fine a COMMIT is executed once the chain has been completed.
284
+ #
285
+ # If a <tt>before_*</tt> callback cancels the action a ROLLBACK is issued. You
286
+ # can also trigger a ROLLBACK raising an exception in any of the callbacks,
287
+ # including <tt>after_*</tt> hooks. Note, however, that in that case the client
288
+ # needs to be aware of it because an ordinary {#save}[rdoc-ref:Persistence#save] will raise such exception
289
+ # instead of quietly returning +false+.
290
+ #
291
+ # == Debugging callbacks
292
+ #
293
+ # The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. Active Model \Callbacks support
294
+ # <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
295
+ # defines what part of the chain the callback runs in.
296
+ #
297
+ # To find all callbacks in the before_save callback chain:
298
+ #
299
+ # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }
300
+ #
301
+ # Returns an array of callback objects that form the before_save chain.
302
+ #
303
+ # To further check if the before_save chain contains a proc defined as <tt>rest_when_dead</tt> use the <tt>filter</tt> property of the callback object:
304
+ #
305
+ # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead)
306
+ #
307
+ # Returns true or false depending on whether the proc is contained in the before_save callback chain on a Topic model.
308
+ #
309
+ module Callbacks
310
+ extend ActiveSupport::Concern
311
+
312
+ CALLBACKS = [
313
+ :after_initialize, :after_find, :after_touch, :before_validation, :after_validation,
314
+ :before_save, :around_save, :after_save, :before_create, :around_create,
315
+ :after_create, :before_update, :around_update, :after_update,
316
+ :before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
317
+ ]
318
+
319
+ def destroy #:nodoc:
320
+ @_destroy_callback_already_called ||= false
321
+ return if @_destroy_callback_already_called
322
+ @_destroy_callback_already_called = true
323
+ _run_destroy_callbacks { super }
324
+ rescue RecordNotDestroyed => e
325
+ @_association_destroy_exception = e
326
+ false
327
+ ensure
328
+ @_destroy_callback_already_called = false
329
+ end
330
+
331
+ def touch(*) #:nodoc:
332
+ _run_touch_callbacks { super }
333
+ end
334
+
335
+ def increment!(attribute, by = 1, touch: nil) # :nodoc:
336
+ touch ? _run_touch_callbacks { super } : super
337
+ end
338
+
339
+ private
340
+
341
+ def create_or_update(*)
342
+ _run_save_callbacks { super }
343
+ end
344
+
345
+ def _create_record
346
+ _run_create_callbacks { super }
347
+ end
348
+
349
+ def _update_record(*)
350
+ _run_update_callbacks { super }
351
+ end
352
+ end
353
+ end