activerecord 5.0.7.2 → 6.0.6.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (359) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +844 -1944
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +9 -7
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record/advisory_lock_base.rb +18 -0
  8. data/lib/active_record/aggregations.rb +249 -247
  9. data/lib/active_record/association_relation.rb +18 -14
  10. data/lib/active_record/associations/alias_tracker.rb +24 -34
  11. data/lib/active_record/associations/association.rb +113 -55
  12. data/lib/active_record/associations/association_scope.rb +102 -96
  13. data/lib/active_record/associations/belongs_to_association.rb +58 -42
  14. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  15. data/lib/active_record/associations/builder/association.rb +18 -25
  16. data/lib/active_record/associations/builder/belongs_to.rb +43 -54
  17. data/lib/active_record/associations/builder/collection_association.rb +7 -18
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +41 -62
  19. data/lib/active_record/associations/builder/has_many.rb +4 -0
  20. data/lib/active_record/associations/builder/has_one.rb +37 -1
  21. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  22. data/lib/active_record/associations/collection_association.rb +93 -254
  23. data/lib/active_record/associations/collection_proxy.rb +159 -122
  24. data/lib/active_record/associations/foreign_association.rb +9 -0
  25. data/lib/active_record/associations/has_many_association.rb +23 -30
  26. data/lib/active_record/associations/has_many_through_association.rb +58 -44
  27. data/lib/active_record/associations/has_one_association.rb +59 -54
  28. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  29. data/lib/active_record/associations/join_dependency/join_association.rb +43 -85
  30. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  31. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  32. data/lib/active_record/associations/join_dependency.rb +152 -177
  33. data/lib/active_record/associations/preloader/association.rb +101 -97
  34. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  35. data/lib/active_record/associations/preloader.rb +94 -103
  36. data/lib/active_record/associations/singular_association.rb +12 -45
  37. data/lib/active_record/associations/through_association.rb +27 -15
  38. data/lib/active_record/associations.rb +1603 -1592
  39. data/lib/active_record/attribute_assignment.rb +54 -61
  40. data/lib/active_record/attribute_decorators.rb +38 -17
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
  42. data/lib/active_record/attribute_methods/dirty.rb +179 -109
  43. data/lib/active_record/attribute_methods/primary_key.rb +85 -92
  44. data/lib/active_record/attribute_methods/query.rb +4 -3
  45. data/lib/active_record/attribute_methods/read.rb +20 -49
  46. data/lib/active_record/attribute_methods/serialization.rb +29 -7
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
  48. data/lib/active_record/attribute_methods/write.rb +34 -33
  49. data/lib/active_record/attribute_methods.rb +66 -106
  50. data/lib/active_record/attributes.rb +38 -25
  51. data/lib/active_record/autosave_association.rb +58 -39
  52. data/lib/active_record/base.rb +27 -24
  53. data/lib/active_record/callbacks.rb +64 -35
  54. data/lib/active_record/coders/json.rb +2 -0
  55. data/lib/active_record/coders/yaml_column.rb +34 -13
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +558 -323
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +128 -75
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +233 -147
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +373 -202
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -562
  69. data/lib/active_record/connection_adapters/column.rb +41 -13
  70. data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
  72. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +137 -49
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -54
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +12 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  99. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +8 -4
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +20 -26
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -275
  117. data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +261 -267
  127. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  128. data/lib/active_record/connection_handling.rb +143 -40
  129. data/lib/active_record/core.rb +207 -160
  130. data/lib/active_record/counter_cache.rb +60 -28
  131. data/lib/active_record/database_configurations/database_config.rb +37 -0
  132. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  133. data/lib/active_record/database_configurations/url_config.rb +78 -0
  134. data/lib/active_record/database_configurations.rb +233 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +87 -87
  137. data/lib/active_record/enum.rb +67 -23
  138. data/lib/active_record/errors.rb +114 -18
  139. data/lib/active_record/explain.rb +4 -4
  140. data/lib/active_record/explain_registry.rb +3 -1
  141. data/lib/active_record/explain_subscriber.rb +9 -4
  142. data/lib/active_record/fixture_set/file.rb +13 -8
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +152 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  147. data/lib/active_record/fixtures.rb +194 -504
  148. data/lib/active_record/gem_version.rb +5 -3
  149. data/lib/active_record/inheritance.rb +150 -99
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +116 -25
  152. data/lib/active_record/internal_metadata.rb +16 -19
  153. data/lib/active_record/legacy_yaml_adapter.rb +4 -2
  154. data/lib/active_record/locking/optimistic.rb +85 -86
  155. data/lib/active_record/locking/pessimistic.rb +18 -6
  156. data/lib/active_record/log_subscriber.rb +48 -29
  157. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  158. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  159. data/lib/active_record/middleware/database_selector.rb +74 -0
  160. data/lib/active_record/migration/command_recorder.rb +134 -100
  161. data/lib/active_record/migration/compatibility.rb +174 -56
  162. data/lib/active_record/migration/join_table.rb +8 -7
  163. data/lib/active_record/migration.rb +369 -302
  164. data/lib/active_record/model_schema.rb +160 -127
  165. data/lib/active_record/nested_attributes.rb +213 -202
  166. data/lib/active_record/no_touching.rb +12 -3
  167. data/lib/active_record/null_relation.rb +12 -34
  168. data/lib/active_record/persistence.rb +446 -77
  169. data/lib/active_record/query_cache.rb +13 -12
  170. data/lib/active_record/querying.rb +37 -24
  171. data/lib/active_record/railtie.rb +128 -36
  172. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  173. data/lib/active_record/railties/console_sandbox.rb +2 -0
  174. data/lib/active_record/railties/controller_runtime.rb +34 -33
  175. data/lib/active_record/railties/databases.rake +312 -177
  176. data/lib/active_record/readonly_attributes.rb +5 -4
  177. data/lib/active_record/reflection.rb +214 -254
  178. data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
  179. data/lib/active_record/relation/batches.rb +98 -52
  180. data/lib/active_record/relation/calculations.rb +212 -173
  181. data/lib/active_record/relation/delegation.rb +73 -69
  182. data/lib/active_record/relation/finder_methods.rb +207 -247
  183. data/lib/active_record/relation/from_clause.rb +6 -8
  184. data/lib/active_record/relation/merger.rb +82 -61
  185. data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
  186. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  187. data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
  188. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  189. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  190. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  191. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  192. data/lib/active_record/relation/predicate_builder.rb +83 -105
  193. data/lib/active_record/relation/query_attribute.rb +33 -2
  194. data/lib/active_record/relation/query_methods.rb +488 -332
  195. data/lib/active_record/relation/record_fetch_warning.rb +5 -3
  196. data/lib/active_record/relation/spawn_methods.rb +8 -8
  197. data/lib/active_record/relation/where_clause.rb +111 -96
  198. data/lib/active_record/relation/where_clause_factory.rb +6 -11
  199. data/lib/active_record/relation.rb +443 -318
  200. data/lib/active_record/result.rb +69 -40
  201. data/lib/active_record/runtime_registry.rb +5 -3
  202. data/lib/active_record/sanitization.rb +83 -99
  203. data/lib/active_record/schema.rb +7 -14
  204. data/lib/active_record/schema_dumper.rb +71 -69
  205. data/lib/active_record/schema_migration.rb +16 -6
  206. data/lib/active_record/scoping/default.rb +92 -95
  207. data/lib/active_record/scoping/named.rb +51 -26
  208. data/lib/active_record/scoping.rb +20 -20
  209. data/lib/active_record/secure_token.rb +4 -2
  210. data/lib/active_record/serialization.rb +2 -0
  211. data/lib/active_record/statement_cache.rb +63 -28
  212. data/lib/active_record/store.rb +121 -41
  213. data/lib/active_record/suppressor.rb +6 -3
  214. data/lib/active_record/table_metadata.rb +39 -18
  215. data/lib/active_record/tasks/database_tasks.rb +271 -81
  216. data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
  217. data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
  218. data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
  219. data/lib/active_record/test_databases.rb +23 -0
  220. data/lib/active_record/test_fixtures.rb +243 -0
  221. data/lib/active_record/timestamp.rb +70 -36
  222. data/lib/active_record/touch_later.rb +8 -6
  223. data/lib/active_record/transactions.rb +141 -157
  224. data/lib/active_record/translation.rb +3 -1
  225. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  226. data/lib/active_record/type/date.rb +2 -0
  227. data/lib/active_record/type/date_time.rb +2 -0
  228. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  229. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  230. data/lib/active_record/type/internal/timezone.rb +2 -0
  231. data/lib/active_record/type/json.rb +30 -0
  232. data/lib/active_record/type/serialized.rb +16 -9
  233. data/lib/active_record/type/text.rb +11 -0
  234. data/lib/active_record/type/time.rb +12 -1
  235. data/lib/active_record/type/type_map.rb +14 -17
  236. data/lib/active_record/type/unsigned_integer.rb +16 -0
  237. data/lib/active_record/type.rb +23 -18
  238. data/lib/active_record/type_caster/connection.rb +17 -12
  239. data/lib/active_record/type_caster/map.rb +5 -4
  240. data/lib/active_record/type_caster.rb +4 -2
  241. data/lib/active_record/validations/absence.rb +2 -0
  242. data/lib/active_record/validations/associated.rb +3 -2
  243. data/lib/active_record/validations/length.rb +2 -0
  244. data/lib/active_record/validations/presence.rb +4 -2
  245. data/lib/active_record/validations/uniqueness.rb +29 -42
  246. data/lib/active_record/validations.rb +7 -5
  247. data/lib/active_record/version.rb +3 -1
  248. data/lib/active_record.rb +37 -22
  249. data/lib/arel/alias_predication.rb +9 -0
  250. data/lib/arel/attributes/attribute.rb +37 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/collectors/bind.rb +24 -0
  253. data/lib/arel/collectors/composite.rb +31 -0
  254. data/lib/arel/collectors/plain_string.rb +20 -0
  255. data/lib/arel/collectors/sql_string.rb +20 -0
  256. data/lib/arel/collectors/substitute_binds.rb +28 -0
  257. data/lib/arel/crud.rb +42 -0
  258. data/lib/arel/delete_manager.rb +18 -0
  259. data/lib/arel/errors.rb +9 -0
  260. data/lib/arel/expressions.rb +29 -0
  261. data/lib/arel/factory_methods.rb +49 -0
  262. data/lib/arel/insert_manager.rb +49 -0
  263. data/lib/arel/math.rb +45 -0
  264. data/lib/arel/nodes/and.rb +32 -0
  265. data/lib/arel/nodes/ascending.rb +23 -0
  266. data/lib/arel/nodes/binary.rb +52 -0
  267. data/lib/arel/nodes/bind_param.rb +36 -0
  268. data/lib/arel/nodes/case.rb +55 -0
  269. data/lib/arel/nodes/casted.rb +50 -0
  270. data/lib/arel/nodes/comment.rb +29 -0
  271. data/lib/arel/nodes/count.rb +12 -0
  272. data/lib/arel/nodes/delete_statement.rb +45 -0
  273. data/lib/arel/nodes/descending.rb +23 -0
  274. data/lib/arel/nodes/equality.rb +18 -0
  275. data/lib/arel/nodes/extract.rb +24 -0
  276. data/lib/arel/nodes/false.rb +16 -0
  277. data/lib/arel/nodes/full_outer_join.rb +8 -0
  278. data/lib/arel/nodes/function.rb +44 -0
  279. data/lib/arel/nodes/grouping.rb +8 -0
  280. data/lib/arel/nodes/in.rb +8 -0
  281. data/lib/arel/nodes/infix_operation.rb +80 -0
  282. data/lib/arel/nodes/inner_join.rb +8 -0
  283. data/lib/arel/nodes/insert_statement.rb +37 -0
  284. data/lib/arel/nodes/join_source.rb +20 -0
  285. data/lib/arel/nodes/matches.rb +18 -0
  286. data/lib/arel/nodes/named_function.rb +23 -0
  287. data/lib/arel/nodes/node.rb +50 -0
  288. data/lib/arel/nodes/node_expression.rb +13 -0
  289. data/lib/arel/nodes/outer_join.rb +8 -0
  290. data/lib/arel/nodes/over.rb +15 -0
  291. data/lib/arel/nodes/regexp.rb +16 -0
  292. data/lib/arel/nodes/right_outer_join.rb +8 -0
  293. data/lib/arel/nodes/select_core.rb +67 -0
  294. data/lib/arel/nodes/select_statement.rb +41 -0
  295. data/lib/arel/nodes/sql_literal.rb +16 -0
  296. data/lib/arel/nodes/string_join.rb +11 -0
  297. data/lib/arel/nodes/table_alias.rb +27 -0
  298. data/lib/arel/nodes/terminal.rb +16 -0
  299. data/lib/arel/nodes/true.rb +16 -0
  300. data/lib/arel/nodes/unary.rb +45 -0
  301. data/lib/arel/nodes/unary_operation.rb +20 -0
  302. data/lib/arel/nodes/unqualified_column.rb +22 -0
  303. data/lib/arel/nodes/update_statement.rb +41 -0
  304. data/lib/arel/nodes/values_list.rb +9 -0
  305. data/lib/arel/nodes/window.rb +126 -0
  306. data/lib/arel/nodes/with.rb +11 -0
  307. data/lib/arel/nodes.rb +68 -0
  308. data/lib/arel/order_predications.rb +13 -0
  309. data/lib/arel/predications.rb +256 -0
  310. data/lib/arel/select_manager.rb +271 -0
  311. data/lib/arel/table.rb +110 -0
  312. data/lib/arel/tree_manager.rb +72 -0
  313. data/lib/arel/update_manager.rb +34 -0
  314. data/lib/arel/visitors/depth_first.rb +203 -0
  315. data/lib/arel/visitors/dot.rb +296 -0
  316. data/lib/arel/visitors/ibm_db.rb +34 -0
  317. data/lib/arel/visitors/informix.rb +62 -0
  318. data/lib/arel/visitors/mssql.rb +156 -0
  319. data/lib/arel/visitors/mysql.rb +83 -0
  320. data/lib/arel/visitors/oracle.rb +158 -0
  321. data/lib/arel/visitors/oracle12.rb +65 -0
  322. data/lib/arel/visitors/postgresql.rb +109 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +888 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors/where_sql.rb +22 -0
  327. data/lib/arel/visitors.rb +20 -0
  328. data/lib/arel/window_predications.rb +9 -0
  329. data/lib/arel.rb +62 -0
  330. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
  332. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
  334. data/lib/rails/generators/active_record/migration.rb +17 -3
  335. data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
  336. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  337. data/lib/rails/generators/active_record.rb +7 -5
  338. metadata +138 -52
  339. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  340. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  341. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  342. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  343. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  344. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  345. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  346. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  347. data/lib/active_record/attribute.rb +0 -213
  348. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  349. data/lib/active_record/attribute_set/builder.rb +0 -132
  350. data/lib/active_record/attribute_set.rb +0 -110
  351. data/lib/active_record/collection_cache_key.rb +0 -50
  352. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  353. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  354. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  355. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  356. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  357. data/lib/active_record/type/internal/abstract_json.rb +0 -33
  358. /data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  359. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,51 +1,41 @@
