activerecord 5.0.7.2 → 6.0.3.4

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 +708 -2040
  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.rb +37 -22
  8. data/lib/active_record/advisory_lock_base.rb +18 -0
  9. data/lib/active_record/aggregations.rb +249 -247
  10. data/lib/active_record/association_relation.rb +18 -14
  11. data/lib/active_record/associations.rb +1603 -1592
  12. data/lib/active_record/associations/alias_tracker.rb +24 -34
  13. data/lib/active_record/associations/association.rb +114 -55
  14. data/lib/active_record/associations/association_scope.rb +94 -94
  15. data/lib/active_record/associations/belongs_to_association.rb +58 -42
  16. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  17. data/lib/active_record/associations/builder/association.rb +18 -25
  18. data/lib/active_record/associations/builder/belongs_to.rb +43 -54
  19. data/lib/active_record/associations/builder/collection_association.rb +7 -18
  20. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +41 -62
  21. data/lib/active_record/associations/builder/has_many.rb +4 -0
  22. data/lib/active_record/associations/builder/has_one.rb +37 -1
  23. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  24. data/lib/active_record/associations/collection_association.rb +86 -254
  25. data/lib/active_record/associations/collection_proxy.rb +158 -122
  26. data/lib/active_record/associations/foreign_association.rb +9 -0
  27. data/lib/active_record/associations/has_many_association.rb +23 -30
  28. data/lib/active_record/associations/has_many_through_association.rb +58 -44
  29. data/lib/active_record/associations/has_one_association.rb +59 -54
  30. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  31. data/lib/active_record/associations/join_dependency.rb +143 -176
  32. data/lib/active_record/associations/join_dependency/join_association.rb +38 -87
  33. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  34. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  35. data/lib/active_record/associations/preloader.rb +90 -103
  36. data/lib/active_record/associations/preloader/association.rb +86 -100
  37. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  38. data/lib/active_record/associations/singular_association.rb +12 -45
  39. data/lib/active_record/associations/through_association.rb +26 -14
  40. data/lib/active_record/attribute_assignment.rb +54 -61
  41. data/lib/active_record/attribute_decorators.rb +38 -17
  42. data/lib/active_record/attribute_methods.rb +66 -106
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
  44. data/lib/active_record/attribute_methods/dirty.rb +179 -109
  45. data/lib/active_record/attribute_methods/primary_key.rb +85 -92
  46. data/lib/active_record/attribute_methods/query.rb +4 -3
  47. data/lib/active_record/attribute_methods/read.rb +20 -49
  48. data/lib/active_record/attribute_methods/serialization.rb +29 -7
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
  50. data/lib/active_record/attribute_methods/write.rb +34 -33
  51. data/lib/active_record/attributes.rb +38 -25
  52. data/lib/active_record/autosave_association.rb +54 -35
  53. data/lib/active_record/base.rb +27 -24
  54. data/lib/active_record/callbacks.rb +64 -35
  55. data/lib/active_record/coders/json.rb +2 -0
  56. data/lib/active_record/coders/yaml_column.rb +11 -12
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +552 -323
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +228 -147
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -202
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +396 -562
  70. data/lib/active_record/connection_adapters/column.rb +41 -13
  71. data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
  73. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +137 -49
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  80. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  81. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
  82. data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -54
  85. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
  87. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  99. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  101. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -31
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +8 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  109. data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
  110. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +20 -26
  111. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  113. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
  115. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
  116. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  117. data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -275
  118. data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
  119. data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
  120. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  121. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  122. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  123. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
  124. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  127. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +259 -266
  128. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  129. data/lib/active_record/connection_handling.rb +143 -40
  130. data/lib/active_record/core.rb +201 -163
  131. data/lib/active_record/counter_cache.rb +60 -28
  132. data/lib/active_record/database_configurations.rb +233 -0
  133. data/lib/active_record/database_configurations/database_config.rb +37 -0
  134. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  135. data/lib/active_record/database_configurations/url_config.rb +78 -0
  136. data/lib/active_record/define_callbacks.rb +22 -0
  137. data/lib/active_record/dynamic_matchers.rb +87 -87
  138. data/lib/active_record/enum.rb +60 -23
  139. data/lib/active_record/errors.rb +114 -18
  140. data/lib/active_record/explain.rb +4 -4
  141. data/lib/active_record/explain_registry.rb +3 -1
  142. data/lib/active_record/explain_subscriber.rb +9 -4
  143. data/lib/active_record/fixture_set/file.rb +13 -8
  144. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  145. data/lib/active_record/fixture_set/render_context.rb +17 -0
  146. data/lib/active_record/fixture_set/table_row.rb +152 -0
  147. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  148. data/lib/active_record/fixtures.rb +194 -504
  149. data/lib/active_record/gem_version.rb +5 -3
  150. data/lib/active_record/inheritance.rb +150 -99
  151. data/lib/active_record/insert_all.rb +179 -0
  152. data/lib/active_record/integration.rb +116 -25
  153. data/lib/active_record/internal_metadata.rb +16 -19
  154. data/lib/active_record/legacy_yaml_adapter.rb +4 -2
  155. data/lib/active_record/locking/optimistic.rb +77 -87
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +48 -29
  158. data/lib/active_record/middleware/database_selector.rb +74 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +369 -302
  162. data/lib/active_record/migration/command_recorder.rb +134 -100
  163. data/lib/active_record/migration/compatibility.rb +174 -56
  164. data/lib/active_record/migration/join_table.rb +8 -7
  165. data/lib/active_record/model_schema.rb +131 -127
  166. data/lib/active_record/nested_attributes.rb +213 -202
  167. data/lib/active_record/no_touching.rb +12 -3
  168. data/lib/active_record/null_relation.rb +12 -34
  169. data/lib/active_record/persistence.rb +446 -77
  170. data/lib/active_record/query_cache.rb +13 -12
  171. data/lib/active_record/querying.rb +37 -24
  172. data/lib/active_record/railtie.rb +128 -36
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +2 -0
  175. data/lib/active_record/railties/controller_runtime.rb +34 -33
  176. data/lib/active_record/railties/databases.rake +312 -177
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +214 -252
  179. data/lib/active_record/relation.rb +440 -318
  180. data/lib/active_record/relation/batches.rb +98 -52
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
  182. data/lib/active_record/relation/calculations.rb +212 -173
  183. data/lib/active_record/relation/delegation.rb +72 -69
  184. data/lib/active_record/relation/finder_methods.rb +207 -247
  185. data/lib/active_record/relation/from_clause.rb +6 -8
  186. data/lib/active_record/relation/merger.rb +78 -62
  187. data/lib/active_record/relation/predicate_builder.rb +83 -105
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  195. data/lib/active_record/relation/query_attribute.rb +33 -2
  196. data/lib/active_record/relation/query_methods.rb +476 -334
  197. data/lib/active_record/relation/record_fetch_warning.rb +5 -3
  198. data/lib/active_record/relation/spawn_methods.rb +8 -8
  199. data/lib/active_record/relation/where_clause.rb +111 -96
  200. data/lib/active_record/relation/where_clause_factory.rb +6 -11
  201. data/lib/active_record/result.rb +69 -40
  202. data/lib/active_record/runtime_registry.rb +5 -3
  203. data/lib/active_record/sanitization.rb +83 -99
  204. data/lib/active_record/schema.rb +7 -14
  205. data/lib/active_record/schema_dumper.rb +71 -69
  206. data/lib/active_record/schema_migration.rb +16 -6
  207. data/lib/active_record/scoping.rb +20 -20
  208. data/lib/active_record/scoping/default.rb +92 -95
  209. data/lib/active_record/scoping/named.rb +47 -27
  210. data/lib/active_record/secure_token.rb +4 -2
  211. data/lib/active_record/serialization.rb +2 -0
  212. data/lib/active_record/statement_cache.rb +63 -28
  213. data/lib/active_record/store.rb +121 -41
  214. data/lib/active_record/suppressor.rb +6 -3
  215. data/lib/active_record/table_metadata.rb +39 -18
  216. data/lib/active_record/tasks/database_tasks.rb +271 -81
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +225 -0
  222. data/lib/active_record/timestamp.rb +70 -36
  223. data/lib/active_record/touch_later.rb +8 -6
  224. data/lib/active_record/transactions.rb +141 -157
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type.rb +23 -18
  227. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  228. data/lib/active_record/type/date.rb +2 -0
  229. data/lib/active_record/type/date_time.rb +2 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  232. data/lib/active_record/type/internal/timezone.rb +2 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +16 -9
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +2 -1
  237. data/lib/active_record/type/type_map.rb +14 -17
  238. data/lib/active_record/type/unsigned_integer.rb +16 -0
  239. data/lib/active_record/type_caster.rb +4 -2
  240. data/lib/active_record/type_caster/connection.rb +17 -12
  241. data/lib/active_record/type_caster/map.rb +5 -4
  242. data/lib/active_record/validations.rb +7 -5
  243. data/lib/active_record/validations/absence.rb +2 -0
  244. data/lib/active_record/validations/associated.rb +4 -3
  245. data/lib/active_record/validations/length.rb +2 -0
  246. data/lib/active_record/validations/presence.rb +4 -2
  247. data/lib/active_record/validations/uniqueness.rb +29 -42
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/arel.rb +62 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +256 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +203 -0
  317. data/lib/arel/visitors/dot.rb +296 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +156 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +158 -0
  323. data/lib/arel/visitors/oracle12.rb +65 -0
  324. data/lib/arel/visitors/postgresql.rb +109 -0
  325. data/lib/arel/visitors/sqlite.rb +38 -0
  326. data/lib/arel/visitors/to_sql.rb +888 -0
  327. data/lib/arel/visitors/visitor.rb +45 -0
  328. data/lib/arel/visitors/where_sql.rb +22 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +7 -5
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  332. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  333. data/lib/rails/generators/active_record/migration.rb +17 -3
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
  335. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
  336. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
  337. data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
  338. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  339. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  340. metadata +137 -52
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  348. data/lib/active_record/attribute.rb +0 -213
  349. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  350. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/attribute_set/builder.rb +0 -132
  353. data/lib/active_record/collection_cache_key.rb +0 -50
  354. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  355. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  356. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  357. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  358. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  359. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -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,57 @@ 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
