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,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/scoping/default"
4
+ require "active_record/scoping/named"
5
+
6
+ module ActiveRecord
7
+ # This class is used to create a table that keeps track of which migrations
8
+ # have been applied to a given database. When a migration is run, its schema
9
+ # number is inserted in to the `SchemaMigration.table_name` so it doesn't need
10
+ # to be executed the next time.
11
+ class SchemaMigration < ActiveRecord::Base # :nodoc:
12
+ class << self
13
+ def primary_key
14
+ "version"
15
+ end
16
+
17
+ def table_name
18
+ "#{table_name_prefix}#{ActiveRecord::Base.schema_migrations_table_name}#{table_name_suffix}"
19
+ end
20
+
21
+ def table_exists?
22
+ connection.table_exists?(table_name)
23
+ end
24
+
25
+ def create_table
26
+ unless table_exists?
27
+ version_options = connection.internal_string_options_for_primary_key
28
+
29
+ connection.create_table(table_name, id: false) do |t|
30
+ t.string :version, version_options
31
+ end
32
+ end
33
+ end
34
+
35
+ def drop_table
36
+ connection.drop_table table_name, if_exists: true
37
+ end
38
+
39
+ def normalize_migration_number(number)
40
+ "%.3d" % number.to_i
41
+ end
42
+
43
+ def normalized_versions
44
+ all_versions.map { |v| normalize_migration_number v }
45
+ end
46
+
47
+ def all_versions
48
+ order(:version).pluck(:version)
49
+ end
50
+ end
51
+
52
+ def version
53
+ super.to_i
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/per_thread_registry"
4
+
5
+ module ActiveRecord
6
+ module Scoping
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ include Default
11
+ include Named
12
+ end
13
+
14
+ module ClassMethods # :nodoc:
15
+ def current_scope(skip_inherited_scope = false)
16
+ ScopeRegistry.value_for(:current_scope, self, skip_inherited_scope)
17
+ end
18
+
19
+ def current_scope=(scope)
20
+ ScopeRegistry.set_value_for(:current_scope, self, scope)
21
+ end
22
+
23
+ # Collects attributes from scopes that should be applied when creating
24
+ # an AR instance for the particular class this is called on.
25
+ def scope_attributes
26
+ all.scope_for_create
27
+ end
28
+
29
+ # Are there attributes associated with this scope?
30
+ def scope_attributes?
31
+ current_scope
32
+ end
33
+ end
34
+
35
+ def populate_with_current_scope_attributes # :nodoc:
36
+ return unless self.class.scope_attributes?
37
+
38
+ attributes = self.class.scope_attributes
39
+ _assign_attributes(attributes) if attributes.any?
40
+ end
41
+
42
+ def initialize_internals_callback # :nodoc:
43
+ super
44
+ populate_with_current_scope_attributes
45
+ end
46
+
47
+ # This class stores the +:current_scope+ and +:ignore_default_scope+ values
48
+ # for different classes. The registry is stored as a thread local, which is
49
+ # accessed through +ScopeRegistry.current+.
50
+ #
51
+ # This class allows you to store and get the scope values on different
52
+ # classes and different types of scopes. For example, if you are attempting
53
+ # to get the current_scope for the +Board+ model, then you would use the
54
+ # following code:
55
+ #
56
+ # registry = ActiveRecord::Scoping::ScopeRegistry
57
+ # registry.set_value_for(:current_scope, Board, some_new_scope)
58
+ #
59
+ # Now when you run:
60
+ #
61
+ # registry.value_for(:current_scope, Board)
62
+ #
63
+ # You will obtain whatever was defined in +some_new_scope+. The #value_for
64
+ # and #set_value_for methods are delegated to the current ScopeRegistry
65
+ # object, so the above example code can also be called as:
66
+ #
67
+ # ActiveRecord::Scoping::ScopeRegistry.set_value_for(:current_scope,
68
+ # Board, some_new_scope)
69
+ class ScopeRegistry # :nodoc:
70
+ extend ActiveSupport::PerThreadRegistry
71
+
72
+ VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope]
73
+
74
+ def initialize
75
+ @registry = Hash.new { |hash, key| hash[key] = {} }
76
+ end
77
+
78
+ # Obtains the value for a given +scope_type+ and +model+.
79
+ def value_for(scope_type, model, skip_inherited_scope = false)
80
+ raise_invalid_scope_type!(scope_type)
81
+ return @registry[scope_type][model.name] if skip_inherited_scope
82
+ klass = model
83
+ base = model.base_class
84
+ while klass <= base
85
+ value = @registry[scope_type][klass.name]
86
+ return value if value
87
+ klass = klass.superclass
88
+ end
89
+ end
90
+
91
+ # Sets the +value+ for a given +scope_type+ and +model+.
92
+ def set_value_for(scope_type, model, value)
93
+ raise_invalid_scope_type!(scope_type)
94
+ @registry[scope_type][model.name] = value
95
+ end
96
+
97
+ private
98
+
99
+ def raise_invalid_scope_type!(scope_type)
100
+ if !VALID_SCOPE_TYPES.include?(scope_type)
101
+ raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES"
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Scoping
5
+ module Default
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ # Stores the default scope for the class.
10
+ class_attribute :default_scopes, instance_writer: false, instance_predicate: false, default: []
11
+ class_attribute :default_scope_override, instance_writer: false, instance_predicate: false, default: nil
12
+ end
13
+
14
+ module ClassMethods
15
+ # Returns a scope for the model without the previously set scopes.
16
+ #
17
+ # class Post < ActiveRecord::Base
18
+ # def self.default_scope
19
+ # where(published: true)
20
+ # end
21
+ # end
22
+ #
23
+ # Post.all # Fires "SELECT * FROM posts WHERE published = true"
24
+ # Post.unscoped.all # Fires "SELECT * FROM posts"
25
+ # Post.where(published: false).unscoped.all # Fires "SELECT * FROM posts"
26
+ #
27
+ # This method also accepts a block. All queries inside the block will
28
+ # not use the previously set scopes.
29
+ #
30
+ # Post.unscoped {
31
+ # Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
32
+ # }
33
+ def unscoped
34
+ block_given? ? relation.scoping { yield } : relation
35
+ end
36
+
37
+ # Are there attributes associated with this scope?
38
+ def scope_attributes? # :nodoc:
39
+ super || default_scopes.any? || respond_to?(:default_scope)
40
+ end
41
+
42
+ def before_remove_const #:nodoc:
43
+ self.current_scope = nil
44
+ end
45
+
46
+ private
47
+
48
+ # Use this macro in your model to set a default scope for all operations on
49
+ # the model.
50
+ #
51
+ # class Article < ActiveRecord::Base
52
+ # default_scope { where(published: true) }
53
+ # end
54
+ #
55
+ # Article.all # => SELECT * FROM articles WHERE published = true
56
+ #
57
+ # The #default_scope is also applied while creating/building a record.
58
+ # It is not applied while updating a record.
59
+ #
60
+ # Article.new.published # => true
61
+ # Article.create.published # => true
62
+ #
63
+ # (You can also pass any object which responds to +call+ to the
64
+ # +default_scope+ macro, and it will be called when building the
65
+ # default scope.)
66
+ #
67
+ # If you use multiple #default_scope declarations in your model then
68
+ # they will be merged together:
69
+ #
70
+ # class Article < ActiveRecord::Base
71
+ # default_scope { where(published: true) }
72
+ # default_scope { where(rating: 'G') }
73
+ # end
74
+ #
75
+ # Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
76
+ #
77
+ # This is also the case with inheritance and module includes where the
78
+ # parent or module defines a #default_scope and the child or including
79
+ # class defines a second one.
80
+ #
81
+ # If you need to do more complex things with a default scope, you can
82
+ # alternatively define it as a class method:
83
+ #
84
+ # class Article < ActiveRecord::Base
85
+ # def self.default_scope
86
+ # # Should return a scope, you can call 'super' here etc.
87
+ # end
88
+ # end
89
+ def default_scope(scope = nil) # :doc:
90
+ scope = Proc.new if block_given?
91
+
92
+ if scope.is_a?(Relation) || !scope.respond_to?(:call)
93
+ raise ArgumentError,
94
+ "Support for calling #default_scope without a block is removed. For example instead " \
95
+ "of `default_scope where(color: 'red')`, please use " \
96
+ "`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
97
+ "self.default_scope.)"
98
+ end
99
+
100
+ self.default_scopes += [scope]
101
+ end
102
+
103
+ def build_default_scope(base_rel = nil)
104
+ return if abstract_class?
105
+
106
+ if default_scope_override.nil?
107
+ self.default_scope_override = !Base.is_a?(method(:default_scope).owner)
108
+ end
109
+
110
+ if default_scope_override
111
+ # The user has defined their own default scope method, so call that
112
+ evaluate_default_scope do
113
+ if scope = default_scope
114
+ (base_rel ||= relation).merge!(scope)
115
+ end
116
+ end
117
+ elsif default_scopes.any?
118
+ base_rel ||= relation
119
+ evaluate_default_scope do
120
+ default_scopes.inject(base_rel) do |default_scope, scope|
121
+ scope = scope.respond_to?(:to_proc) ? scope : scope.method(:call)
122
+ default_scope.merge!(base_rel.instance_exec(&scope))
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ def ignore_default_scope?
129
+ ScopeRegistry.value_for(:ignore_default_scope, base_class)
130
+ end
131
+
132
+ def ignore_default_scope=(ignore)
133
+ ScopeRegistry.set_value_for(:ignore_default_scope, base_class, ignore)
134
+ end
135
+
136
+ # The ignore_default_scope flag is used to prevent an infinite recursion
137
+ # situation where a default scope references a scope which has a default
138
+ # scope which references a scope...
139
+ def evaluate_default_scope
140
+ return if ignore_default_scope?
141
+
142
+ begin
143
+ self.ignore_default_scope = true
144
+ yield
145
+ ensure
146
+ self.ignore_default_scope = false
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,213 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/array"
4
+ require "active_support/core_ext/hash/except"
5
+ require "active_support/core_ext/kernel/singleton_class"
6
+
7
+ module ActiveRecord
8
+ # = Active Record \Named \Scopes
9
+ module Scoping
10
+ module Named
11
+ extend ActiveSupport::Concern
12
+
13
+ module ClassMethods
14
+ # Returns an ActiveRecord::Relation scope object.
15
+ #
16
+ # posts = Post.all
17
+ # posts.size # Fires "select count(*) from posts" and returns the count
18
+ # posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
19
+ #
20
+ # fruits = Fruit.all
21
+ # fruits = fruits.where(color: 'red') if options[:red_only]
22
+ # fruits = fruits.limit(10) if limited?
23
+ #
24
+ # You can define a scope that applies to all finders using
25
+ # {default_scope}[rdoc-ref:Scoping::Default::ClassMethods#default_scope].
26
+ def all
27
+ current_scope = self.current_scope
28
+
29
+ if current_scope
30
+ if self == current_scope.klass
31
+ current_scope.clone
32
+ else
33
+ relation.merge!(current_scope)
34
+ end
35
+ else
36
+ default_scoped
37
+ end
38
+ end
39
+
40
+ def scope_for_association(scope = relation) # :nodoc:
41
+ current_scope = self.current_scope
42
+
43
+ if current_scope && current_scope.empty_scope?
44
+ scope
45
+ else
46
+ default_scoped(scope)
47
+ end
48
+ end
49
+
50
+ def default_scoped(scope = relation) # :nodoc:
51
+ build_default_scope(scope) || scope
52
+ end
53
+
54
+ def default_extensions # :nodoc:
55
+ if scope = current_scope || build_default_scope
56
+ scope.extensions
57
+ else
58
+ []
59
+ end
60
+ end
61
+
62
+ # Adds a class method for retrieving and querying objects.
63
+ # The method is intended to return an ActiveRecord::Relation
64
+ # object, which is composable with other scopes.
65
+ # If it returns +nil+ or +false+, an
66
+ # {all}[rdoc-ref:Scoping::Named::ClassMethods#all] scope is returned instead.
67
+ #
68
+ # A \scope represents a narrowing of a database query, such as
69
+ # <tt>where(color: :red).select('shirts.*').includes(:washing_instructions)</tt>.
70
+ #
71
+ # class Shirt < ActiveRecord::Base
72
+ # scope :red, -> { where(color: 'red') }
73
+ # scope :dry_clean_only, -> { joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true) }
74
+ # end
75
+ #
76
+ # The above calls to #scope define class methods <tt>Shirt.red</tt> and
77
+ # <tt>Shirt.dry_clean_only</tt>. <tt>Shirt.red</tt>, in effect,
78
+ # represents the query <tt>Shirt.where(color: 'red')</tt>.
79
+ #
80
+ # You should always pass a callable object to the scopes defined
81
+ # with #scope. This ensures that the scope is re-evaluated each
82
+ # time it is called.
83
+ #
84
+ # Note that this is simply 'syntactic sugar' for defining an actual
85
+ # class method:
86
+ #
87
+ # class Shirt < ActiveRecord::Base
88
+ # def self.red
89
+ # where(color: 'red')
90
+ # end
91
+ # end
92
+ #
93
+ # Unlike <tt>Shirt.find(...)</tt>, however, the object returned by
94
+ # <tt>Shirt.red</tt> is not an Array but an ActiveRecord::Relation,
95
+ # which is composable with other scopes; it resembles the association object
96
+ # constructed by a {has_many}[rdoc-ref:Associations::ClassMethods#has_many]
97
+ # declaration. For instance, you can invoke <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>,
98
+ # <tt>Shirt.red.where(size: 'small')</tt>. Also, just as with the
99
+ # association objects, named \scopes act like an Array, implementing
100
+ # Enumerable; <tt>Shirt.red.each(&block)</tt>, <tt>Shirt.red.first</tt>,
101
+ # and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if
102
+ # <tt>Shirt.red</tt> really was an array.
103
+ #
104
+ # These named \scopes are composable. For instance,
105
+ # <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are
106
+ # both red and dry clean only. Nested finds and calculations also work
107
+ # with these compositions: <tt>Shirt.red.dry_clean_only.count</tt>
108
+ # returns the number of garments for which these criteria obtain.
109
+ # Similarly with <tt>Shirt.red.dry_clean_only.average(:thread_count)</tt>.
110
+ #
111
+ # All scopes are available as class methods on the ActiveRecord::Base
112
+ # descendant upon which the \scopes were defined. But they are also
113
+ # available to {has_many}[rdoc-ref:Associations::ClassMethods#has_many]
114
+ # associations. If,
115
+ #
116
+ # class Person < ActiveRecord::Base
117
+ # has_many :shirts
118
+ # end
119
+ #
120
+ # then <tt>elton.shirts.red.dry_clean_only</tt> will return all of
121
+ # Elton's red, dry clean only shirts.
122
+ #
123
+ # \Named scopes can also have extensions, just as with
124
+ # {has_many}[rdoc-ref:Associations::ClassMethods#has_many] declarations:
125
+ #
126
+ # class Shirt < ActiveRecord::Base
127
+ # scope :red, -> { where(color: 'red') } do
128
+ # def dom_id
129
+ # 'red_shirts'
130
+ # end
131
+ # end
132
+ # end
133
+ #
134
+ # Scopes can also be used while creating/building a record.
135
+ #
136
+ # class Article < ActiveRecord::Base
137
+ # scope :published, -> { where(published: true) }
138
+ # end
139
+ #
140
+ # Article.published.new.published # => true
141
+ # Article.published.create.published # => true
142
+ #
143
+ # \Class methods on your model are automatically available
144
+ # on scopes. Assuming the following setup:
145
+ #
146
+ # class Article < ActiveRecord::Base
147
+ # scope :published, -> { where(published: true) }
148
+ # scope :featured, -> { where(featured: true) }
149
+ #
150
+ # def self.latest_article
151
+ # order('published_at desc').first
152
+ # end
153
+ #
154
+ # def self.titles
155
+ # pluck(:title)
156
+ # end
157
+ # end
158
+ #
159
+ # We are able to call the methods like this:
160
+ #
161
+ # Article.published.featured.latest_article
162
+ # Article.featured.titles
163
+ def scope(name, body, &block)
164
+ unless body.respond_to?(:call)
165
+ raise ArgumentError, "The scope body needs to be callable."
166
+ end
167
+
168
+ if dangerous_class_method?(name)
169
+ raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
170
+ "on the model \"#{self.name}\", but Active Record already defined " \
171
+ "a class method with the same name."
172
+ end
173
+
174
+ if method_defined_within?(name, Relation)
175
+ raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
176
+ "on the model \"#{self.name}\", but ActiveRecord::Relation already defined " \
177
+ "an instance method with the same name."
178
+ end
179
+
180
+ valid_scope_name?(name)
181
+ extension = Module.new(&block) if block
182
+
183
+ if body.respond_to?(:to_proc)
184
+ singleton_class.send(:define_method, name) do |*args|
185
+ scope = all
186
+ scope = scope._exec_scope(*args, &body)
187
+ scope = scope.extending(extension) if extension
188
+ scope
189
+ end
190
+ else
191
+ singleton_class.send(:define_method, name) do |*args|
192
+ scope = all
193
+ scope = scope.scoping { body.call(*args) || scope }
194
+ scope = scope.extending(extension) if extension
195
+ scope
196
+ end
197
+ end
198
+
199
+ generate_relation_method(name)
200
+ end
201
+
202
+ private
203
+
204
+ def valid_scope_name?(name)
205
+ if respond_to?(name, true) && logger
206
+ logger.warn "Creating scope :#{name}. " \
207
+ "Overwriting existing method #{self.name}.#{name}."
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end