1
- require 'active_support/core_ext/string/conversions'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/conversions"
2
4
 
3
5
  module ActiveRecord
4
6
  module Associations
5
7
  # Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
6
8
  class AliasTracker # :nodoc:
7
- attr_reader :aliases
8
-
9
- def self.create(connection, initial_table, type_caster)
10
- aliases = Hash.new(0)
11
- aliases[initial_table] = 1
12
- new connection, aliases, type_caster
13
- end
14
-
15
- def self.create_with_joins(connection, initial_table, joins, type_caster)
9
+ def self.create(connection, initial_table, joins)
16
10
  if joins.empty?
17
- create(connection, initial_table, type_caster)
11
+ aliases = Hash.new(0)
18
12
  else
19
13
  aliases = Hash.new { |h, k|
20
14
  h[k] = initial_count_for(connection, k, joins)
21
15
  }
22
- aliases[initial_table] = 1
23
- new connection, aliases, type_caster
24
16
  end
17
+ aliases[initial_table] = 1
18
+ new(connection, aliases)
25
19
  end
26
20
 
27
21
  def self.initial_count_for(connection, name, table_joins)
28
- # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase
29
- quoted_name = connection.quote_table_name(name).downcase
22
+ quoted_name = nil
30
23
 
31
24
  counts = table_joins.map do |join|