+ conn = klass.connection
208
+ sc = reflection.association_scope_cache(conn, owner) do |params|
209
+ as = AssociationScope.create { params.bind }
210
+ target_scope.merge!(as.scope(self))
211
+ end
212
+
213
+ binds = AssociationScope.get_bind_values(owner, reflection.chain)
214
+ sc.execute(binds, conn) { |record| set_inverse_instance(record) } || []
215
+ end
216
+
217
+ # The scope for this association.
218
+ #
219
+ # Note that the association_scope is merged into the target_scope only when the
220
+ # scope method is called. This is because at that point the call may be surrounded
221
+ # by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which
222
+ # actually gets built.
223
+ def association_scope
224
+ if klass
225
+ @association_scope ||= AssociationScope.scope(self)
226
+ end
227
+ end
228
+
229
+ # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
230
+ # through association's scope)
231
+ def target_scope
232
+ AssociationRelation.create(klass, self).merge!(klass.scope_for_association)
233
+ end
234
+
235
+ def scope_for_create
236
+ scope.scope_for_create
237
+ end
187
238
 
188
239
  def find_target?
189
240
  !loaded? && (!owner.new_record? || foreign_key_present?) && klass
@@ -195,8 +246,8 @@ module ActiveRecord
195
246
  if (reflection.has_one? || reflection.collection?) && !options[:through]
