omg-activerecord 8.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
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,1163 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Associations
5
+ # = Active Record Collection Proxy
6
+ #
7
+ # Collection proxies in Active Record are middlemen between an
8
+ # <tt>association</tt>, and its <tt>target</tt> result set.
9
+ #
10
+ # For example, given
11
+ #
12
+ # class Blog < ActiveRecord::Base
13
+ # has_many :posts
14
+ # end
15
+ #
16
+ # blog = Blog.first
17
+ #
18
+ # The collection proxy returned by <tt>blog.posts</tt> is built from a
19
+ # <tt>:has_many</tt> <tt>association</tt>, and delegates to a collection
20
+ # of posts as the <tt>target</tt>.
21
+ #
22
+ # This class delegates unknown methods to the <tt>association</tt>'s
23
+ # relation class via a delegate cache.
24
+ #
25
+ # The <tt>target</tt> result set is not loaded until needed. For example,
26
+ #
27
+ # blog.posts.count
28
+ #
29
+ # is computed directly through SQL and does not trigger by itself the
30
+ # instantiation of the actual post records.
31
+ class CollectionProxy < Relation
32
+ def initialize(klass, association, **) # :nodoc:
33
+ @association = association
34
+ super klass
35
+
36
+ extensions = association.extensions
37
+ extend(*extensions) if extensions.any?
38
+ end
39
+
40
+ def target
41
+ @association.target
42
+ end
43
+
44
+ def load_target
45
+ @association.load_target
46
+ end
47
+
48
+ # Returns +true+ if the association has been loaded, otherwise +false+.
49
+ #
50
+ # person.pets.loaded? # => false
51
+ # person.pets.records
52
+ # person.pets.loaded? # => true
53
+ def loaded?
54
+ @association.loaded?
55
+ end
56
+ alias :loaded :loaded?
57
+
58
+ ##
59
+ # :method: select
60
+ #
61
+ # :call-seq:
62
+ # select(*fields, &block)
63
+ #
64
+ # Works in two ways.
65
+ #
66
+ # *First:* Specify a subset of fields to be selected from the result set.
67
+ #
68
+ # class Person < ActiveRecord::Base
69
+ # has_many :pets
70
+ # end
71
+ #
72
+ # person.pets
73
+ # # => [
74
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
75
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
76
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
77
+ # # ]
78
+ #
79
+ # person.pets.select(:name)
80
+ # # => [
81
+ # # #<Pet id: nil, name: "Fancy-Fancy">,
82
+ # # #<Pet id: nil, name: "Spook">,
83
+ # # #<Pet id: nil, name: "Choo-Choo">
84
+ # # ]
85
+ #
86
+ # person.pets.select(:id, :name)
87
+ # # => [
88
+ # # #<Pet id: 1, name: "Fancy-Fancy">,
89
+ # # #<Pet id: 2, name: "Spook">,
90
+ # # #<Pet id: 3, name: "Choo-Choo">
91
+ # # ]
92
+ #
93
+ # Be careful because this also means you're initializing a model
94
+ # object with only the fields that you've selected. If you attempt
95
+ # to access a field except +id+ that is not in the initialized record you'll
96
+ # receive:
97
+ #
98
+ # person.pets.select(:name).first.person_id
99
+ # # => ActiveModel::MissingAttributeError: missing attribute 'person_id' for Pet
100
+ #
101
+ # *Second:* You can pass a block so it can be used just like <tt>Array#select</tt>.
102
+ # This builds an array of objects from the database for the scope,
103
+ # converting them into an array and iterating through them using
104
+ # <tt>Array#select</tt>.
105
+ #
106
+ # person.pets.select { |pet| /oo/.match?(pet.name) }
107
+ # # => [
108
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
109
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
110
+ # # ]
111
+
112
+ # Finds an object in the collection responding to the +id+. Uses the same
113
+ # rules as ActiveRecord::FinderMethods.find. Returns ActiveRecord::RecordNotFound
114
+ # error if the object cannot be found.
115
+ #
116
+ # class Person < ActiveRecord::Base
117
+ # has_many :pets
118
+ # end
119
+ #
120
+ # person.pets
121
+ # # => [
122
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
123
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
124
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
125
+ # # ]
126
+ #
127
+ # person.pets.find(1) # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
128
+ # person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=4
129
+ #
130
+ # person.pets.find(2) { |pet| pet.name.downcase! }
131
+ # # => #<Pet id: 2, name: "fancy-fancy", person_id: 1>
132
+ #
133
+ # person.pets.find(2, 3)
134
+ # # => [
135
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
136
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
137
+ # # ]
138
+ def find(*args)
139
+ return super if block_given?
140
+ @association.find(*args)
141
+ end
142
+
143
+ ##
144
+ # :method: first
145
+ #
146
+ # :call-seq:
147
+ # first(limit = nil)
148
+ #
149
+ # Returns the first record, or the first +n+ records, from the collection.
150
+ # If the collection is empty, the first form returns +nil+, and the second
151
+ # form returns an empty array.
152
+ #
153
+ # class Person < ActiveRecord::Base
154
+ # has_many :pets
155
+ # end
156
+ #
157
+ # person.pets
158
+ # # => [
159
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
160
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
161
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
162
+ # # ]
163
+ #
164
+ # person.pets.first # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
165
+ #
166
+ # person.pets.first(2)
167
+ # # => [
168
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
169
+ # # #<Pet id: 2, name: "Spook", person_id: 1>
170
+ # # ]
171
+ #
172
+ # another_person_without.pets # => []
173
+ # another_person_without.pets.first # => nil
174
+ # another_person_without.pets.first(3) # => []
175
+
176
+ ##
177
+ # :method: second
178
+ #
179
+ # :call-seq:
180
+ # second()
181
+ #
182
+ # Same as #first except returns only the second record.
183
+
184
+ ##
185
+ # :method: third
186
+ #
187
+ # :call-seq:
188
+ # third()
189
+ #
190
+ # Same as #first except returns only the third record.
191
+
192
+ ##
193
+ # :method: fourth
194
+ #
195
+ # :call-seq:
196
+ # fourth()
197
+ #
198
+ # Same as #first except returns only the fourth record.
199
+
200
+ ##
201
+ # :method: fifth
202
+ #
203
+ # :call-seq:
204
+ # fifth()
205
+ #
206
+ # Same as #first except returns only the fifth record.
207
+
208
+ ##
209
+ # :method: forty_two
210
+ #
211
+ # :call-seq:
212
+ # forty_two()
213
+ #
214
+ # Same as #first except returns only the forty second record.
215
+ # Also known as accessing "the reddit".
216
+
217
+ ##
218
+ # :method: third_to_last
219
+ #
220
+ # :call-seq:
221
+ # third_to_last()
222
+ #
223
+ # Same as #last except returns only the third-to-last record.
224
+
225
+ ##
226
+ # :method: second_to_last
227
+ #
228
+ # :call-seq:
229
+ # second_to_last()
230
+ #
231
+ # Same as #last except returns only the second-to-last record.
232
+
233
+ # Returns the last record, or the last +n+ records, from the collection.
234
+ # If the collection is empty, the first form returns +nil+, and the second
235
+ # form returns an empty array.
236
+ #
237
+ # class Person < ActiveRecord::Base
238
+ # has_many :pets
239
+ # end
240
+ #
241
+ # person.pets
242
+ # # => [
243
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
244
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
245
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
246
+ # # ]
247
+ #
248
+ # person.pets.last # => #<Pet id: 3, name: "Choo-Choo", person_id: 1>
249
+ #
250
+ # person.pets.last(2)
251
+ # # => [
252
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
253
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
254
+ # # ]
255
+ #
256
+ # another_person_without.pets # => []
257
+ # another_person_without.pets.last # => nil
258
+ # another_person_without.pets.last(3) # => []
259
+ def last(limit = nil)
260
+ load_target if find_from_target?
261
+ super
262
+ end
263
+
264
+ # Gives a record (or N records if a parameter is supplied) from the collection
265
+ # using the same rules as ActiveRecord::FinderMethods.take.
266
+ #
267
+ # class Person < ActiveRecord::Base
268
+ # has_many :pets
269
+ # end
270
+ #
271
+ # person.pets
272
+ # # => [
273
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
274
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
275
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
276
+ # # ]
277
+ #
278
+ # person.pets.take # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
279
+ #
280
+ # person.pets.take(2)
281
+ # # => [
282
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
283
+ # # #<Pet id: 2, name: "Spook", person_id: 1>
284
+ # # ]
285
+ #
286
+ # another_person_without.pets # => []
287
+ # another_person_without.pets.take # => nil
288
+ # another_person_without.pets.take(2) # => []
289
+ def take(limit = nil)
290
+ load_target if find_from_target?
291
+ super
292
+ end
293
+
294
+ # Returns a new object of the collection type that has been instantiated
295
+ # with +attributes+ and linked to this object, but have not yet been saved.
296
+ # You can pass an array of attributes hashes, this will return an array
297
+ # with the new objects.
298
+ #
299
+ # class Person
300
+ # has_many :pets
301
+ # end
302
+ #
303
+ # person.pets.build
304
+ # # => #<Pet id: nil, name: nil, person_id: 1>
305
+ #
306
+ # person.pets.build(name: 'Fancy-Fancy')
307
+ # # => #<Pet id: nil, name: "Fancy-Fancy", person_id: 1>
308
+ #
309
+ # person.pets.build([{name: 'Spook'}, {name: 'Choo-Choo'}, {name: 'Brain'}])
310
+ # # => [
311
+ # # #<Pet id: nil, name: "Spook", person_id: 1>,
312
+ # # #<Pet id: nil, name: "Choo-Choo", person_id: 1>,
313
+ # # #<Pet id: nil, name: "Brain", person_id: 1>
314
+ # # ]
315
+ #
316
+ # person.pets.size # => 5 # size of the collection
317
+ # person.pets.count # => 0 # count from database
318
+ def build(attributes = {}, &block)
319
+ @association.build(attributes, &block)
320
+ end
321
+ alias_method :new, :build
322
+
323
+ # Returns a new object of the collection type that has been instantiated with
324
+ # attributes, linked to this object and that has already been saved (if it
325
+ # passes the validations).
326
+ #
327
+ # class Person
328
+ # has_many :pets
329
+ # end
330
+ #
331
+ # person.pets.create(name: 'Fancy-Fancy')
332
+ # # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
333
+ #
334
+ # person.pets.create([{name: 'Spook'}, {name: 'Choo-Choo'}])
335
+ # # => [
336
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
337
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
338
+ # # ]
339
+ #
340
+ # person.pets.size # => 3
341
+ # person.pets.count # => 3
342
+ #
343
+ # person.pets.find(1, 2, 3)
344
+ # # => [
345
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
346
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
347
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
348
+ # # ]
349
+ def create(attributes = {}, &block)
350
+ @association.create(attributes, &block)
351
+ end
352
+
353
+ # Like #create, except that if the record is invalid, raises an exception.
354
+ #
355
+ # class Person
356
+ # has_many :pets
357
+ # end
358
+ #
359
+ # class Pet
360
+ # validates :name, presence: true
361
+ # end
362
+ #
363
+ # person.pets.create!(name: nil)
364
+ # # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
365
+ def create!(attributes = {}, &block)
366
+ @association.create!(attributes, &block)
367
+ end
368
+
369
+ # Replaces this collection with +other_array+. This will perform a diff
370
+ # and delete/add only records that have changed.
371
+ #
372
+ # class Person < ActiveRecord::Base
373
+ # has_many :pets
374
+ # end
375
+ #
376
+ # person.pets
377
+ # # => [#<Pet id: 1, name: "Gorby", group: "cats", person_id: 1>]
378
+ #
379
+ # other_pets = [Pet.new(name: 'Puff', group: 'celebrities')]
380
+ #
381
+ # person.pets.replace(other_pets)
382
+ #
383
+ # person.pets
384
+ # # => [#<Pet id: 2, name: "Puff", group: "celebrities", person_id: 1>]
385
+ #
386
+ # If the supplied array has an incorrect association type, it raises
387
+ # an ActiveRecord::AssociationTypeMismatch error:
388
+ #
389
+ # person.pets.replace(["doo", "ggie", "gaga"])
390
+ # # => ActiveRecord::AssociationTypeMismatch: Pet expected, got String
391
+ def replace(other_array)
392
+ @association.replace(other_array)
393
+ end
394
+
395
+ # Deletes all the records from the collection according to the strategy
396
+ # specified by the +:dependent+ option. If no +:dependent+ option is given,
397
+ # then it will follow the default strategy.
398
+ #
399
+ # For <tt>has_many :through</tt> associations, the default deletion strategy is
400
+ # +:delete_all+.
401
+ #
402
+ # For +has_many+ associations, the default deletion strategy is +:nullify+.
403
+ # This sets the foreign keys to +NULL+.
404
+ #
405
+ # class Person < ActiveRecord::Base
406
+ # has_many :pets # dependent: :nullify option by default
407
+ # end
408
+ #
409
+ # person.pets.size # => 3
410
+ # person.pets
411
+ # # => [
412
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
413
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
414
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
415
+ # # ]
416
+ #
417
+ # person.pets.delete_all
418
+ # # => [
419
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
420
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
421
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
422
+ # # ]
423
+ #
424
+ # person.pets.size # => 0
425
+ # person.pets # => []
426
+ #
427
+ # Pet.find(1, 2, 3)
428
+ # # => [
429
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: nil>,
430
+ # # #<Pet id: 2, name: "Spook", person_id: nil>,
431
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: nil>
432
+ # # ]
433
+ #
434
+ # Both +has_many+ and <tt>has_many :through</tt> dependencies default to the
435
+ # +:delete_all+ strategy if the +:dependent+ option is set to +:destroy+.
436
+ # Records are not instantiated and callbacks will not be fired.
437
+ #
438
+ # class Person < ActiveRecord::Base
439
+ # has_many :pets, dependent: :destroy
440
+ # end
441
+ #
442
+ # person.pets.size # => 3
443
+ # person.pets
444
+ # # => [
445
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
446
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
447
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
448
+ # # ]
449
+ #
450
+ # person.pets.delete_all
451
+ #
452
+ # Pet.find(1, 2, 3)
453
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
454
+ #
455
+ # If it is set to <tt>:delete_all</tt>, all the objects are deleted
456
+ # *without* calling their +destroy+ method.
457
+ #
458
+ # class Person < ActiveRecord::Base
459
+ # has_many :pets, dependent: :delete_all
460
+ # end
461
+ #
462
+ # person.pets.size # => 3
463
+ # person.pets
464
+ # # => [
465
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
466
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
467
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
468
+ # # ]
469
+ #
470
+ # person.pets.delete_all
471
+ #
472
+ # Pet.find(1, 2, 3)
473
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
474
+ def delete_all(dependent = nil)
475
+ @association.delete_all(dependent).tap { reset_scope }
476
+ end
477
+
478
+ # Deletes the records of the collection directly from the database
479
+ # ignoring the +:dependent+ option. Records are instantiated and it
480
+ # invokes +before_remove+, +after_remove+, +before_destroy+, and
481
+ # +after_destroy+ callbacks.
482
+ #
483
+ # class Person < ActiveRecord::Base
484
+ # has_many :pets
485
+ # end
486
+ #
487
+ # person.pets.size # => 3
488
+ # person.pets
489
+ # # => [
490
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
491
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
492
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
493
+ # # ]
494
+ #
495
+ # person.pets.destroy_all
496
+ #
497
+ # person.pets.size # => 0
498
+ # person.pets # => []
499
+ #
500
+ # Pet.find(1) # => Couldn't find Pet with id=1
501
+ def destroy_all
502
+ @association.destroy_all.tap { reset_scope }
503
+ end
504
+
505
+ # Deletes the +records+ supplied from the collection according to the strategy
506
+ # specified by the +:dependent+ option. If no +:dependent+ option is given,
507
+ # then it will follow the default strategy. Returns an array with the
508
+ # deleted records.
509
+ #
510
+ # For <tt>has_many :through</tt> associations, the default deletion strategy is
511
+ # +:delete_all+.
512
+ #
513
+ # For +has_many+ associations, the default deletion strategy is +:nullify+.
514
+ # This sets the foreign keys to +NULL+.
515
+ #
516
+ # class Person < ActiveRecord::Base
517
+ # has_many :pets # dependent: :nullify option by default
518
+ # end
519
+ #
520
+ # person.pets.size # => 3
521
+ # person.pets
522
+ # # => [
523
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
524
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
525
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
526
+ # # ]
527
+ #
528
+ # person.pets.delete(Pet.find(1))
529
+ # # => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]
530
+ #
531
+ # person.pets.size # => 2
532
+ # person.pets
533
+ # # => [
534
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
535
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
536
+ # # ]
537
+ #
538
+ # Pet.find(1)
539
+ # # => #<Pet id: 1, name: "Fancy-Fancy", person_id: nil>
540
+ #
541
+ # If it is set to <tt>:destroy</tt> all the +records+ are removed by calling
542
+ # their +destroy+ method. See +destroy+ for more information.
543
+ #
544
+ # class Person < ActiveRecord::Base
545
+ # has_many :pets, dependent: :destroy
546
+ # end
547
+ #
548
+ # person.pets.size # => 3
549
+ # person.pets
550
+ # # => [
551
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
552
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
553
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
554
+ # # ]
555
+ #
556
+ # person.pets.delete(Pet.find(1), Pet.find(3))
557
+ # # => [
558
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
559
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
560
+ # # ]
561
+ #
562
+ # person.pets.size # => 1
563
+ # person.pets
564
+ # # => [#<Pet id: 2, name: "Spook", person_id: 1>]
565
+ #
566
+ # Pet.find(1, 3)
567
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 3)
568
+ #
569
+ # If it is set to <tt>:delete_all</tt>, all the +records+ are deleted
570
+ # *without* calling their +destroy+ method.
571
+ #
572
+ # class Person < ActiveRecord::Base
573
+ # has_many :pets, dependent: :delete_all
574
+ # end
575
+ #
576
+ # person.pets.size # => 3
577
+ # person.pets
578
+ # # => [
579
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
580
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
581
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
582
+ # # ]
583
+ #
584
+ # person.pets.delete(Pet.find(1))
585
+ # # => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]
586
+ #
587
+ # person.pets.size # => 2
588
+ # person.pets
589
+ # # => [
590
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
591
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
592
+ # # ]
593
+ #
594
+ # Pet.find(1)
595
+ # # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=1
596
+ #
597
+ # You can pass +Integer+ or +String+ values, it finds the records
598
+ # responding to the +id+ and executes delete on them.
599
+ #
600
+ # class Person < ActiveRecord::Base
601
+ # has_many :pets
602
+ # end
603
+ #
604
+ # person.pets.size # => 3
605
+ # person.pets
606
+ # # => [
607
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
608
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
609
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
610
+ # # ]
611
+ #
612
+ # person.pets.delete("1")
613
+ # # => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]
614
+ #
615
+ # person.pets.delete(2, 3)
616
+ # # => [
617
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
618
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
619
+ # # ]
620
+ def delete(*records)
621
+ @association.delete(*records).tap { reset_scope }
622
+ end
623
+
624
+ # Destroys the +records+ supplied and removes them from the collection.
625
+ # This method will _always_ remove record from the database ignoring
626
+ # the +:dependent+ option. Returns an array with the removed records.
627
+ #
628
+ # class Person < ActiveRecord::Base
629
+ # has_many :pets
630
+ # end
631
+ #
632
+ # person.pets.size # => 3
633
+ # person.pets
634
+ # # => [
635
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
636
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
637
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
638
+ # # ]
639
+ #
640
+ # person.pets.destroy(Pet.find(1))
641
+ # # => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]
642
+ #
643
+ # person.pets.size # => 2
644
+ # person.pets
645
+ # # => [
646
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
647
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
648
+ # # ]
649
+ #
650
+ # person.pets.destroy(Pet.find(2), Pet.find(3))
651
+ # # => [
652
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
653
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
654
+ # # ]
655
+ #
656
+ # person.pets.size # => 0
657
+ # person.pets # => []
658
+ #
659
+ # Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
660
+ #
661
+ # You can pass +Integer+ or +String+ values, it finds the records
662
+ # responding to the +id+ and then deletes them from the database.
663
+ #
664
+ # person.pets.size # => 3
665
+ # person.pets
666
+ # # => [
667
+ # # #<Pet id: 4, name: "Benny", person_id: 1>,
668
+ # # #<Pet id: 5, name: "Brain", person_id: 1>,
669
+ # # #<Pet id: 6, name: "Boss", person_id: 1>
670
+ # # ]
671
+ #
672
+ # person.pets.destroy("4")
673
+ # # => #<Pet id: 4, name: "Benny", person_id: 1>
674
+ #
675
+ # person.pets.size # => 2
676
+ # person.pets
677
+ # # => [
678
+ # # #<Pet id: 5, name: "Brain", person_id: 1>,
679
+ # # #<Pet id: 6, name: "Boss", person_id: 1>
680
+ # # ]
681
+ #
682
+ # person.pets.destroy(5, 6)
683
+ # # => [
684
+ # # #<Pet id: 5, name: "Brain", person_id: 1>,
685
+ # # #<Pet id: 6, name: "Boss", person_id: 1>
686
+ # # ]
687
+ #
688
+ # person.pets.size # => 0
689
+ # person.pets # => []
690
+ #
691
+ # Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6)
692
+ def destroy(*records)
693
+ @association.destroy(*records).tap { reset_scope }
694
+ end
695
+
696
+ ##
697
+ # :method: distinct
698
+ #
699
+ # :call-seq:
700
+ # distinct(value = true)
701
+ #
702
+ # Specifies whether the records should be unique or not.
703
+ #
704
+ # class Person < ActiveRecord::Base
705
+ # has_many :pets
706
+ # end
707
+ #
708
+ # person.pets.select(:name)
709
+ # # => [
710
+ # # #<Pet name: "Fancy-Fancy">,
711
+ # # #<Pet name: "Fancy-Fancy">
712
+ # # ]
713
+ #
714
+ # person.pets.select(:name).distinct
715
+ # # => [#<Pet name: "Fancy-Fancy">]
716
+ #
717
+ # person.pets.select(:name).distinct.distinct(false)
718
+ # # => [
719
+ # # #<Pet name: "Fancy-Fancy">,
720
+ # # #<Pet name: "Fancy-Fancy">
721
+ # # ]
722
+
723
+ #--
724
+ def calculate(operation, column_name)
725
+ null_scope? ? scope.calculate(operation, column_name) : super
726
+ end
727
+
728
+ def pluck(*column_names)
729
+ null_scope? ? scope.pluck(*column_names) : super
730
+ end
731
+
732
+ ##
733
+ # :method: count
734
+ #
735
+ # :call-seq:
736
+ # count(column_name = nil, &block)
737
+ #
738
+ # Count all records.
739
+ #
740
+ # class Person < ActiveRecord::Base
741
+ # has_many :pets
742
+ # end
743
+ #
744
+ # # This will perform the count using SQL.
745
+ # person.pets.count # => 3
746
+ # person.pets
747
+ # # => [
748
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
749
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
750
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
751
+ # # ]
752
+ #
753
+ # Passing a block will select all of a person's pets in SQL and then
754
+ # perform the count using Ruby.
755
+ #
756
+ # person.pets.count { |pet| pet.name.include?('-') } # => 2
757
+
758
+ # Returns the size of the collection. If the collection hasn't been loaded,
759
+ # it executes a <tt>SELECT COUNT(*)</tt> query. Else it calls <tt>collection.size</tt>.
760
+ #
761
+ # If the collection has been already loaded +size+ and +length+ are
762
+ # equivalent. If not and you are going to need the records anyway
763
+ # +length+ will take one less query. Otherwise +size+ is more efficient.
764
+ #
765
+ # class Person < ActiveRecord::Base
766
+ # has_many :pets
767
+ # end
768
+ #
769
+ # person.pets.size # => 3
770
+ # # executes something like SELECT COUNT(*) FROM "pets" WHERE "pets"."person_id" = 1
771
+ #
772
+ # person.pets # This will execute a SELECT * FROM query
773
+ # # => [
774
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
775
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
776
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
777
+ # # ]
778
+ #
779
+ # person.pets.size # => 3
780
+ # # Because the collection is already loaded, this will behave like
781
+ # # collection.size and no SQL count query is executed.
782
+ def size
783
+ @association.size
784
+ end
785
+
786
+ ##
787
+ # :method: length
788
+ #
789
+ # :call-seq:
790
+ # length()
791
+ #
792
+ # Returns the size of the collection calling +size+ on the target.
793
+ # If the collection has been already loaded, +length+ and +size+ are
794
+ # equivalent. If not and you are going to need the records anyway this
795
+ # method will take one less query. Otherwise +size+ is more efficient.
796
+ #
797
+ # class Person < ActiveRecord::Base
798
+ # has_many :pets
799
+ # end
800
+ #
801
+ # person.pets.length # => 3
802
+ # # executes something like SELECT "pets".* FROM "pets" WHERE "pets"."person_id" = 1
803
+ #
804
+ # # Because the collection is loaded, you can
805
+ # # call the collection with no additional queries:
806
+ # person.pets
807
+ # # => [
808
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
809
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
810
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
811
+ # # ]
812
+
813
+ # Returns +true+ if the collection is empty. If the collection has been
814
+ # loaded it is equivalent
815
+ # to <tt>collection.size.zero?</tt>. If the collection has not been loaded,
816
+ # it is equivalent to <tt>!collection.exists?</tt>. If the collection has
817
+ # not already been loaded and you are going to fetch the records anyway it
818
+ # is better to check <tt>collection.load.empty?</tt>.
819
+ #
820
+ # class Person < ActiveRecord::Base
821
+ # has_many :pets
822
+ # end
823
+ #
824
+ # person.pets.count # => 1
825
+ # person.pets.empty? # => false
826
+ #
827
+ # person.pets.delete_all
828
+ #
829
+ # person.pets.count # => 0
830
+ # person.pets.empty? # => true
831
+ def empty?
832
+ @association.empty?
833
+ end
834
+
835
+ ##
836
+ # :method: any?
837
+ #
838
+ # :call-seq:
839
+ # any?()
840
+ #
841
+ # Returns +true+ if the collection is not empty.
842
+ #
843
+ # class Person < ActiveRecord::Base
844
+ # has_many :pets
845
+ # end
846
+ #
847
+ # person.pets.count # => 0
848
+ # person.pets.any? # => false
849
+ #
850
+ # person.pets << Pet.new(name: 'Snoop')
851
+ # person.pets.count # => 1
852
+ # person.pets.any? # => true
853
+ #
854
+ # Calling it without a block when the collection is not yet
855
+ # loaded is equivalent to <tt>collection.exists?</tt>.
856
+ # If you're going to load the collection anyway, it is better
857
+ # to call <tt>collection.load.any?</tt> to avoid an extra query.
858
+ #
859
+ # You can also pass a +block+ to define criteria. The behavior
860
+ # is the same, it returns true if the collection based on the
861
+ # criteria is not empty.
862
+ #
863
+ # person.pets
864
+ # # => [#<Pet name: "Snoop", group: "dogs">]
865
+ #
866
+ # person.pets.any? do |pet|
867
+ # pet.group == 'cats'
868
+ # end
869
+ # # => false
870
+ #
871
+ # person.pets.any? do |pet|
872
+ # pet.group == 'dogs'
873
+ # end
874
+ # # => true
875
+
876
+ ##
877
+ # :method: many?
878
+ #
879
+ # :call-seq:
880
+ # many?()
881
+ #
882
+ # Returns true if the collection has more than one record.
883
+ # Equivalent to <tt>collection.size > 1</tt>.
884
+ #
885
+ # class Person < ActiveRecord::Base
886
+ # has_many :pets
887
+ # end
888
+ #
889
+ # person.pets.count # => 1
890
+ # person.pets.many? # => false
891
+ #
892
+ # person.pets << Pet.new(name: 'Snoopy')
893
+ # person.pets.count # => 2
894
+ # person.pets.many? # => true
895
+ #
896
+ # You can also pass a +block+ to define criteria. The
897
+ # behavior is the same, it returns true if the collection
898
+ # based on the criteria has more than one record.
899
+ #
900
+ # person.pets
901
+ # # => [
902
+ # # #<Pet name: "Gorby", group: "cats">,
903
+ # # #<Pet name: "Puff", group: "cats">,
904
+ # # #<Pet name: "Snoop", group: "dogs">
905
+ # # ]
906
+ #
907
+ # person.pets.many? do |pet|
908
+ # pet.group == 'dogs'
909
+ # end
910
+ # # => false
911
+ #
912
+ # person.pets.many? do |pet|
913
+ # pet.group == 'cats'
914
+ # end
915
+ # # => true
916
+
917
+ # Returns +true+ if the given +record+ is present in the collection.
918
+ #
919
+ # class Person < ActiveRecord::Base
920
+ # has_many :pets
921
+ # end
922
+ #
923
+ # person.pets # => [#<Pet id: 20, name: "Snoop">]
924
+ #
925
+ # person.pets.include?(Pet.find(20)) # => true
926
+ # person.pets.include?(Pet.find(21)) # => false
927
+ def include?(record)
928
+ !!@association.include?(record)
929
+ end
930
+
931
+ # Returns the association object for the collection.
932
+ #
933
+ # class Person < ActiveRecord::Base
934
+ # has_many :pets
935
+ # end
936
+ #
937
+ # person.pets.proxy_association
938
+ # # => #<ActiveRecord::Associations::HasManyAssociation owner="#<Person:0x00>">
939
+ #
940
+ # Returns the same object as <tt>person.association(:pets)</tt>,
941
+ # allowing you to make calls like <tt>person.pets.proxy_association.owner</tt>.
942
+ #
943
+ # See Associations::ClassMethods@Association+extensions for more.
944
+ def proxy_association
945
+ @association
946
+ end
947
+
948
+ # Returns a Relation object for the records in this association
949
+ def scope
950
+ @scope ||= @association.scope
951
+ end
952
+
953
+ # Equivalent to <tt>Array#==</tt>. Returns +true+ if the two arrays
954
+ # contain the same number of elements and if each element is equal
955
+ # to the corresponding element in the +other+ array, otherwise returns
956
+ # +false+.
957
+ #
958
+ # class Person < ActiveRecord::Base
959
+ # has_many :pets
960
+ # end
961
+ #
962
+ # person.pets
963
+ # # => [
964
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
965
+ # # #<Pet id: 2, name: "Spook", person_id: 1>
966
+ # # ]
967
+ #
968
+ # other = person.pets.to_ary
969
+ #
970
+ # person.pets == other
971
+ # # => true
972
+ #
973
+ #
974
+ # Note that unpersisted records can still be seen as equal:
975
+ #
976
+ # other = [Pet.new(id: 1), Pet.new(id: 2)]
977
+ #
978
+ # person.pets == other
979
+ # # => true
980
+ def ==(other)
981
+ load_target == other
982
+ end
983
+
984
+ ##
985
+ # :method: to_ary
986
+ #
987
+ # :call-seq:
988
+ # to_ary()
989
+ #
990
+ # Returns a new array of objects from the collection. If the collection
991
+ # hasn't been loaded, it fetches the records from the database.
992
+ #
993
+ # class Person < ActiveRecord::Base
994
+ # has_many :pets
995
+ # end
996
+ #
997
+ # person.pets
998
+ # # => [
999
+ # # #<Pet id: 4, name: "Benny", person_id: 1>,
1000
+ # # #<Pet id: 5, name: "Brain", person_id: 1>,
1001
+ # # #<Pet id: 6, name: "Boss", person_id: 1>
1002
+ # # ]
1003
+ #
1004
+ # other_pets = person.pets.to_ary
1005
+ # # => [
1006
+ # # #<Pet id: 4, name: "Benny", person_id: 1>,
1007
+ # # #<Pet id: 5, name: "Brain", person_id: 1>,
1008
+ # # #<Pet id: 6, name: "Boss", person_id: 1>
1009
+ # # ]
1010
+ #
1011
+ # other_pets.replace([Pet.new(name: 'BooGoo')])
1012
+ #
1013
+ # other_pets
1014
+ # # => [#<Pet id: nil, name: "BooGoo", person_id: 1>]
1015
+ #
1016
+ # person.pets
1017
+ # # This is not affected by replace
1018
+ # # => [
1019
+ # # #<Pet id: 4, name: "Benny", person_id: 1>,
1020
+ # # #<Pet id: 5, name: "Brain", person_id: 1>,
1021
+ # # #<Pet id: 6, name: "Boss", person_id: 1>
1022
+ # # ]
1023
+
1024
+ def records # :nodoc:
1025
+ load_target
1026
+ end
1027
+
1028
+ # Adds one or more +records+ to the collection by setting their foreign keys
1029
+ # to the association's primary key. Since <tt><<</tt> flattens its argument list and
1030
+ # inserts each record, +push+ and +concat+ behave identically. Returns +self+
1031
+ # so several appends may be chained together.
1032
+ #
1033
+ # class Person < ActiveRecord::Base
1034
+ # has_many :pets
1035
+ # end
1036
+ #
1037
+ # person.pets.size # => 0
1038
+ # person.pets << Pet.new(name: 'Fancy-Fancy')
1039
+ # person.pets << [Pet.new(name: 'Spook'), Pet.new(name: 'Choo-Choo')]
1040
+ # person.pets.size # => 3
1041
+ #
1042
+ # person.id # => 1
1043
+ # person.pets
1044
+ # # => [
1045
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
1046
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
1047
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
1048
+ # # ]
1049
+ def <<(*records)
1050
+ proxy_association.concat(records) && self
1051
+ end
1052
+ alias_method :push, :<<
1053
+ alias_method :append, :<<
1054
+ alias_method :concat, :<<
1055
+
1056
+ def prepend(*args) # :nodoc:
1057
+ raise NoMethodError, "prepend on association is not defined. Please use <<, push or append"
1058
+ end
1059
+
1060
+ # Equivalent to +delete_all+. The difference is that returns +self+, instead
1061
+ # of an array with the deleted objects, so methods can be chained. See
1062
+ # +delete_all+ for more information.
1063
+ # Note that because +delete_all+ removes records by directly
1064
+ # running an SQL query into the database, the +updated_at+ column of
1065
+ # the object is not changed.
1066
+ def clear
1067
+ delete_all
1068
+ self
1069
+ end
1070
+
1071
+ # Reloads the collection from the database. Returns +self+.
1072
+ #
1073
+ # class Person < ActiveRecord::Base
1074
+ # has_many :pets
1075
+ # end
1076
+ #
1077
+ # person.pets # fetches pets from the database
1078
+ # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1079
+ #
1080
+ # person.pets # uses the pets cache
1081
+ # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1082
+ #
1083
+ # person.pets.reload # fetches pets from the database
1084
+ # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1085
+ def reload
1086
+ proxy_association.reload(true)
1087
+ reset_scope
1088
+ end
1089
+
1090
+ # Unloads the association. Returns +self+.
1091
+ #
1092
+ # class Person < ActiveRecord::Base
1093
+ # has_many :pets
1094
+ # end
1095
+ #
1096
+ # person.pets # fetches pets from the database
1097
+ # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1098
+ #
1099
+ # person.pets # uses the pets cache
1100
+ # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1101
+ #
1102
+ # person.pets.reset # clears the pets cache
1103
+ #
1104
+ # person.pets # fetches pets from the database
1105
+ # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1106
+ def reset
1107
+ proxy_association.reset
1108
+ proxy_association.reset_scope
1109
+ reset_scope
1110
+ end
1111
+
1112
+ def reset_scope # :nodoc:
1113
+ @offsets = @take = nil
1114
+ @scope = nil
1115
+ self
1116
+ end
1117
+
1118
+ def inspect # :nodoc:
1119
+ load_target if find_from_target?
1120
+ super
1121
+ end
1122
+
1123
+ def pretty_print(pp) # :nodoc:
1124
+ load_target if find_from_target?
1125
+ super
1126
+ end
1127
+
1128
+ delegate_methods = [
1129
+ QueryMethods,
1130
+ SpawnMethods,
1131
+ ].flat_map { |klass|
1132
+ klass.public_instance_methods(false)
1133
+ } - self.public_instance_methods(false) - [:select] + [
1134
+ :scoping, :values, :insert, :insert_all, :insert!, :insert_all!, :upsert, :upsert_all, :load_async
1135
+ ]
1136
+
1137
+ delegate(*delegate_methods, to: :scope)
1138
+
1139
+ private
1140
+ def find_nth_with_limit(index, limit)
1141
+ load_target if find_from_target?
1142
+ super
1143
+ end
1144
+
1145
+ def find_nth_from_last(index)
1146
+ load_target if find_from_target?
1147
+ super
1148
+ end
1149
+
1150
+ def null_scope?
1151
+ @association.null_scope?
1152
+ end
1153
+
1154
+ def find_from_target?
1155
+ @association.find_from_target?
1156
+ end
1157
+
1158
+ def exec_queries
1159
+ load_target
1160
+ end
1161
+ end
1162
+ end
1163
+ end