32
25
  if join.is_a?(Arel::Nodes::StringJoin)
26
+ # quoted_name should be case ignored as some database adapters (Oracle) return quoted name in uppercase
27
+ quoted_name ||= connection.quote_table_name(name)
28
+
33
29
  # Table names + table aliases
34
- join.left.downcase.scan(
35
- /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/
30
+ join.left.scan(
31
+ /JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name}|#{name})\sON/i
36
32
  ).size
37
- elsif join.respond_to? :left
38
- join.left.table_name == name ? 1 : 0
33
+ elsif join.is_a?(Arel::Nodes::Join)
34
+ join.left.name == name ? 1 : 0
35
+ elsif join.is_a?(Hash)
36
+ join[name]
39
37
  else
40
- # this branch is reached by two tests:
41
- #
42
- # activerecord/test/cases/associations/cascaded_eager_loading_test.rb:37
43
- # with :posts
44
- #
45
- # activerecord/test/cases/associations/eager_test.rb:1133
46
- # with :comments
47
- #
48
- 0
38
+ raise ArgumentError, "joins list should be initialized by list of Arel::Nodes::Join"
49
39
  end
50
40
  end
51
41
 
@@ -53,17 +43,16 @@ module ActiveRecord
53
43
  end
54
44
 
55
45
  # table_joins is an array of arel joins which might conflict with the aliases we assign here