196
247
  attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
197
248
 
198
- if reflection.options[:as]
199
- attributes[reflection.type] = owner.class.base_class.name
249
+ if reflection.type
250
+ attributes[reflection.type] = owner.class.polymorphic_name
200
251
  end
201
252
  end
202
253
 
@@ -227,12 +278,19 @@ module ActiveRecord
227
278
  unless record.is_a?(reflection.klass)
228
279
  fresh_class = reflection.class_name.safe_constantize
229
280
  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})"
281
+ message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, "\
282
+ "got #{record.inspect} which is an instance of #{record.class}(##{record.class.object_id})"
231
283
  raise ActiveRecord::AssociationTypeMismatch, message
232
284
  end
233
285
  end
234
286
  end
235
287
 
288
+ def inverse_association_for(record)
289
+ if invertible_for?(record)
290
+ record.association(inverse_reflection_for(record).name)
291
+ end
292
+ end
293
+
236
294
  # Can be redefined by subclasses, notably polymorphic belongs_to
237
295
  # The record parameter is necessary to support polymorphic inverses as we must check for
238
296
  # the association in the specific class of the record.
@@ -255,18 +313,19 @@ module ActiveRecord
255
313
  # so that when stale_state is different from the value stored on the last find_target,
256
314
  # the target is stale.
