omg-activerecord 8.0.0.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (412) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +355 -0
  3. data/MIT-LICENSE +22 -0
  4. data/README.rdoc +219 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record/aggregations.rb +287 -0
  8. data/lib/active_record/association_relation.rb +50 -0
  9. data/lib/active_record/associations/alias_tracker.rb +90 -0
  10. data/lib/active_record/associations/association.rb +417 -0
  11. data/lib/active_record/associations/association_scope.rb +175 -0
  12. data/lib/active_record/associations/belongs_to_association.rb +163 -0
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
  14. data/lib/active_record/associations/builder/association.rb +170 -0
  15. data/lib/active_record/associations/builder/belongs_to.rb +160 -0
  16. data/lib/active_record/associations/builder/collection_association.rb +80 -0
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +107 -0
  18. data/lib/active_record/associations/builder/has_many.rb +23 -0
  19. data/lib/active_record/associations/builder/has_one.rb +61 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +48 -0
  21. data/lib/active_record/associations/collection_association.rb +535 -0
  22. data/lib/active_record/associations/collection_proxy.rb +1163 -0
  23. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  24. data/lib/active_record/associations/errors.rb +265 -0
  25. data/lib/active_record/associations/foreign_association.rb +40 -0
  26. data/lib/active_record/associations/has_many_association.rb +167 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +232 -0
  28. data/lib/active_record/associations/has_one_association.rb +142 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency/join_association.rb +106 -0
  31. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  32. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  33. data/lib/active_record/associations/join_dependency.rb +301 -0
  34. data/lib/active_record/associations/nested_error.rb +47 -0
  35. data/lib/active_record/associations/preloader/association.rb +316 -0
  36. data/lib/active_record/associations/preloader/batch.rb +48 -0
  37. data/lib/active_record/associations/preloader/branch.rb +153 -0
  38. data/lib/active_record/associations/preloader/through_association.rb +150 -0
  39. data/lib/active_record/associations/preloader.rb +135 -0
  40. data/lib/active_record/associations/singular_association.rb +76 -0
  41. data/lib/active_record/associations/through_association.rb +132 -0
  42. data/lib/active_record/associations.rb +1897 -0
  43. data/lib/active_record/asynchronous_queries_tracker.rb +64 -0
  44. data/lib/active_record/attribute_assignment.rb +82 -0
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +106 -0
  46. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  47. data/lib/active_record/attribute_methods/dirty.rb +262 -0
  48. data/lib/active_record/attribute_methods/primary_key.rb +158 -0
  49. data/lib/active_record/attribute_methods/query.rb +50 -0
  50. data/lib/active_record/attribute_methods/read.rb +46 -0
  51. data/lib/active_record/attribute_methods/serialization.rb +232 -0
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +94 -0
  53. data/lib/active_record/attribute_methods/write.rb +49 -0
  54. data/lib/active_record/attribute_methods.rb +542 -0
  55. data/lib/active_record/attributes.rb +307 -0
  56. data/lib/active_record/autosave_association.rb +586 -0
  57. data/lib/active_record/base.rb +338 -0
  58. data/lib/active_record/callbacks.rb +452 -0
  59. data/lib/active_record/coders/column_serializer.rb +61 -0
  60. data/lib/active_record/coders/json.rb +15 -0
  61. data/lib/active_record/coders/yaml_column.rb +95 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +290 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +210 -0
  64. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +923 -0
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +31 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +747 -0
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +319 -0
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +239 -0
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +24 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +190 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +961 -0
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +106 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1883 -0
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +676 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +1218 -0
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1016 -0
  78. data/lib/active_record/connection_adapters/column.rb +122 -0
  79. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  80. data/lib/active_record/connection_adapters/mysql/column.rb +28 -0
  81. data/lib/active_record/connection_adapters/mysql/database_statements.rb +95 -0
  82. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  83. data/lib/active_record/connection_adapters/mysql/quoting.rb +114 -0
  84. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +106 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +106 -0
  86. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +97 -0
  87. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +300 -0
  88. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  89. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +96 -0
  90. data/lib/active_record/connection_adapters/mysql2_adapter.rb +196 -0
  91. data/lib/active_record/connection_adapters/pool_config.rb +83 -0
  92. data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
  93. data/lib/active_record/connection_adapters/postgresql/column.rb +82 -0
  94. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +231 -0
  95. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +91 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +54 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +31 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +20 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +109 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +42 -0
  112. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  113. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +74 -0
  114. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +124 -0
  115. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  116. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  117. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  118. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +125 -0
  119. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +45 -0
  120. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  121. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  122. data/lib/active_record/connection_adapters/postgresql/oid.rb +38 -0
  123. data/lib/active_record/connection_adapters/postgresql/quoting.rb +238 -0
  124. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +71 -0
  125. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +169 -0
  126. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +392 -0
  127. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +127 -0
  128. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1162 -0
  129. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  130. data/lib/active_record/connection_adapters/postgresql/utils.rb +79 -0
  131. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1182 -0
  132. data/lib/active_record/connection_adapters/schema_cache.rb +478 -0
  133. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  134. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  135. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +145 -0
  136. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  137. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +116 -0
  138. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +37 -0
  139. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +39 -0
  140. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +47 -0
  141. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +221 -0
  142. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +843 -0
  143. data/lib/active_record/connection_adapters/statement_pool.rb +67 -0
  144. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +69 -0
  145. data/lib/active_record/connection_adapters/trilogy_adapter.rb +212 -0
  146. data/lib/active_record/connection_adapters.rb +176 -0
  147. data/lib/active_record/connection_handling.rb +413 -0
  148. data/lib/active_record/core.rb +836 -0
  149. data/lib/active_record/counter_cache.rb +230 -0
  150. data/lib/active_record/database_configurations/connection_url_resolver.rb +105 -0
  151. data/lib/active_record/database_configurations/database_config.rb +104 -0
  152. data/lib/active_record/database_configurations/hash_config.rb +172 -0
  153. data/lib/active_record/database_configurations/url_config.rb +78 -0
  154. data/lib/active_record/database_configurations.rb +309 -0
  155. data/lib/active_record/delegated_type.rb +289 -0
  156. data/lib/active_record/deprecator.rb +7 -0
  157. data/lib/active_record/destroy_association_async_job.rb +38 -0
  158. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  159. data/lib/active_record/dynamic_matchers.rb +121 -0
  160. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  161. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  162. data/lib/active_record/encryption/cipher.rb +53 -0
  163. data/lib/active_record/encryption/config.rb +70 -0
  164. data/lib/active_record/encryption/configurable.rb +60 -0
  165. data/lib/active_record/encryption/context.rb +42 -0
  166. data/lib/active_record/encryption/contexts.rb +76 -0
  167. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  168. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  169. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  170. data/lib/active_record/encryption/encrypted_attribute_type.rb +184 -0
  171. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  172. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  173. data/lib/active_record/encryption/encryptor.rb +177 -0
  174. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  175. data/lib/active_record/encryption/errors.rb +15 -0
  176. data/lib/active_record/encryption/extended_deterministic_queries.rb +159 -0
  177. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  178. data/lib/active_record/encryption/key.rb +28 -0
  179. data/lib/active_record/encryption/key_generator.rb +53 -0
  180. data/lib/active_record/encryption/key_provider.rb +46 -0
  181. data/lib/active_record/encryption/message.rb +33 -0
  182. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  183. data/lib/active_record/encryption/message_serializer.rb +96 -0
  184. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  185. data/lib/active_record/encryption/properties.rb +76 -0
  186. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  187. data/lib/active_record/encryption/scheme.rb +107 -0
  188. data/lib/active_record/encryption.rb +58 -0
  189. data/lib/active_record/enum.rb +424 -0
  190. data/lib/active_record/errors.rb +614 -0
  191. data/lib/active_record/explain.rb +63 -0
  192. data/lib/active_record/explain_registry.rb +37 -0
  193. data/lib/active_record/explain_subscriber.rb +34 -0
  194. data/lib/active_record/fixture_set/file.rb +89 -0
  195. data/lib/active_record/fixture_set/model_metadata.rb +42 -0
  196. data/lib/active_record/fixture_set/render_context.rb +19 -0
  197. data/lib/active_record/fixture_set/table_row.rb +208 -0
  198. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  199. data/lib/active_record/fixtures.rb +850 -0
  200. data/lib/active_record/future_result.rb +182 -0
  201. data/lib/active_record/gem_version.rb +17 -0
  202. data/lib/active_record/inheritance.rb +366 -0
  203. data/lib/active_record/insert_all.rb +328 -0
  204. data/lib/active_record/integration.rb +209 -0
  205. data/lib/active_record/internal_metadata.rb +164 -0
  206. data/lib/active_record/legacy_yaml_adapter.rb +15 -0
  207. data/lib/active_record/locale/en.yml +48 -0
  208. data/lib/active_record/locking/optimistic.rb +228 -0
  209. data/lib/active_record/locking/pessimistic.rb +102 -0
  210. data/lib/active_record/log_subscriber.rb +149 -0
  211. data/lib/active_record/marshalling.rb +56 -0
  212. data/lib/active_record/message_pack.rb +124 -0
  213. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  214. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  215. data/lib/active_record/middleware/database_selector.rb +87 -0
  216. data/lib/active_record/middleware/shard_selector.rb +62 -0
  217. data/lib/active_record/migration/command_recorder.rb +406 -0
  218. data/lib/active_record/migration/compatibility.rb +490 -0
  219. data/lib/active_record/migration/default_strategy.rb +22 -0
  220. data/lib/active_record/migration/execution_strategy.rb +19 -0
  221. data/lib/active_record/migration/join_table.rb +16 -0
  222. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  223. data/lib/active_record/migration.rb +1626 -0
  224. data/lib/active_record/model_schema.rb +635 -0
  225. data/lib/active_record/nested_attributes.rb +633 -0
  226. data/lib/active_record/no_touching.rb +65 -0
  227. data/lib/active_record/normalization.rb +163 -0
  228. data/lib/active_record/persistence.rb +968 -0
  229. data/lib/active_record/promise.rb +84 -0
  230. data/lib/active_record/query_cache.rb +56 -0
  231. data/lib/active_record/query_logs.rb +247 -0
  232. data/lib/active_record/query_logs_formatter.rb +30 -0
  233. data/lib/active_record/querying.rb +122 -0
  234. data/lib/active_record/railtie.rb +440 -0
  235. data/lib/active_record/railties/console_sandbox.rb +5 -0
  236. data/lib/active_record/railties/controller_runtime.rb +65 -0
  237. data/lib/active_record/railties/databases.rake +641 -0
  238. data/lib/active_record/railties/job_runtime.rb +23 -0
  239. data/lib/active_record/readonly_attributes.rb +66 -0
  240. data/lib/active_record/reflection.rb +1287 -0
  241. data/lib/active_record/relation/batches/batch_enumerator.rb +115 -0
  242. data/lib/active_record/relation/batches.rb +491 -0
  243. data/lib/active_record/relation/calculations.rb +679 -0
  244. data/lib/active_record/relation/delegation.rb +154 -0
  245. data/lib/active_record/relation/finder_methods.rb +661 -0
  246. data/lib/active_record/relation/from_clause.rb +30 -0
  247. data/lib/active_record/relation/merger.rb +192 -0
  248. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  249. data/lib/active_record/relation/predicate_builder/association_query_value.rb +76 -0
  250. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  251. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +60 -0
  252. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  253. data/lib/active_record/relation/predicate_builder/relation_handler.rb +24 -0
  254. data/lib/active_record/relation/predicate_builder.rb +181 -0
  255. data/lib/active_record/relation/query_attribute.rb +68 -0
  256. data/lib/active_record/relation/query_methods.rb +2235 -0
  257. data/lib/active_record/relation/record_fetch_warning.rb +52 -0
  258. data/lib/active_record/relation/spawn_methods.rb +78 -0
  259. data/lib/active_record/relation/where_clause.rb +218 -0
  260. data/lib/active_record/relation.rb +1495 -0
  261. data/lib/active_record/result.rb +249 -0
  262. data/lib/active_record/runtime_registry.rb +82 -0
  263. data/lib/active_record/sanitization.rb +254 -0
  264. data/lib/active_record/schema.rb +77 -0
  265. data/lib/active_record/schema_dumper.rb +364 -0
  266. data/lib/active_record/schema_migration.rb +106 -0
  267. data/lib/active_record/scoping/default.rb +205 -0
  268. data/lib/active_record/scoping/named.rb +202 -0
  269. data/lib/active_record/scoping.rb +136 -0
  270. data/lib/active_record/secure_password.rb +60 -0
  271. data/lib/active_record/secure_token.rb +66 -0
  272. data/lib/active_record/serialization.rb +29 -0
  273. data/lib/active_record/signed_id.rb +137 -0
  274. data/lib/active_record/statement_cache.rb +164 -0
  275. data/lib/active_record/store.rb +299 -0
  276. data/lib/active_record/suppressor.rb +59 -0
  277. data/lib/active_record/table_metadata.rb +85 -0
  278. data/lib/active_record/tasks/database_tasks.rb +681 -0
  279. data/lib/active_record/tasks/mysql_database_tasks.rb +120 -0
  280. data/lib/active_record/tasks/postgresql_database_tasks.rb +147 -0
  281. data/lib/active_record/tasks/sqlite_database_tasks.rb +89 -0
  282. data/lib/active_record/test_databases.rb +24 -0
  283. data/lib/active_record/test_fixtures.rb +321 -0
  284. data/lib/active_record/testing/query_assertions.rb +121 -0
  285. data/lib/active_record/timestamp.rb +177 -0
  286. data/lib/active_record/token_for.rb +123 -0
  287. data/lib/active_record/touch_later.rb +70 -0
  288. data/lib/active_record/transaction.rb +132 -0
  289. data/lib/active_record/transactions.rb +523 -0
  290. data/lib/active_record/translation.rb +22 -0
  291. data/lib/active_record/type/adapter_specific_registry.rb +144 -0
  292. data/lib/active_record/type/date.rb +9 -0
  293. data/lib/active_record/type/date_time.rb +9 -0
  294. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  295. data/lib/active_record/type/hash_lookup_type_map.rb +57 -0
  296. data/lib/active_record/type/internal/timezone.rb +22 -0
  297. data/lib/active_record/type/json.rb +30 -0
  298. data/lib/active_record/type/serialized.rb +76 -0
  299. data/lib/active_record/type/text.rb +11 -0
  300. data/lib/active_record/type/time.rb +35 -0
  301. data/lib/active_record/type/type_map.rb +58 -0
  302. data/lib/active_record/type/unsigned_integer.rb +16 -0
  303. data/lib/active_record/type.rb +83 -0
  304. data/lib/active_record/type_caster/connection.rb +33 -0
  305. data/lib/active_record/type_caster/map.rb +23 -0
  306. data/lib/active_record/type_caster.rb +9 -0
  307. data/lib/active_record/validations/absence.rb +25 -0
  308. data/lib/active_record/validations/associated.rb +65 -0
  309. data/lib/active_record/validations/length.rb +26 -0
  310. data/lib/active_record/validations/numericality.rb +36 -0
  311. data/lib/active_record/validations/presence.rb +45 -0
  312. data/lib/active_record/validations/uniqueness.rb +295 -0
  313. data/lib/active_record/validations.rb +101 -0
  314. data/lib/active_record/version.rb +10 -0
  315. data/lib/active_record.rb +616 -0
  316. data/lib/arel/alias_predication.rb +9 -0
  317. data/lib/arel/attributes/attribute.rb +33 -0
  318. data/lib/arel/collectors/bind.rb +31 -0
  319. data/lib/arel/collectors/composite.rb +46 -0
  320. data/lib/arel/collectors/plain_string.rb +20 -0
  321. data/lib/arel/collectors/sql_string.rb +27 -0
  322. data/lib/arel/collectors/substitute_binds.rb +35 -0
  323. data/lib/arel/crud.rb +48 -0
  324. data/lib/arel/delete_manager.rb +32 -0
  325. data/lib/arel/errors.rb +19 -0
  326. data/lib/arel/expressions.rb +29 -0
  327. data/lib/arel/factory_methods.rb +53 -0
  328. data/lib/arel/filter_predications.rb +9 -0
  329. data/lib/arel/insert_manager.rb +48 -0
  330. data/lib/arel/math.rb +45 -0
  331. data/lib/arel/nodes/ascending.rb +23 -0
  332. data/lib/arel/nodes/binary.rb +125 -0
  333. data/lib/arel/nodes/bind_param.rb +44 -0
  334. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  335. data/lib/arel/nodes/case.rb +55 -0
  336. data/lib/arel/nodes/casted.rb +62 -0
  337. data/lib/arel/nodes/comment.rb +29 -0
  338. data/lib/arel/nodes/count.rb +12 -0
  339. data/lib/arel/nodes/cte.rb +36 -0
  340. data/lib/arel/nodes/delete_statement.rb +44 -0
  341. data/lib/arel/nodes/descending.rb +23 -0
  342. data/lib/arel/nodes/equality.rb +15 -0
  343. data/lib/arel/nodes/extract.rb +24 -0
  344. data/lib/arel/nodes/false.rb +16 -0
  345. data/lib/arel/nodes/filter.rb +10 -0
  346. data/lib/arel/nodes/fragments.rb +35 -0
  347. data/lib/arel/nodes/full_outer_join.rb +8 -0
  348. data/lib/arel/nodes/function.rb +45 -0
  349. data/lib/arel/nodes/grouping.rb +11 -0
  350. data/lib/arel/nodes/homogeneous_in.rb +68 -0
  351. data/lib/arel/nodes/in.rb +15 -0
  352. data/lib/arel/nodes/infix_operation.rb +92 -0
  353. data/lib/arel/nodes/inner_join.rb +8 -0
  354. data/lib/arel/nodes/insert_statement.rb +37 -0
  355. data/lib/arel/nodes/join_source.rb +20 -0
  356. data/lib/arel/nodes/leading_join.rb +8 -0
  357. data/lib/arel/nodes/matches.rb +18 -0
  358. data/lib/arel/nodes/named_function.rb +23 -0
  359. data/lib/arel/nodes/nary.rb +39 -0
  360. data/lib/arel/nodes/node.rb +161 -0
  361. data/lib/arel/nodes/node_expression.rb +13 -0
  362. data/lib/arel/nodes/ordering.rb +27 -0
  363. data/lib/arel/nodes/outer_join.rb +8 -0
  364. data/lib/arel/nodes/over.rb +15 -0
  365. data/lib/arel/nodes/regexp.rb +16 -0
  366. data/lib/arel/nodes/right_outer_join.rb +8 -0
  367. data/lib/arel/nodes/select_core.rb +67 -0
  368. data/lib/arel/nodes/select_statement.rb +41 -0
  369. data/lib/arel/nodes/sql_literal.rb +32 -0
  370. data/lib/arel/nodes/string_join.rb +11 -0
  371. data/lib/arel/nodes/table_alias.rb +35 -0
  372. data/lib/arel/nodes/terminal.rb +16 -0
  373. data/lib/arel/nodes/true.rb +16 -0
  374. data/lib/arel/nodes/unary.rb +44 -0
  375. data/lib/arel/nodes/unary_operation.rb +20 -0
  376. data/lib/arel/nodes/unqualified_column.rb +22 -0
  377. data/lib/arel/nodes/update_statement.rb +46 -0
  378. data/lib/arel/nodes/values_list.rb +9 -0
  379. data/lib/arel/nodes/window.rb +126 -0
  380. data/lib/arel/nodes/with.rb +11 -0
  381. data/lib/arel/nodes.rb +75 -0
  382. data/lib/arel/order_predications.rb +13 -0
  383. data/lib/arel/predications.rb +260 -0
  384. data/lib/arel/select_manager.rb +276 -0
  385. data/lib/arel/table.rb +121 -0
  386. data/lib/arel/tree_manager.rb +65 -0
  387. data/lib/arel/update_manager.rb +49 -0
  388. data/lib/arel/visitors/dot.rb +299 -0
  389. data/lib/arel/visitors/mysql.rb +111 -0
  390. data/lib/arel/visitors/postgresql.rb +99 -0
  391. data/lib/arel/visitors/sqlite.rb +38 -0
  392. data/lib/arel/visitors/to_sql.rb +1033 -0
  393. data/lib/arel/visitors/visitor.rb +45 -0
  394. data/lib/arel/visitors.rb +13 -0
  395. data/lib/arel/window_predications.rb +9 -0
  396. data/lib/arel.rb +73 -0
  397. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  398. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  399. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  400. data/lib/rails/generators/active_record/migration/migration_generator.rb +76 -0
  401. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +29 -0
  402. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  403. data/lib/rails/generators/active_record/migration.rb +54 -0
  404. data/lib/rails/generators/active_record/model/USAGE +113 -0
  405. data/lib/rails/generators/active_record/model/model_generator.rb +94 -0
  406. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  407. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  408. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  409. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  410. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  411. data/lib/rails/generators/active_record.rb +19 -0
  412. metadata +505 -0