56
- def initialize(connection, aliases, type_caster)
46
+ def initialize(connection, aliases)
57
47
  @aliases = aliases
58
48
  @connection = connection
59
- @type_caster = type_caster
60
49
  end
61
50
 
62
- def aliased_table_for(table_name, aliased_name)
51
+ def aliased_table_for(table_name, aliased_name, type_caster)
63
52
  if aliases[table_name].zero?
64
53
  # If it's zero, we can have our table_name
65
54
  aliases[table_name] = 1
66
- Arel::Table.new(table_name, type_caster: @type_caster)
55
+ Arel::Table.new(table_name, type_caster: type_caster)
67
56
  else
68
57
  # Otherwise, we need to use an alias
69
58
  aliased_name = @connection.table_alias_for(aliased_name)
@@ -76,12 +65,13 @@ module ActiveRecord
76
65
  else
77
66
  aliased_name
78
67
  end
79
- Arel::Table.new(table_name, type_caster: @type_caster).alias(table_alias)
68
+ Arel::Table.new(table_name, type_caster: type_caster).alias(table_alias)
80
69
  end
81
70
  end
82
71
 
83
- private
72
+ attr_reader :aliases
84
73
 
74
+ private
85
75
  def truncate(name)
86
76
  name.slice(0, @connection.table_alias_length - 2)
87
77
  end
@@ -1,4 +1,6 @@
1
- require 'active_support/core_ext/array/wrap'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/array/wrap"
2
4
 
3
5
  module ActiveRecord
4
6
  module Associations
@@ -15,11 +17,27 @@ module ActiveRecord
15
17
  # CollectionAssociation
16
18
  # HasManyAssociation + ForeignAssociation
17
19
  # HasManyThroughAssociation + ThroughAssociation