257
315
  #
258
- # This is only relevant to certain associations, which is why it returns nil by default.
316
+ # This is only relevant to certain associations, which is why it returns +nil+ by default.
259
317
  def stale_state
260
318
  end
261
319
 
262
320
  def build_record(attributes)
263
321
  reflection.build_association(attributes) do |record|
264
322
  initialize_attributes(record, attributes)
323
+ yield(record) if block_given?
265
324
  end
266
325
  end
267
326
 
268
327
  # Returns true if statement cache should be skipped on the association reader.
269
- def skip_statement_cache?
328
+ def skip_statement_cache?(scope)
270
329
  reflection.has_scope? ||
271
330
  scope.eager_loading? ||
272
331
  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,130 @@ 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))
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
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)
121
+ def add_constraints(scope, owner, chain)
122
+ scope = last_chain_scope(scope, chain.last, owner)
125
123
 
126
- reflection = chain_head
127
- loop do
128
- break unless reflection
129
- table = reflection.alias_name
130
-
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)
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)
141
134
 
142
- if scope_chain_item == refl.scope
143
- scope.merge! item.except(:where, :includes)
144
- end
135
+ if scope_chain_item == chain_head.scope
136
+ scope.merge! item.except(:where, :includes, :unscope, :order)
137
+ end
145
138
 
146
- reflection.all_includes do
147
- scope.includes! item.includes_values
148
- end
139
+ reflection.all_includes do
140
+ scope.includes! item.includes_values
141
+ end
149
142
 
150
- scope.unscope!(*item.unscope_values)
151
- scope.where_clause += item.where_clause
152
- scope.order_values |= item.order_values
143
+ scope.unscope!(*item.unscope_values)
144
+ scope.where_clause += item.where_clause
145
+ scope.order_values = item.order_values | scope.order_values
146
+ end
153
147
  end
154
148
 
155
- reflection = reflection.next
149
+ scope
156
150
  end
157
151
 
158
- scope
159
- end
152
+ def apply_scope(scope, table, key, value)
153
+ if scope.table == table
154
+ scope.where!(key => value)
155
+ else
156
+ scope.where!(table.name => { key => value })
157
+ end
158
+ end
160
159
 
161
- def eval_scope(klass, scope, owner)
162
- klass.unscoped.instance_exec(owner, &scope)
163
- end
160
+ def eval_scope(reflection, scope, owner)
161
+ relation = reflection.build_scope(reflection.aliased_table)
162
+ relation.instance_exec(owner, &scope) || relation
163
+ end
164
164
  end
165
165
  end
166
166
  end