@@ -0,0 +1,364 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+
5
+ module ActiveRecord
6
+ # = Active Record Schema Dumper
7
+ #
8
+ # This class is used to dump the database schema for some connection to some
9
+ # output format (i.e., ActiveRecord::Schema).
10
+ class SchemaDumper # :nodoc:
11
+ private_class_method :new
12
+
13
+ ##
14
+ # :singleton-method:
15
+ # A list of tables which should not be dumped to the schema.
16
+ # Acceptable values are strings and regexps.
17
+ cattr_accessor :ignore_tables, default: []
18
+
19
+ ##
20
+ # :singleton-method:
21
+ # Specify a custom regular expression matching foreign keys which name
22
+ # should not be dumped to db/schema.rb.
23
+ cattr_accessor :fk_ignore_pattern, default: /^fk_rails_[0-9a-f]{10}$/
24
+
25
+ ##
26
+ # :singleton-method:
27
+ # Specify a custom regular expression matching check constraints which name
28
+ # should not be dumped to db/schema.rb.
29
+ cattr_accessor :chk_ignore_pattern, default: /^chk_rails_[0-9a-f]{10}$/
30
+
31
+ ##
32
+ # :singleton-method:
33
+ # Specify a custom regular expression matching exclusion constraints which name
34
+ # should not be dumped to db/schema.rb.
35
+ cattr_accessor :excl_ignore_pattern, default: /^excl_rails_[0-9a-f]{10}$/
36
+
37
+ ##
38
+ # :singleton-method:
39
+ # Specify a custom regular expression matching unique constraints which name
40
+ # should not be dumped to db/schema.rb.
41
+ cattr_accessor :unique_ignore_pattern, default: /^uniq_rails_[0-9a-f]{10}$/
42
+
43
+ class << self
44
+ def dump(pool = ActiveRecord::Base.connection_pool, stream = $stdout, config = ActiveRecord::Base)
45
+ pool.with_connection do |connection|
46
+ connection.create_schema_dumper(generate_options(config)).dump(stream)
47
+ end
48
+ stream
49
+ end
50
+
51
+ private
52
+ def generate_options(config)
53
+ {
54
+ table_name_prefix: config.table_name_prefix,
55
+ table_name_suffix: config.table_name_suffix
56
+ }
57
+ end
58
+ end
59
+
60
+ def dump(stream)
61
+ header(stream)
62
+ schemas(stream)
63
+ extensions(stream)
64
+ types(stream)
65
+ tables(stream)
66
+ virtual_tables(stream)
67
+ trailer(stream)
68
+ stream
69
+ end
70
+
71
+ private
72
+ attr_accessor :table_name
73
+
74
+ def initialize(connection, options = {})
75
+ @connection = connection
76
+ @version = connection.pool.migration_context.current_version rescue nil
77
+ @options = options
78
+ @ignore_tables = [
79
+ ActiveRecord::Base.schema_migrations_table_name,
80
+ ActiveRecord::Base.internal_metadata_table_name,
81
+ self.class.ignore_tables
82
+ ].flatten
83
+ end
84
+
85
+ # turns 20170404131909 into "2017_04_04_131909"
86
+ def formatted_version
87
+ stringified = @version.to_s
88
+ return stringified unless stringified.length == 14
89
+ stringified.insert(4, "_").insert(7, "_").insert(10, "_")
90
+ end
91
+
92
+ def define_params
93
+ @version ? "version: #{formatted_version}" : ""
94
+ end
95
+
96
+ def header(stream)
97
+ stream.puts <<~HEADER
98
+ # This file is auto-generated from the current state of the database. Instead
99
+ # of editing this file, please use the migrations feature of Active Record to
100
+ # incrementally modify your database, and then regenerate this schema definition.
101
+ #
102
+ # This file is the source Rails uses to define your schema when running `bin/rails
103
+ # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
104
+ # be faster and is potentially less error prone than running all of your
105
+ # migrations from scratch. Old migrations may fail to apply correctly if those
106
+ # migrations use external dependencies or application code.
107
+ #
108
+ # It's strongly recommended that you check this file into your version control system.
109
+
110
+ ActiveRecord::Schema[#{ActiveRecord::Migration.current_version}].define(#{define_params}) do
111
+ HEADER
112
+ end
113
+
114
+ def trailer(stream)
115
+ stream.puts "end"
116
+ end
117
+
118
+ # extensions are only supported by PostgreSQL
119
+ def extensions(stream)
120
+ end
121
+
122
+ # (enum) types are only supported by PostgreSQL
123
+ def types(stream)
124
+ end
125
+
126
+ # schemas are only supported by PostgreSQL
127
+ def schemas(stream)
128
+ end
129
+
130
+ # virtual tables are only supported by SQLite
131
+ def virtual_tables(stream)
132
+ end
133
+
134
+ def tables(stream)
135
+ sorted_tables = @connection.tables.sort
136
+
137
+ not_ignored_tables = sorted_tables.reject { |table_name| ignored?(table_name) }
138
+
139
+ not_ignored_tables.each_with_index do |table_name, index|
140
+ table(table_name, stream)
141
+ stream.puts if index < not_ignored_tables.count - 1
142
+ end
143
+
144
+ # dump foreign keys at the end to make sure all dependent tables exist.
145
+ if @connection.supports_foreign_keys?
146
+ foreign_keys_stream = StringIO.new
147
+ not_ignored_tables.each do |tbl|
148
+ foreign_keys(tbl, foreign_keys_stream)
149
+ end
150
+
151
+ foreign_keys_string = foreign_keys_stream.string
152
+ stream.puts if foreign_keys_string.length > 0
153
+
154
+ stream.print foreign_keys_string
155
+ end
156
+ end
157
+
158
+ def table(table, stream)
159
+ columns = @connection.columns(table)
160
+ begin
161
+ self.table_name = table
162
+
163
+ tbl = StringIO.new
164
+
165
+ # first dump primary key column
166
+ pk = @connection.primary_key(table)
167
+
168
+ tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}"
169
+
170
+ case pk
171
+ when String
172
+ tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
173
+ pkcol = columns.detect { |c| c.name == pk }
174
+ pkcolspec = column_spec_for_primary_key(pkcol)
175
+ unless pkcolspec.empty?
176
+ if pkcolspec != pkcolspec.slice(:id, :default)
177
+ pkcolspec = { id: { type: pkcolspec.delete(:id), **pkcolspec }.compact }
178
+ end
179
+ tbl.print ", #{format_colspec(pkcolspec)}"
180
+ end
181
+ when Array
182
+ tbl.print ", primary_key: #{pk.inspect}"
183
+ else
184
+ tbl.print ", id: false"
185
+ end
186
+
187
+ table_options = @connection.table_options(table)
188
+ if table_options.present?
189
+ tbl.print ", #{format_options(table_options)}"
190
+ end
191
+
192
+ tbl.puts ", force: :cascade do |t|"
193
+
194
+ # then dump all non-primary key columns
195
+ columns.each do |column|
196
+ raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
197
+ next if column.name == pk
198
+
199
+ type, colspec = column_spec(column)
200
+ if type.is_a?(Symbol)
201
+ tbl.print " t.#{type} #{column.name.inspect}"
202
+ else
203
+ tbl.print " t.column #{column.name.inspect}, #{type.inspect}"
204
+ end
205
+ tbl.print ", #{format_colspec(colspec)}" if colspec.present?
206
+ tbl.puts
207
+ end
208
+
209
+ indexes_in_create(table, tbl)
210
+ check_constraints_in_create(table, tbl) if @connection.supports_check_constraints?
211
+ exclusion_constraints_in_create(table, tbl) if @connection.supports_exclusion_constraints?
212
+ unique_constraints_in_create(table, tbl) if @connection.supports_unique_constraints?
213
+
214
+ tbl.puts " end"
215
+
216
+ stream.print tbl.string
217
+ rescue => e
218
+ stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
219
+ stream.puts "# #{e.message}"
220
+ stream.puts
221
+ ensure
222
+ self.table_name = nil
223
+ end
224
+ end
225
+
226
+ # Keep it for indexing materialized views
227
+ def indexes(table, stream)
228
+ if (indexes = @connection.indexes(table)).any?
229
+ add_index_statements = indexes.map do |index|
230
+ table_name = remove_prefix_and_suffix(index.table).inspect
231
+ " add_index #{([table_name] + index_parts(index)).join(', ')}"
232
+ end
233
+
234
+ stream.puts add_index_statements.sort.join("\n")
235
+ stream.puts
236
+ end
237
+ end
238
+
239
+ def indexes_in_create(table, stream)
240
+ if (indexes = @connection.indexes(table)).any?
241
+ if @connection.supports_exclusion_constraints? && (exclusion_constraints = @connection.exclusion_constraints(table)).any?
242
+ exclusion_constraint_names = exclusion_constraints.collect(&:name)
243
+
244
+ indexes = indexes.reject { |index| exclusion_constraint_names.include?(index.name) }
245
+ end
246
+
247
+ if @connection.supports_unique_constraints? && (unique_constraints = @connection.unique_constraints(table)).any?
248
+ unique_constraint_names = unique_constraints.collect(&:name)
249
+
250
+ indexes = indexes.reject { |index| unique_constraint_names.include?(index.name) }
251
+ end
252
+
253
+ index_statements = indexes.map do |index|
254
+ " t.index #{index_parts(index).join(', ')}"
255
+ end
256
+ stream.puts index_statements.sort.join("\n")
257
+ end
258
+ end
259
+
260
+ def index_parts(index)
261
+ index_parts = [
262
+ index.columns.inspect,
263
+ "name: #{index.name.inspect}",
264
+ ]
265
+ index_parts << "unique: true" if index.unique
266
+ index_parts << "length: #{format_index_parts(index.lengths)}" if index.lengths.present?
267
+ index_parts << "order: #{format_index_parts(index.orders)}" if index.orders.present?
268
+ index_parts << "opclass: #{format_index_parts(index.opclasses)}" if index.opclasses.present?
269
+ index_parts << "where: #{index.where.inspect}" if index.where
270
+ index_parts << "using: #{index.using.inspect}" if !@connection.default_index_type?(index)
271
+ index_parts << "include: #{index.include.inspect}" if index.include
272
+ index_parts << "nulls_not_distinct: #{index.nulls_not_distinct.inspect}" if index.nulls_not_distinct
273
+ index_parts << "type: #{index.type.inspect}" if index.type
274
+ index_parts << "comment: #{index.comment.inspect}" if index.comment
275
+ index_parts
276
+ end
277
+
278
+ def check_constraints_in_create(table, stream)
279
+ if (check_constraints = @connection.check_constraints(table)).any?
280
+ add_check_constraint_statements = check_constraints.map do |check_constraint|
281
+ parts = [
282
+ "t.check_constraint #{check_constraint.expression.inspect}"
283
+ ]
284
+
285
+ if check_constraint.export_name_on_schema_dump?
286
+ parts << "name: #{check_constraint.name.inspect}"
287
+ end
288
+
289
+ parts << "validate: #{check_constraint.validate?.inspect}" unless check_constraint.validate?
290
+
291
+ " #{parts.join(', ')}"
292
+ end
293
+
294
+ stream.puts add_check_constraint_statements.sort.join("\n")
295
+ end
296
+ end
297
+
298
+ def foreign_keys(table, stream)
299
+ if (foreign_keys = @connection.foreign_keys(table)).any?
300
+ add_foreign_key_statements = foreign_keys.map do |foreign_key|
301
+ parts = [
302
+ "add_foreign_key #{remove_prefix_and_suffix(foreign_key.from_table).inspect}",
303
+ remove_prefix_and_suffix(foreign_key.to_table).inspect,
304
+ ]
305
+
306
+ if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table, "id")
307
+ parts << "column: #{foreign_key.column.inspect}"
308
+ end
309
+
310
+ if foreign_key.custom_primary_key?
311
+ parts << "primary_key: #{foreign_key.primary_key.inspect}"
312
+ end
313
+
314
+ if foreign_key.export_name_on_schema_dump?
315
+ parts << "name: #{foreign_key.name.inspect}"
316
+ end
317
+
318
+ parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
319
+ parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
320
+ parts << "deferrable: #{foreign_key.deferrable.inspect}" if foreign_key.deferrable
321
+ parts << "validate: #{foreign_key.validate?.inspect}" unless foreign_key.validate?
322
+
323
+ " #{parts.join(', ')}"
324
+ end
325
+
326
+ stream.puts add_foreign_key_statements.sort.join("\n")
327
+ end
328
+ end
329
+
330
+ def format_colspec(colspec)
331
+ colspec.map do |key, value|
332
+ "#{key}: #{ value.is_a?(Hash) ? "{ #{format_colspec(value)} }" : value }"
333
+ end.join(", ")
334
+ end
335
+
336
+ def format_options(options)
337
+ options.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
338
+ end
339
+
340
+ def format_index_parts(options)
341
+ if options.is_a?(Hash)
342
+ "{ #{format_options(options)} }"
343
+ else
344
+ options.inspect
345
+ end
346
+ end
347
+
348
+ def remove_prefix_and_suffix(table)
349
+ # This method appears at the top when profiling active_record test cases run.
350
+ # Avoid costly calculation when there are no prefix and suffix.
351
+ return table if @options[:table_name_prefix].blank? && @options[:table_name_suffix].blank?
352
+
353
+ prefix = Regexp.escape(@options[:table_name_prefix].to_s)
354
+ suffix = Regexp.escape(@options[:table_name_suffix].to_s)
355
+ table.sub(/\A#{prefix}(.+)#{suffix}\z/, "\\1")
356
+ end
357
+
358
+ def ignored?(table_name)
359
+ @ignore_tables.any? do |ignored|
360
+ ignored === remove_prefix_and_suffix(table_name)
361
+ end
362
+ end
363
+ end
364
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ # This class is used to create a table that keeps track of which migrations
5
+ # have been applied to a given database. When a migration is run, its schema
6
+ # number is inserted in to the schema migrations table so it doesn't need
7
+ # to be executed the next time.
8
+ class SchemaMigration # :nodoc:
9
+ class NullSchemaMigration # :nodoc:
10
+ end
11
+
12
+ attr_reader :arel_table
13
+
14
+ def initialize(pool)
15
+ @pool = pool
16
+ @arel_table = Arel::Table.new(table_name)
17
+ end
18
+
19
+ def create_version(version)
20
+ im = Arel::InsertManager.new(arel_table)
21
+ im.insert(arel_table[primary_key] => version)
22
+ @pool.with_connection do |connection|
23
+ connection.insert(im, "#{self.class} Create", primary_key, version)
24
+ end
25
+ end
26
+
27
+ def delete_version(version)
28
+ dm = Arel::DeleteManager.new(arel_table)
29
+ dm.wheres = [arel_table[primary_key].eq(version)]
30
+
31
+ @pool.with_connection do |connection|
32
+ connection.delete(dm, "#{self.class} Destroy")
33
+ end
34
+ end
35
+
36
+ def delete_all_versions
37
+ # Eagerly check in connection to avoid checking in/out many times in the called method.
38
+ @pool.with_connection do
39
+ versions.each do |version|
40
+ delete_version(version)
41
+ end
42
+ end
43
+ end
44
+
45
+ def primary_key
46
+ "version"
47
+ end
48
+
49
+ def table_name
50
+ "#{ActiveRecord::Base.table_name_prefix}#{ActiveRecord::Base.schema_migrations_table_name}#{ActiveRecord::Base.table_name_suffix}"
51
+ end
52
+
53
+ def create_table
54
+ @pool.with_connection do |connection|
55
+ unless connection.table_exists?(table_name)
56
+ connection.create_table(table_name, id: false) do |t|
57
+ t.string :version, **connection.internal_string_options_for_primary_key
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ def drop_table
64
+ @pool.with_connection do |connection|
65
+ connection.drop_table table_name, if_exists: true
66
+ end
67
+ end
68
+
69
+ def normalize_migration_number(number)
70
+ "%.3d" % number.to_i
71
+ end
72
+
73
+ def normalized_versions
74
+ versions.map { |v| normalize_migration_number v }
75
+ end
76
+
77
+ def versions
78
+ sm = Arel::SelectManager.new(arel_table)
79
+ sm.project(arel_table[primary_key])
80
+ sm.order(arel_table[primary_key].asc)
81
+
82
+ @pool.with_connection do |connection|
83
+ connection.select_values(sm, "#{self.class} Load")
84
+ end
85
+ end
86
+
87
+ def integer_versions
88
+ versions.map(&:to_i)
89
+ end
90
+
91
+ def count
92
+ sm = Arel::SelectManager.new(arel_table)
93
+ sm.project(*Arel::Nodes::Count.new([Arel.star]))
94
+
95
+ @pool.with_connection do |connection|
96
+ connection.select_values(sm, "#{self.class} Count").first
97
+ end
98
+ end
99
+
100
+ def table_exists?
101
+ @pool.with_connection do |connection|
102
+ connection.data_source_exists?(table_name)
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Scoping
5
+ class DefaultScope # :nodoc:
6
+ attr_reader :scope, :all_queries
7
+
8
+ def initialize(scope, all_queries = nil)
9
+ @scope = scope
10
+ @all_queries = all_queries
11
+ end
12
+ end
13
+
14
+ module Default
15
+ extend ActiveSupport::Concern
16
+
17
+ included do
18
+ # Stores the default scope for the class.
19
+ class_attribute :default_scopes, instance_writer: false, instance_predicate: false, default: []
20
+ class_attribute :default_scope_override, instance_writer: false, instance_predicate: false, default: nil
21
+ end
22
+
23
+ module ClassMethods
24
+ # Returns a scope for the model without the previously set scopes.
25
+ #
26
+ # class Post < ActiveRecord::Base
27
+ # belongs_to :user
28
+ #
29
+ # def self.default_scope
30
+ # where(published: true)
31
+ # end
32
+ # end
33
+ #
34
+ # class User < ActiveRecord::Base
35
+ # has_many :posts
36
+ # end
37
+ #
38
+ # Post.all # Fires "SELECT * FROM posts WHERE published = true"
39
+ # Post.unscoped.all # Fires "SELECT * FROM posts"
40
+ # Post.where(published: false).unscoped.all # Fires "SELECT * FROM posts"
41
+ # User.find(1).posts # Fires "SELECT * FROM posts WHERE published = true AND posts.user_id = 1"
42
+ # User.find(1).posts.unscoped # Fires "SELECT * FROM posts"
43
+ #
44
+ # This method also accepts a block. All queries inside the block will
45
+ # not use the previously set scopes.
46
+ #
47
+ # Post.unscoped {
48
+ # Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
49
+ # }
50
+ def unscoped(&block)
51
+ block_given? ? relation.scoping(&block) : relation
52
+ end
53
+
54
+ # Are there attributes associated with this scope?
55
+ def scope_attributes? # :nodoc:
56
+ super || default_scopes.any? || respond_to?(:default_scope)
57
+ end
58
+
59
+ # Checks if the model has any default scopes. If all_queries
60
+ # is set to true, the method will check if there are any
61
+ # default_scopes for the model where +all_queries+ is true.
62
+ def default_scopes?(all_queries: false)
63
+ if all_queries
64
+ self.default_scopes.any?(&:all_queries)
65
+ else
66
+ self.default_scopes.any?
67
+ end
68
+ end
69
+
70
+ private
71
+ # Use this macro in your model to set a default scope for all operations on
72
+ # the model.
73
+ #
74
+ # class Article < ActiveRecord::Base
75
+ # default_scope { where(published: true) }
76
+ # end
77
+ #
78
+ # Article.all
79
+ # # SELECT * FROM articles WHERE published = true
80
+ #
81
+ # The #default_scope is also applied while creating/building a record.
82
+ # It is not applied while updating or deleting a record.
83
+ #
84
+ # Article.new.published # => true
85
+ # Article.create.published # => true
86
+ #
87
+ # To apply a #default_scope when updating or deleting a record, add
88
+ # <tt>all_queries: true</tt>:
89
+ #
90
+ # class Article < ActiveRecord::Base
91
+ # default_scope -> { where(blog_id: 1) }, all_queries: true
92
+ # end
93
+ #
94
+ # Applying a default scope to all queries will ensure that records
95
+ # are always queried by the additional conditions. Note that only
96
+ # where clauses apply, as it does not make sense to add order to
97
+ # queries that return a single object by primary key.
98
+ #
99
+ # Article.find(1).destroy
100
+ # # DELETE ... FROM `articles` where ID = 1 AND blog_id = 1;
101
+ #
102
+ # (You can also pass any object which responds to +call+ to the
103
+ # +default_scope+ macro, and it will be called when building the
104
+ # default scope.)
105
+ #
106
+ # If you use multiple #default_scope declarations in your model then
107
+ # they will be merged together:
108
+ #
109
+ # class Article < ActiveRecord::Base
110
+ # default_scope { where(published: true) }
111
+ # default_scope { where(rating: 'G') }
112
+ # end
113
+ #
114
+ # Article.all
115
+ # # SELECT * FROM articles WHERE published = true AND rating = 'G'
116
+ #
117
+ # This is also the case with inheritance and module includes where the
118
+ # parent or module defines a #default_scope and the child or including
119
+ # class defines a second one.
120
+ #
121
+ # If you need to do more complex things with a default scope, you can
122
+ # alternatively define it as a class method:
123
+ #
124
+ # class Article < ActiveRecord::Base
125
+ # def self.default_scope
126
+ # # Should return a scope, you can call 'super' here etc.
127
+ # end
128
+ # end
129
+ def default_scope(scope = nil, all_queries: nil, &block) # :doc:
130
+ scope = block if block_given?
131
+
132
+ if scope.is_a?(Relation) || !scope.respond_to?(:call)
133
+ raise ArgumentError,
134
+ "Support for calling #default_scope without a block is removed. For example instead " \
135
+ "of `default_scope where(color: 'red')`, please use " \
136
+ "`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
137
+ "self.default_scope.)"
138
+ end
139
+
140
+ default_scope = DefaultScope.new(scope, all_queries)
141
+
142
+ self.default_scopes += [default_scope]
143
+ end
144
+
145
+ def build_default_scope(relation = relation(), all_queries: nil)
146
+ return if abstract_class?
147
+
148
+ if default_scope_override.nil?
149
+ self.default_scope_override = !Base.is_a?(method(:default_scope).owner)
150
+ end
151
+
152
+ if default_scope_override
153
+ # The user has defined their own default scope method, so call that
154
+ evaluate_default_scope do
155
+ relation.scoping { default_scope }
156
+ end
157
+ elsif default_scopes.any?
158
+ evaluate_default_scope do
159
+ default_scopes.inject(relation) do |combined_scope, scope_obj|
160
+ if execute_scope?(all_queries, scope_obj)
161
+ scope = scope_obj.scope.respond_to?(:to_proc) ? scope_obj.scope : scope_obj.scope.method(:call)
162
+
163
+ combined_scope.instance_exec(&scope) || combined_scope
164
+ else
165
+ combined_scope
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ # If all_queries is nil, only execute on select and insert queries.
173
+ #
174
+ # If all_queries is true, check if the default_scope object has
175
+ # all_queries set, then execute on all queries; select, insert, update,
176
+ # delete, and reload.
177
+ def execute_scope?(all_queries, default_scope_obj)
178
+ all_queries.nil? || all_queries && default_scope_obj.all_queries
179
+ end
180
+
181
+ def ignore_default_scope?
182
+ ScopeRegistry.ignore_default_scope(base_class)
183
+ end
184
+
185
+ def ignore_default_scope=(ignore)
186
+ ScopeRegistry.set_ignore_default_scope(base_class, ignore)
187
+ end
188
+
189
+ # The ignore_default_scope flag is used to prevent an infinite recursion
190
+ # situation where a default scope references a scope which has a default
191
+ # scope which references a scope...
192
+ def evaluate_default_scope
193
+ return if ignore_default_scope?
194
+
195
+ begin
196
+ self.ignore_default_scope = true
197
+ yield
198
+ ensure
199
+ self.ignore_default_scope = false
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end