20
+ #
21
+ # Associations in Active Record are middlemen between the object that
22
+ # holds the association, known as the <tt>owner</tt>, and the associated
23
+ # result set, known as the <tt>target</tt>. Association metadata is available in
24
+ # <tt>reflection</tt>, which is an instance of <tt>ActiveRecord::Reflection::AssociationReflection</tt>.
25
+ #
26
+ # For example, given
27
+ #
28
+ # class Blog < ActiveRecord::Base
29
+ # has_many :posts
30
+ # end
31
+ #
32
+ # blog = Blog.first
33
+ #
34
+ # The association of <tt>blog.posts</tt> has the object +blog+ as its
35
+ # <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
36
+ # the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
18
37
  class Association #:nodoc:
19
38
  attr_reader :owner, :target, :reflection
20
- attr_accessor :inversed
21
39
 
22
- delegate :options, :to => :reflection
40
+ delegate :options, to: :reflection
23
41
 
24
42
  def initialize(owner, reflection)
25
43
  reflection.check_validity!
@@ -30,14 +48,6 @@ module ActiveRecord
30
48
  reset_scope
31
49
  end
32
50
 
33
- # Returns the name of the table of the associated class:
34
- #
35
- # post.comments.aliased_table_name # => "comments"
36
- #
37
- def aliased_table_name
38
- klass.table_name
39
- end
40
-
41
51
  # Resets the \loaded flag to +false+ and sets the \target to +nil+.
42
52
  def reset
43
53
  @loaded = false
@@ -47,7 +57,9 @@ module ActiveRecord
47
57
  end
48
58
 
49
59
  # Reloads the \target and returns +self+ on success.
50
- def reload
60
+ # The QueryCache is cleared if +force+ is true.
61
+ def reload(force = false)
62
+ klass.connection.clear_query_cache if force && klass
51
63
  reset
52
64
  reset_scope
53
65
  load_target
@@ -73,7 +85,7 @@ module ActiveRecord
73
85
  #
74
86
  # Note that if the target has not been loaded, it is not considered stale.
75
87
  def stale_target?
76
- !inversed && loaded? && @stale_state != stale_state
88
+ !@inversed && loaded? && @stale_state != stale_state
77
89
  end
78
90
 
79
91
  # Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
@@ -83,18 +95,10 @@ module ActiveRecord
83
95
  end
84
96
 
85
97
  def scope
86
- target_scope.merge!(association_scope)
87
- end
88
-
89
- # The scope for this association.
90
- #
91
- # Note that the association_scope is merged into the target_scope only when the
92
- # scope method is called. This is because at that point the call may be surrounded
93
- # by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
94
- # actually gets built.
95
- def association_scope
96
- if klass
97
- @association_scope ||= AssociationScope.scope(self, klass.connection)
98
+ if (scope = klass.current_scope) && scope.try(:proxy_association) == self
99
+ scope.spawn
100
+ else
101
+ target_scope.merge!(association_scope)
98
102
  end
99
103
  end
100
104
 
@@ -104,31 +108,43 @@ module ActiveRecord
104
108
 
105
109
  # Set the inverse association, if possible
106
110
  def set_inverse_instance(record)
107
- if invertible_for?(record)
108
- inverse = record.association(inverse_reflection_for(record).name)
109
- inverse.target = owner
110
- inverse.inversed = true
111
+ if inverse = inverse_association_for(record)
112
+ inverse.inversed_from(owner)
113
+ end
114
+ record
115
+ end
116
+
117
+ def set_inverse_instance_from_queries(record)
118
+ if inverse = inverse_association_for(record)
119
+ inverse.inversed_from_queries(owner)
111
120
  end
112
121
  record
113
122
  end
114
123
 
124
+ # Remove the inverse association, if possible
125
+ def remove_inverse_instance(record)
126
+ if inverse = inverse_association_for(record)
127
+ inverse.inversed_from(nil)
128
+ end
129
+ end
130
+
131
+ def inversed_from(record)
132
+ self.target = record
133
+ @inversed = !!record
134
+ end
135
+ alias :inversed_from_queries :inversed_from
136
+
115
137
  # Returns the class of the target. belongs_to polymorphic overrides this to look at the
116
138
  # polymorphic_type field on the owner.
117
139
  def klass
118
140
  reflection.klass
119
141
  end
120
142
 
121
- # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
122
- # through association's scope)
123
- def target_scope
124
- AssociationRelation.create(klass, klass.arel_table, klass.predicate_builder, self).merge!(klass.all)
125
- end
126
-
127
143
  def extensions
128
144
  extensions = klass.default_extensions | reflection.extensions
129
145
 
130
- if scope = reflection.scope
131
- extensions |= klass.unscoped.instance_exec(owner, &scope).extensions
146
+ if reflection.scope
147
+ extensions |= reflection.scope_for(klass.unscoped, owner).extensions
132
148
  end
133
149
 
134
150
  extensions
@@ -153,17 +169,9 @@ module ActiveRecord
153
169
  reset
154
170
  end
155
171
 
156
- def interpolate(sql, record = nil)
157
- if sql.respond_to?(:to_proc)
158
- owner.instance_exec(record, &sql)
159
- else
160
- sql
161
- end
162
- end
163
-
164
- # We can't dump @reflection since it contains the scope proc
172
+ # We can't dump @reflection and @through_reflection since it contains the scope proc
165
173
  def marshal_dump
166
- ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
174
+ ivars = (instance_variables - [:@reflection, :@through_reflection]).map { |name| [name, instance_variable_get(name)] }
167
175
  [@reflection.name, ivars]
168
176
  end
169
177
 
@@ -176,14 +184,56 @@ module ActiveRecord
176
184
  def initialize_attributes(record, except_from_scope_attributes = nil) #:nodoc:
177
185
  except_from_scope_attributes ||= {}
178
186
  skip_assign = [reflection.foreign_key, reflection.type].compact
179
- assigned_keys = record.changed
187
+ assigned_keys = record.changed_attribute_names_to_save
180
188
  assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
181
- attributes = create_scope.except(*(assigned_keys - skip_assign))
182
- record.assign_attributes(attributes)
189
+ attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
190
+ record.send(:_assign_attributes, attributes) if attributes.any?
183
191
  set_inverse_instance(record)
184
192
  end
185
193
 
194
+ def create(attributes = {}, &block)
195
+ _create_record(attributes, &block)
196
+ end
197
+
198
+ def create!(attributes = {}, &block)
199
+ _create_record(attributes, true, &block)
200
+ end
201
+
186
202
  private
203
+ def find_target
204
+ scope = self.scope
205
+ return scope.to_a if skip_statement_cache?(scope)
206
+
207
+ sc = reflection.association_scope_cache(klass, owner) do |params|
208
+ as = AssociationScope.create { params.bind }
209
+ target_scope.merge!(as.scope(self))
210
+ end
211
+
212
+ binds = AssociationScope.get_bind_values(owner, reflection.chain)
213
+ sc.execute(binds, klass.connection) { |record| set_inverse_instance(record) } || []
214
+ end
215
+
216
+ # The scope for this association.
217
+ #
218
+ # Note that the association_scope is merged into the target_scope only when the
219
+ # scope method is called. This is because at that point the call may be surrounded
220
+ # by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which
221
+ # actually gets built.
222
+ def association_scope
223
+ if klass
224
+ @association_scope ||= AssociationScope.scope(self)
225
+ end
226
+ end
227
+
228
+ # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
229
+ # through association's scope)
230
+ def target_scope
231
+ AssociationRelation.create(klass, self).merge!(klass.scope_for_association)
232
+ end
233
+
234
+ def scope_for_create
235
+ scope.scope_for_create
236
+ end
187
237
 
188
238
  def find_target?
189
239
  !loaded? && (!owner.new_record? || foreign_key_present?) && klass
@@ -195,8 +245,8 @@ module ActiveRecord
195
245
  if (reflection.has_one? || reflection.collection?) && !options[:through]
196
246
  attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
197
247
 
198
- if reflection.options[:as]
199
- attributes[reflection.type] = owner.class.base_class.name
248
+ if reflection.type
249
+ attributes[reflection.type] = owner.class.polymorphic_name
200
250
  end
201
251
  end
202
252
 
@@ -227,12 +277,19 @@ module ActiveRecord
227
277
  unless record.is_a?(reflection.klass)
228
278
  fresh_class = reflection.class_name.safe_constantize
229
279
  unless fresh_class && record.is_a?(fresh_class)
230
- message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"
280
+ message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, "\
281
+ "got #{record.inspect} which is an instance of #{record.class}(##{record.class.object_id})"
231
282
  raise ActiveRecord::AssociationTypeMismatch, message
232
283
  end
233
284
  end
234
285
  end
235
286
 
287
+ def inverse_association_for(record)
288
+ if invertible_for?(record)
289
+ record.association(inverse_reflection_for(record).name)
290
+ end
291
+ end
292
+
236
293
  # Can be redefined by subclasses, notably polymorphic belongs_to
237
294
  # The record parameter is necessary to support polymorphic inverses as we must check for
238
295
  # the association in the specific class of the record.
@@ -255,18 +312,19 @@ module ActiveRecord
255
312
  # so that when stale_state is different from the value stored on the last find_target,
256
313
  # the target is stale.
257
314
  #
258
- # This is only relevant to certain associations, which is why it returns nil by default.
315
+ # This is only relevant to certain associations, which is why it returns +nil+ by default.
259
316
  def stale_state
260
317
  end
261
318
 
262
319
  def build_record(attributes)
263
320
  reflection.build_association(attributes) do |record|
264
321
  initialize_attributes(record, attributes)
322
+ yield(record) if block_given?
265
323
  end
266
324
  end
267
325
 
268
326
  # Returns true if statement cache should be skipped on the association reader.
269
- def skip_statement_cache?
327
+ def skip_statement_cache?(scope)
270
328
  reflection.has_scope? ||
271
329
  scope.eager_loading? ||
272
330
  klass.scope_attributes? ||
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Associations
3
5
  class AssociationScope #:nodoc:
4
- def self.scope(association, connection)
5
- INSTANCE.scope(association, connection)
6
+ def self.scope(association)
7
+ INSTANCE.scope(association)
6
8
  end
7
9
 
8
10
  def self.create(&block)
@@ -16,20 +18,17 @@ module ActiveRecord
16
18
 
17
19
  INSTANCE = create
18
20
 
19
- def scope(association, connection)
21
+ def scope(association)
20
22
  klass = association.klass
21
23
  reflection = association.reflection
22
24
  scope = klass.unscoped
23
25
  owner = association.owner
24
- alias_tracker = AliasTracker.create connection, association.klass.table_name, klass.type_caster
25
- chain_head, chain_tail = get_chain(reflection, association, alias_tracker)
26
+ chain = get_chain(reflection, association, scope.alias_tracker)
26
27
 
27
28
  scope.extending! reflection.extensions
28
- add_constraints(scope, owner, klass, reflection, chain_head, chain_tail)
29
- end
30
-
31
- def join_type
32
- Arel::Nodes::InnerJoin
29
+ scope = add_constraints(scope, owner, chain)
30
+ scope.limit!(1) unless reflection.collection?
31
+ scope
33
32
  end
34
33
 
35
34
  def self.get_bind_values(owner, chain)
@@ -38,129 +37,136 @@ module ActiveRecord
38
37
 
39
38
  binds << last_reflection.join_id_for(owner)
40
39
  if last_reflection.type
41
- binds << owner.class.base_class.name
40
+ binds << owner.class.polymorphic_name
42
41
  end
43
42
 
44
43
  chain.each_cons(2).each do |reflection, next_reflection|
45
44
  if reflection.type
46
- binds << next_reflection.klass.base_class.name
45
+ binds << next_reflection.klass.polymorphic_name
47
46
  end
48
47
  end
49
48
  binds
50
49
  end
51
50
 
52
- protected
51
+ private
52
+ attr_reader :value_transformation
53
53
 
54
- attr_reader :value_transformation
54
+ def join(table, constraint)
55
+ table.create_join(table, table.create_on(constraint), Arel::Nodes::LeadingJoin)
56
+ end
55
57
 
56
- private
57
- def join(table, constraint)
58
- table.create_join(table, table.create_on(constraint), join_type)
59
- end
58
+ def last_chain_scope(scope, reflection, owner)
59
+ join_keys = reflection.join_keys
60
+ key = join_keys.key
61
+ foreign_key = join_keys.foreign_key
60
62
 
61
- def last_chain_scope(scope, table, reflection, owner, association_klass)
62
- join_keys = reflection.join_keys(association_klass)
63
- key = join_keys.key
64
- foreign_key = join_keys.foreign_key
63
+ table = reflection.aliased_table
64
+ value = transform_value(owner[foreign_key])
65
+ scope = apply_scope(scope, table, key, value)
65
66
 
66
- value = transform_value(owner[foreign_key])
67
- scope = scope.where(table.name => { key => value })
67
+ if reflection.type
68
+ polymorphic_type = transform_value(owner.class.polymorphic_name)
69
+ scope = apply_scope(scope, table, reflection.type, polymorphic_type)
70
+ end
68
71
 
69
- if reflection.type
70
- polymorphic_type = transform_value(owner.class.base_class.name)
71
- scope = scope.where(table.name => { reflection.type => polymorphic_type })
72
+ scope
72
73
  end
73
74
 
74
- scope
75
- end
75
+ def transform_value(value)
76
+ value_transformation.call(value)
77
+ end
76
78
 
77
- def transform_value(value)
78
- value_transformation.call(value)
79
- end
79
+ def next_chain_scope(scope, reflection, next_reflection)
80
+ join_keys = reflection.join_keys
81
+ key = join_keys.key
82
+ foreign_key = join_keys.foreign_key
80
83
 
81
- def next_chain_scope(scope, table, reflection, association_klass, foreign_table, next_reflection)
82
- join_keys = reflection.join_keys(association_klass)
83
- key = join_keys.key
84
- foreign_key = join_keys.foreign_key
84
+ table = reflection.aliased_table
85
+ foreign_table = next_reflection.aliased_table
86
+ constraint = table[key].eq(foreign_table[foreign_key])
85
87
 
86
- constraint = table[key].eq(foreign_table[foreign_key])
88
+ if reflection.type
89
+ value = transform_value(next_reflection.klass.polymorphic_name)
90
+ scope = apply_scope(scope, table, reflection.type, value)
91
+ end
87
92
 
88
- if reflection.type
89
- value = transform_value(next_reflection.klass.base_class.name)
90
- scope = scope.where(table.name => { reflection.type => value })
93
+ scope.joins!(join(foreign_table, constraint))
91
94
  end
92
95
 
93
- scope = scope.joins(join(foreign_table, constraint))
94
- end
96
+ class ReflectionProxy < SimpleDelegator # :nodoc:
97
+ attr_reader :aliased_table
95
98
 
96
- class ReflectionProxy < SimpleDelegator # :nodoc:
97
- attr_accessor :next
98
- attr_reader :alias_name
99
+ def initialize(reflection, aliased_table)
100
+ super(reflection)
101
+ @aliased_table = aliased_table
102
+ end
99
103
 
100
- def initialize(reflection, alias_name)
101
- super(reflection)
102
- @alias_name = alias_name
104
+ def all_includes; nil; end
103
105
  end
104
106
 
105
- def all_includes; nil; end
106
- end
107
-
108
- def get_chain(reflection, association, tracker)
109
- name = reflection.name
110
- runtime_reflection = Reflection::RuntimeReflection.new(reflection, association)
111
- previous_reflection = runtime_reflection
112
- reflection.chain.drop(1).each do |refl|
113
- alias_name = tracker.aliased_table_for(refl.table_name, refl.alias_candidate(name))
114
- proxy = ReflectionProxy.new(refl, alias_name)
115
- previous_reflection.next = proxy
116
- previous_reflection = proxy
107
+ def get_chain(reflection, association, tracker)
108
+ name = reflection.name
109
+ chain = [Reflection::RuntimeReflection.new(reflection, association)]
110
+ reflection.chain.drop(1).each do |refl|
111
+ aliased_table = tracker.aliased_table_for(
112
+ refl.table_name,
113
+ refl.alias_candidate(name),
114
+ refl.klass.type_caster
115
+ )
116
+ chain << ReflectionProxy.new(refl, aliased_table)
117
+ end
118
+ chain
117
119
  end
118
- [runtime_reflection, previous_reflection]
119
- end
120
-
121
- def add_constraints(scope, owner, association_klass, refl, chain_head, chain_tail)
122
- owner_reflection = chain_tail
123
- table = owner_reflection.alias_name
124
- scope = last_chain_scope(scope, table, owner_reflection, owner, association_klass)
125
120
 
126
- reflection = chain_head
127
- loop do
128
- break unless reflection
129
- table = reflection.alias_name
121
+ def add_constraints(scope, owner, chain)
122
+ scope = last_chain_scope(scope, chain.last, owner)
130
123
 
131
- unless reflection == chain_tail
132
- next_reflection = reflection.next
133
- foreign_table = next_reflection.alias_name
134
- scope = next_chain_scope(scope, table, reflection, association_klass, foreign_table, next_reflection)
124
+ chain.each_cons(2) do |reflection, next_reflection|
125
+ scope = next_chain_scope(scope, reflection, next_reflection)
135
126
  end
136
127
 
137
- # Exclude the scope of the association itself, because that
138
- # was already merged in the #scope method.
139
- reflection.constraints.each do |scope_chain_item|
140
- item = eval_scope(reflection.klass, scope_chain_item, owner)
141
-
142
- if scope_chain_item == refl.scope
143
- scope.merge! item.except(:where, :includes)
144
- end
145
-
146
- reflection.all_includes do
147
- scope.includes! item.includes_values
128
+ chain_head = chain.first
129
+ chain.reverse_each do |reflection|
130
+ # Exclude the scope of the association itself, because that
131
+ # was already merged in the #scope method.
132
+ reflection.constraints.each do |scope_chain_item|
133
+ item = eval_scope(reflection, scope_chain_item, owner)
134
+
135
+ if scope_chain_item == chain_head.scope
136
+ scope.merge! item.except(:where, :includes, :unscope, :order)
137
+ elsif !item.references_values.empty?
138
+ join_dependency = item.construct_join_dependency(
139
+ item.eager_load_values | item.includes_values, Arel::Nodes::OuterJoin
140
+ )
141
+ scope.joins!(*item.joins_values, join_dependency)
142
+ scope.left_outer_joins!(*item.left_outer_joins_values)
143
+ end
144
+
145
+ reflection.all_includes do
146
+ scope.includes! item.includes_values
147
+ end
148
+
149
+ scope.unscope!(*item.unscope_values)
150
+ scope.where_clause += item.where_clause
151
+ scope.order_values = item.order_values | scope.order_values
148
152
  end
149
-
150
- scope.unscope!(*item.unscope_values)
151
- scope.where_clause += item.where_clause
152
- scope.order_values |= item.order_values
153
153
  end
154
154
 
155
- reflection = reflection.next
155
+ scope
156
156
  end
157
157
 
158
- scope
159
- end
158
+ def apply_scope(scope, table, key, value)
159
+ if scope.table == table
160
+ scope.where!(key => value)
161
+ else
162
+ scope.where!(table.name => { key => value })
163
+ end
164
+ end
160
165
 
161
- def eval_scope(klass, scope, owner)
162
- klass.unscoped.instance_exec(owner, &scope)
163
- end
166
+ def eval_scope(reflection, scope, owner)
167
+ relation = reflection.build_scope(reflection.aliased_table)
168
+ relation.instance_exec(owner, &scope) || relation
169
+ end
164
170
  end
165
171
  end
166
172
  end