activerecord 4.2.11.3 → 5.0.0.beta1

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 (229) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1029 -1349
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -7
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record.rb +7 -3
  7. data/lib/active_record/aggregations.rb +35 -25
  8. data/lib/active_record/association_relation.rb +2 -2
  9. data/lib/active_record/associations.rb +305 -204
  10. data/lib/active_record/associations/alias_tracker.rb +19 -16
  11. data/lib/active_record/associations/association.rb +10 -8
  12. data/lib/active_record/associations/association_scope.rb +73 -102
  13. data/lib/active_record/associations/belongs_to_association.rb +20 -32
  14. data/lib/active_record/associations/builder/association.rb +28 -34
  15. data/lib/active_record/associations/builder/belongs_to.rb +41 -18
  16. data/lib/active_record/associations/builder/collection_association.rb +8 -24
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +11 -11
  18. data/lib/active_record/associations/builder/has_many.rb +4 -4
  19. data/lib/active_record/associations/builder/has_one.rb +10 -5
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -9
  21. data/lib/active_record/associations/collection_association.rb +40 -43
  22. data/lib/active_record/associations/collection_proxy.rb +55 -29
  23. data/lib/active_record/associations/foreign_association.rb +1 -1
  24. data/lib/active_record/associations/has_many_association.rb +20 -71
  25. data/lib/active_record/associations/has_many_through_association.rb +8 -52
  26. data/lib/active_record/associations/has_one_association.rb +12 -5
  27. data/lib/active_record/associations/join_dependency.rb +28 -18
  28. data/lib/active_record/associations/join_dependency/join_association.rb +13 -12
  29. data/lib/active_record/associations/preloader.rb +13 -4
  30. data/lib/active_record/associations/preloader/association.rb +45 -51
  31. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  32. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  33. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  34. data/lib/active_record/associations/preloader/through_association.rb +5 -4
  35. data/lib/active_record/associations/singular_association.rb +6 -0
  36. data/lib/active_record/associations/through_association.rb +11 -3
  37. data/lib/active_record/attribute.rb +61 -17
  38. data/lib/active_record/attribute/user_provided_default.rb +23 -0
  39. data/lib/active_record/attribute_assignment.rb +27 -140
  40. data/lib/active_record/attribute_decorators.rb +6 -5
  41. data/lib/active_record/attribute_methods.rb +79 -26
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  43. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  44. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  45. data/lib/active_record/attribute_methods/query.rb +2 -2
  46. data/lib/active_record/attribute_methods/read.rb +26 -42
  47. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +42 -9
  49. data/lib/active_record/attribute_methods/write.rb +13 -24
  50. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  51. data/lib/active_record/attribute_set.rb +30 -3
  52. data/lib/active_record/attribute_set/builder.rb +6 -4
  53. data/lib/active_record/attributes.rb +194 -81
  54. data/lib/active_record/autosave_association.rb +33 -15
  55. data/lib/active_record/base.rb +30 -18
  56. data/lib/active_record/callbacks.rb +36 -40
  57. data/lib/active_record/coders/yaml_column.rb +20 -8
  58. data/lib/active_record/collection_cache_key.rb +31 -0
  59. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +431 -122
  60. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  61. data/lib/active_record/connection_adapters/abstract/database_statements.rb +40 -22
  62. data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -8
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -38
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +229 -185
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +52 -13
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +275 -115
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +32 -33
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -32
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +384 -221
  70. data/lib/active_record/connection_adapters/column.rb +27 -41
  71. data/lib/active_record/connection_adapters/connection_specification.rb +2 -21
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  73. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +57 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +69 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +59 -0
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +22 -101
  77. data/lib/active_record/connection_adapters/postgresql/column.rb +6 -10
  78. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -3
  79. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  80. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +23 -57
  81. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  85. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  87. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +23 -16
  92. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  93. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  96. data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -11
  97. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  98. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  99. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +54 -0
  100. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +174 -128
  101. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  102. data/lib/active_record/connection_adapters/postgresql_adapter.rb +184 -112
  103. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  104. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  105. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +15 -0
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +134 -110
  107. data/lib/active_record/connection_adapters/statement_pool.rb +28 -11
  108. data/lib/active_record/connection_handling.rb +5 -5
  109. data/lib/active_record/core.rb +72 -104
  110. data/lib/active_record/counter_cache.rb +9 -20
  111. data/lib/active_record/dynamic_matchers.rb +1 -20
  112. data/lib/active_record/enum.rb +110 -76
  113. data/lib/active_record/errors.rb +72 -47
  114. data/lib/active_record/explain_registry.rb +1 -1
  115. data/lib/active_record/explain_subscriber.rb +1 -1
  116. data/lib/active_record/fixture_set/file.rb +19 -4
  117. data/lib/active_record/fixtures.rb +76 -40
  118. data/lib/active_record/gem_version.rb +4 -4
  119. data/lib/active_record/inheritance.rb +27 -40
  120. data/lib/active_record/integration.rb +4 -4
  121. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  122. data/lib/active_record/locale/en.yml +3 -2
  123. data/lib/active_record/locking/optimistic.rb +10 -14
  124. data/lib/active_record/locking/pessimistic.rb +1 -1
  125. data/lib/active_record/log_subscriber.rb +40 -22
  126. data/lib/active_record/migration.rb +304 -133
  127. data/lib/active_record/migration/command_recorder.rb +59 -18
  128. data/lib/active_record/migration/compatibility.rb +90 -0
  129. data/lib/active_record/model_schema.rb +92 -40
  130. data/lib/active_record/nested_attributes.rb +45 -34
  131. data/lib/active_record/null_relation.rb +15 -7
  132. data/lib/active_record/persistence.rb +112 -72
  133. data/lib/active_record/querying.rb +6 -5
  134. data/lib/active_record/railtie.rb +20 -13
  135. data/lib/active_record/railties/controller_runtime.rb +1 -1
  136. data/lib/active_record/railties/databases.rake +47 -38
  137. data/lib/active_record/readonly_attributes.rb +1 -1
  138. data/lib/active_record/reflection.rb +182 -57
  139. data/lib/active_record/relation.rb +152 -100
  140. data/lib/active_record/relation/batches.rb +133 -33
  141. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  142. data/lib/active_record/relation/calculations.rb +80 -101
  143. data/lib/active_record/relation/delegation.rb +6 -19
  144. data/lib/active_record/relation/finder_methods.rb +58 -46
  145. data/lib/active_record/relation/from_clause.rb +32 -0
  146. data/lib/active_record/relation/merger.rb +13 -42
  147. data/lib/active_record/relation/predicate_builder.rb +99 -105
  148. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  149. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +78 -0
  150. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  151. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  152. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  153. data/lib/active_record/relation/predicate_builder/range_handler.rb +17 -0
  154. data/lib/active_record/relation/query_attribute.rb +19 -0
  155. data/lib/active_record/relation/query_methods.rb +274 -238
  156. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  157. data/lib/active_record/relation/spawn_methods.rb +3 -6
  158. data/lib/active_record/relation/where_clause.rb +173 -0
  159. data/lib/active_record/relation/where_clause_factory.rb +37 -0
  160. data/lib/active_record/result.rb +4 -3
  161. data/lib/active_record/runtime_registry.rb +1 -1
  162. data/lib/active_record/sanitization.rb +94 -65
  163. data/lib/active_record/schema.rb +23 -22
  164. data/lib/active_record/schema_dumper.rb +33 -22
  165. data/lib/active_record/schema_migration.rb +10 -4
  166. data/lib/active_record/scoping.rb +17 -6
  167. data/lib/active_record/scoping/default.rb +19 -6
  168. data/lib/active_record/scoping/named.rb +39 -28
  169. data/lib/active_record/secure_token.rb +38 -0
  170. data/lib/active_record/serialization.rb +2 -4
  171. data/lib/active_record/statement_cache.rb +15 -13
  172. data/lib/active_record/store.rb +8 -3
  173. data/lib/active_record/suppressor.rb +54 -0
  174. data/lib/active_record/table_metadata.rb +64 -0
  175. data/lib/active_record/tasks/database_tasks.rb +30 -40
  176. data/lib/active_record/tasks/mysql_database_tasks.rb +7 -15
  177. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  178. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  179. data/lib/active_record/timestamp.rb +16 -9
  180. data/lib/active_record/touch_later.rb +58 -0
  181. data/lib/active_record/transactions.rb +138 -56
  182. data/lib/active_record/type.rb +66 -17
  183. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  184. data/lib/active_record/type/date.rb +2 -45
  185. data/lib/active_record/type/date_time.rb +2 -49
  186. data/lib/active_record/type/internal/abstract_json.rb +33 -0
  187. data/lib/active_record/type/internal/timezone.rb +15 -0
  188. data/lib/active_record/type/serialized.rb +9 -14
  189. data/lib/active_record/type/time.rb +3 -21
  190. data/lib/active_record/type/type_map.rb +4 -4
  191. data/lib/active_record/type_caster.rb +7 -0
  192. data/lib/active_record/type_caster/connection.rb +29 -0
  193. data/lib/active_record/type_caster/map.rb +19 -0
  194. data/lib/active_record/validations.rb +33 -32
  195. data/lib/active_record/validations/absence.rb +24 -0
  196. data/lib/active_record/validations/associated.rb +10 -3
  197. data/lib/active_record/validations/length.rb +36 -0
  198. data/lib/active_record/validations/presence.rb +12 -12
  199. data/lib/active_record/validations/uniqueness.rb +24 -21
  200. data/lib/rails/generators/active_record/migration.rb +7 -0
  201. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  202. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  203. data/lib/rails/generators/active_record/migration/templates/migration.rb +4 -1
  204. data/lib/rails/generators/active_record/model/model_generator.rb +21 -15
  205. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  206. metadata +50 -35
  207. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  208. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  209. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  210. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  211. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  212. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  213. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  214. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  215. data/lib/active_record/type/big_integer.rb +0 -13
  216. data/lib/active_record/type/binary.rb +0 -50
  217. data/lib/active_record/type/boolean.rb +0 -31
  218. data/lib/active_record/type/decimal.rb +0 -64
  219. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  220. data/lib/active_record/type/decorator.rb +0 -14
  221. data/lib/active_record/type/float.rb +0 -19
  222. data/lib/active_record/type/integer.rb +0 -59
  223. data/lib/active_record/type/mutable.rb +0 -16
  224. data/lib/active_record/type/numeric.rb +0 -36
  225. data/lib/active_record/type/string.rb +0 -40
  226. data/lib/active_record/type/text.rb +0 -11
  227. data/lib/active_record/type/time_value.rb +0 -38
  228. data/lib/active_record/type/unsigned_integer.rb +0 -15
  229. data/lib/active_record/type/value.rb +0 -110
@@ -16,11 +16,11 @@ module ActiveRecord
16
16
  config.app_generators.orm :active_record, :migration => true,
17
17
  :timestamps => true
18
18
 
19
- config.app_middleware.insert_after "::ActionDispatch::Callbacks",
20
- "ActiveRecord::QueryCache"
19
+ config.app_middleware.insert_after ::ActionDispatch::Callbacks,
20
+ ActiveRecord::QueryCache
21
21
 
22
- config.app_middleware.insert_after "::ActionDispatch::Callbacks",
23
- "ActiveRecord::ConnectionAdapters::ConnectionManagement"
22
+ config.app_middleware.insert_after ::ActionDispatch::Callbacks,
23
+ ActiveRecord::ConnectionAdapters::ConnectionManagement
24
24
 
25
25
  config.action_dispatch.rescue_responses.merge!(
26
26
  'ActiveRecord::RecordNotFound' => :not_found,
@@ -57,10 +57,8 @@ module ActiveRecord
57
57
  console do |app|
58
58
  require "active_record/railties/console_sandbox" if app.sandbox?
59
59
  require "active_record/base"
60
- unless ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDERR, STDOUT)
61
- console = ActiveSupport::Logger.new(STDERR)
62
- Rails.logger.extend ActiveSupport::Logger.broadcast console
63
- end
60
+ console = ActiveSupport::Logger.new(STDERR)
61
+ Rails.logger.extend ActiveSupport::Logger.broadcast console
64
62
  end
65
63
 
66
64
  runner do
@@ -80,8 +78,8 @@ module ActiveRecord
80
78
 
81
79
  initializer "active_record.migration_error" do
82
80
  if config.active_record.delete(:migration_error) == :page_load
83
- config.app_middleware.insert_after "::ActionDispatch::Callbacks",
84
- "ActiveRecord::Migration::CheckPending"
81
+ config.app_middleware.insert_after ::ActionDispatch::Callbacks,
82
+ ActiveRecord::Migration::CheckPending
85
83
  end
86
84
  end
87
85
 
@@ -95,6 +93,7 @@ module ActiveRecord
95
93
  cache = Marshal.load File.binread filename
96
94
  if cache.version == ActiveRecord::Migrator.current_version
97
95
  self.connection.schema_cache = cache
96
+ self.connection_pool.schema_cache = cache.dup
98
97
  else
99
98
  warn "Ignoring db/schema_cache.dump because it has expired. The current schema version is #{ActiveRecord::Migrator.current_version}, but the one in the cache is #{cache.version}."
100
99
  end
@@ -104,6 +103,14 @@ module ActiveRecord
104
103
  end
105
104
  end
106
105
 
106
+ initializer "active_record.warn_on_records_fetched_greater_than" do
107
+ if config.active_record.warn_on_records_fetched_greater_than
108
+ ActiveSupport.on_load(:active_record) do
109
+ require 'active_record/relation/record_fetch_warning'
110
+ end
111
+ end
112
+ end
113
+
107
114
  initializer "active_record.set_configs" do |app|
108
115
  ActiveSupport.on_load(:active_record) do
109
116
  app.config.active_record.each do |k,v|
@@ -114,7 +121,7 @@ module ActiveRecord
114
121
 
115
122
  # This sets the database configuration from Configuration#database_configuration
116
123
  # and then establishes the connection.
117
- initializer "active_record.initialize_database" do |app|
124
+ initializer "active_record.initialize_database" do
118
125
  ActiveSupport.on_load(:active_record) do
119
126
  self.configurations = Rails.application.config.database_configuration
120
127
 
@@ -127,8 +134,8 @@ Oops - You have a database configured, but it doesn't exist yet!
127
134
  Here's how to get started:
128
135
 
129
136
  1. Configure your database in config/database.yml.
130
- 2. Run `bin/rake db:create` to create the database.
131
- 3. Run `bin/rake db:setup` to load your database schema.
137
+ 2. Run `bin/rails db:create` to create the database.
138
+ 3. Run `bin/rails db:setup` to load your database schema.
132
139
  end_warning
133
140
  raise
134
141
  end
@@ -19,7 +19,7 @@ module ActiveRecord
19
19
  end
20
20
 
21
21
  def cleanup_view_runtime
22
- if ActiveRecord::Base.connected?
22
+ if logger.info? && ActiveRecord::Base.connected?
23
23
  db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
24
24
  self.db_runtime = (db_runtime || 0) + db_rt_before_render
25
25
  runtime = super
@@ -12,7 +12,7 @@ db_namespace = namespace :db do
12
12
  end
13
13
  end
14
14
 
15
- desc 'Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV it defaults to creating the development and test databases.'
15
+ desc 'Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV, it defaults to creating the development and test databases.'
16
16
  task :create => [:load_config] do
17
17
  ActiveRecord::Tasks::DatabaseTasks.create_current
18
18
  end
@@ -23,7 +23,7 @@ db_namespace = namespace :db do
23
23
  end
24
24
  end
25
25
 
26
- desc 'Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV it defaults to dropping the development and test databases.'
26
+ desc 'Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV, it defaults to dropping the development and test databases.'
27
27
  task :drop => [:load_config] do
28
28
  ActiveRecord::Tasks::DatabaseTasks.drop_current
29
29
  end
@@ -34,7 +34,7 @@ db_namespace = namespace :db do
34
34
  end
35
35
  end
36
36
 
37
- # desc "Empty the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV it defaults to purging the development and test databases."
37
+ # desc "Empty the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:purge:all to purge all databases in the config). Without RAILS_ENV it defaults to purging the development and test databases."
38
38
  task :purge => [:load_config] do
39
39
  ActiveRecord::Tasks::DatabaseTasks.purge_current
40
40
  end
@@ -63,8 +63,6 @@ db_namespace = namespace :db do
63
63
  namespace :migrate do
64
64
  # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
65
65
  task :redo => [:environment, :load_config] do
66
- raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
67
-
68
66
  if ENV['VERSION']
69
67
  db_namespace['migrate:down'].invoke
70
68
  db_namespace['migrate:up'].invoke
@@ -79,18 +77,17 @@ db_namespace = namespace :db do
79
77
 
80
78
  # desc 'Runs the "up" for a given migration VERSION.'
81
79
  task :up => [:environment, :load_config] do
82
- raise "VERSION is required" if ENV["VERSION"] && ENV["VERSION"].empty?
83
-
84
80
  version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
85
- ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_paths, version)
81
+ raise 'VERSION is required' unless version
82
+ ActiveRecord::Migrator.run(:up, ActiveRecord::Tasks::DatabaseTasks.migrations_paths, version)
86
83
  db_namespace['_dump'].invoke
87
84
  end
88
85
 
89
86
  # desc 'Runs the "down" for a given migration VERSION.'
90
87
  task :down => [:environment, :load_config] do
91
- raise "VERSION is required - To go down one migration, use db:rollback" if ENV["VERSION"] && ENV["VERSION"].empty?
92
88
  version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
93
- ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_paths, version)
89
+ raise 'VERSION is required - To go down one migration, run db:rollback' unless version
90
+ ActiveRecord::Migrator.run(:down, ActiveRecord::Tasks::DatabaseTasks.migrations_paths, version)
94
91
  db_namespace['_dump'].invoke
95
92
  end
96
93
 
@@ -99,13 +96,28 @@ db_namespace = namespace :db do
99
96
  unless ActiveRecord::SchemaMigration.table_exists?
100
97
  abort 'Schema migrations table does not exist yet.'
101
98
  end
99
+ db_list = ActiveRecord::SchemaMigration.normalized_versions
100
+
101
+ file_list =
102
+ ActiveRecord::Tasks::DatabaseTasks.migrations_paths.flat_map do |path|
103
+ Dir.foreach(path).map do |file|
104
+ next unless ActiveRecord::Migrator.match_to_migration_filename?(file)
105
+
106
+ version, name, scope = ActiveRecord::Migrator.parse_migration_filename(file)
107
+ version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
108
+ status = db_list.delete(version) ? 'up' : 'down'
109
+ [status, version, (name + scope).humanize]
110
+ end.compact
111
+ end
102
112
 
113
+ db_list.map! do |version|
114
+ ['up', version, '********** NO FILE **********']
115
+ end
103
116
  # output
104
117
  puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
105
118
  puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
106
119
  puts "-" * 50
107
- paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
108
- ActiveRecord::Migrator.migrations_status(paths).each do |status, version, name|
120
+ (db_list + file_list).sort_by { |_, version, _| version }.each do |status, version, name|
109
121
  puts "#{status.center(8)} #{version.ljust(14)} #{name}"
110
122
  end
111
123
  puts
@@ -115,22 +127,19 @@ db_namespace = namespace :db do
115
127
  desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).'
116
128
  task :rollback => [:environment, :load_config] do
117
129
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
118
- ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step)
130
+ ActiveRecord::Migrator.rollback(ActiveRecord::Tasks::DatabaseTasks.migrations_paths, step)
119
131
  db_namespace['_dump'].invoke
120
132
  end
121
133
 
122
134
  # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
123
135
  task :forward => [:environment, :load_config] do
124
136
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
125
- ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_paths, step)
137
+ ActiveRecord::Migrator.forward(ActiveRecord::Tasks::DatabaseTasks.migrations_paths, step)
126
138
  db_namespace['_dump'].invoke
127
139
  end
128
140
 
129
141
  # desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
130
- task :reset => [:environment, :load_config] do
131
- db_namespace["drop"].invoke
132
- db_namespace["setup"].invoke
133
- end
142
+ task :reset => [ 'db:drop', 'db:setup' ]
134
143
 
135
144
  # desc "Retrieves the charset for the current environment's database"
136
145
  task :charset => [:environment, :load_config] do
@@ -152,29 +161,29 @@ db_namespace = namespace :db do
152
161
  end
153
162
 
154
163
  # desc "Raises an error if there are pending migrations"
155
- task :abort_if_pending_migrations => :environment do
156
- pending_migrations = ActiveRecord::Migrator.open(ActiveRecord::Migrator.migrations_paths).pending_migrations
164
+ task :abort_if_pending_migrations => [:environment, :load_config] do
165
+ pending_migrations = ActiveRecord::Migrator.open(ActiveRecord::Tasks::DatabaseTasks.migrations_paths).pending_migrations
157
166
 
158
167
  if pending_migrations.any?
159
168
  puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
160
169
  pending_migrations.each do |pending_migration|
161
170
  puts ' %4d %s' % [pending_migration.version, pending_migration.name]
162
171
  end
163
- abort %{Run `rake db:migrate` to update your database then try again.}
172
+ abort %{Run `rails db:migrate` to update your database then try again.}
164
173
  end
165
174
  end
166
175
 
167
- desc 'Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the database first)'
176
+ desc 'Creates the database, loads the schema, and initializes with the seed data (use db:reset to also drop the database first)'
168
177
  task :setup => ['db:schema:load_if_ruby', 'db:structure:load_if_sql', :seed]
169
178
 
170
- desc 'Load the seed data from db/seeds.rb'
179
+ desc 'Loads the seed data from db/seeds.rb'
171
180
  task :seed do
172
181
  db_namespace['abort_if_pending_migrations'].invoke
173
182
  ActiveRecord::Tasks::DatabaseTasks.load_seed
174
183
  end
175
184
 
176
185
  namespace :fixtures do
177
- desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
186
+ desc "Loads fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
178
187
  task :load => [:environment, :load_config] do
179
188
  require 'active_record/fixtures'
180
189
 
@@ -222,7 +231,7 @@ db_namespace = namespace :db do
222
231
  end
223
232
 
224
233
  namespace :schema do
225
- desc 'Create a db/schema.rb file that is portable against any DB supported by AR'
234
+ desc 'Creates a db/schema.rb file that is portable against any DB supported by Active Record'
226
235
  task :dump => [:environment, :load_config] do
227
236
  require 'active_record/schema_dumper'
228
237
  filename = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb')
@@ -232,7 +241,7 @@ db_namespace = namespace :db do
232
241
  db_namespace['schema:dump'].reenable
233
242
  end
234
243
 
235
- desc 'Load a schema.rb file into the database'
244
+ desc 'Loads a schema.rb file into the database'
236
245
  task :load => [:environment, :load_config] do
237
246
  ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV['SCHEMA'])
238
247
  end
@@ -242,17 +251,17 @@ db_namespace = namespace :db do
242
251
  end
243
252
 
244
253
  namespace :cache do
245
- desc 'Create a db/schema_cache.dump file.'
254
+ desc 'Creates a db/schema_cache.dump file.'
246
255
  task :dump => [:environment, :load_config] do
247
256
  con = ActiveRecord::Base.connection
248
257
  filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
249
258
 
250
259
  con.schema_cache.clear!
251
- con.tables.each { |table| con.schema_cache.add(table) }
260
+ con.data_sources.each { |table| con.schema_cache.add(table) }
252
261
  open(filename, 'wb') { |f| f.write(Marshal.dump(con.schema_cache)) }
253
262
  end
254
263
 
255
- desc 'Clear a db/schema_cache.dump file.'
264
+ desc 'Clears a db/schema_cache.dump file.'
256
265
  task :clear => [:environment, :load_config] do
257
266
  filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
258
267
  FileUtils.rm(filename) if File.exist?(filename)
@@ -262,9 +271,9 @@ db_namespace = namespace :db do
262
271
  end
263
272
 
264
273
  namespace :structure do
265
- desc 'Dump the database structure to db/structure.sql. Specify another file with DB_STRUCTURE=db/my_structure.sql'
274
+ desc 'Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql'
266
275
  task :dump => [:environment, :load_config] do
267
- filename = ENV['DB_STRUCTURE'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
276
+ filename = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
268
277
  current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
269
278
  ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
270
279
 
@@ -278,9 +287,9 @@ db_namespace = namespace :db do
278
287
  db_namespace['structure:dump'].reenable
279
288
  end
280
289
 
281
- desc "Recreate the databases from the structure.sql file"
290
+ desc "Recreates the databases from the structure.sql file"
282
291
  task :load => [:load_config] do
283
- ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV['DB_STRUCTURE'])
292
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV['SCHEMA'])
284
293
  end
285
294
 
286
295
  task :load_if_sql => ['db:create', :environment] do
@@ -312,7 +321,7 @@ db_namespace = namespace :db do
312
321
  begin
313
322
  should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
314
323
  ActiveRecord::Schema.verbose = false
315
- ActiveRecord::Tasks::DatabaseTasks.load_schema_for ActiveRecord::Base.configurations['test'], :ruby, ENV['SCHEMA']
324
+ ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations['test'], :ruby, ENV['SCHEMA']
316
325
  ensure
317
326
  if should_reconnect
318
327
  ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[ActiveRecord::Tasks::DatabaseTasks.env])
@@ -322,7 +331,7 @@ db_namespace = namespace :db do
322
331
 
323
332
  # desc "Recreate the test database from an existent structure.sql file"
324
333
  task :load_structure => %w(db:test:purge) do
325
- ActiveRecord::Tasks::DatabaseTasks.load_schema_for ActiveRecord::Base.configurations['test'], :sql, ENV['SCHEMA']
334
+ ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations['test'], :sql, ENV['SCHEMA']
326
335
  end
327
336
 
328
337
  # desc "Recreate the test database from a fresh schema"
@@ -346,7 +355,7 @@ db_namespace = namespace :db do
346
355
  ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations['test']
347
356
  end
348
357
 
349
- # desc 'Check for pending migrations and load the test schema'
358
+ # desc 'Load the test schema'
350
359
  task :prepare => %w(environment load_config) do
351
360
  unless ActiveRecord::Base.configurations.blank?
352
361
  db_namespace['test:load'].invoke
@@ -359,7 +368,7 @@ namespace :railties do
359
368
  namespace :install do
360
369
  # desc "Copies missing migrations from Railties (e.g. engines). You can specify Railties to use with FROM=railtie1,railtie2"
361
370
  task :migrations => :'db:load_config' do
362
- to_load = ENV['FROM'].blank? ? :all : ENV['FROM'].split(",").map {|n| n.strip }
371
+ to_load = ENV['FROM'].blank? ? :all : ENV['FROM'].split(",").map(&:strip)
363
372
  railties = {}
364
373
  Rails.application.migration_railties.each do |railtie|
365
374
  next unless to_load == :all || to_load.include?(railtie.railtie_name)
@@ -377,7 +386,7 @@ namespace :railties do
377
386
  puts "Copied migration #{migration.basename} from #{name}"
378
387
  end
379
388
 
380
- ActiveRecord::Migration.copy(ActiveRecord::Migrator.migrations_paths.first, railties,
389
+ ActiveRecord::Migration.copy(ActiveRecord::Tasks::DatabaseTasks.migrations_paths.first, railties,
381
390
  :on_skip => on_skip, :on_copy => on_copy)
382
391
  end
383
392
  end
@@ -11,7 +11,7 @@ module ActiveRecord
11
11
  # Attributes listed as readonly will be used to create a new record but update operations will
12
12
  # ignore these fields.
13
13
  def attr_readonly(*attributes)
14
- self._attr_readonly = Set.new(attributes.map { |a| a.to_s }) + (self._attr_readonly || [])
14
+ self._attr_readonly = Set.new(attributes.map(&:to_s)) + (self._attr_readonly || [])
15
15
  end
16
16
 
17
17
  # Returns an array of all the attributes that have been specified as readonly.
@@ -7,8 +7,8 @@ module ActiveRecord
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
- class_attribute :_reflections, instance_writer: false
11
- class_attribute :aggregate_reflections, instance_writer: false
10
+ class_attribute :_reflections
11
+ class_attribute :aggregate_reflections
12
12
  self._reflections = {}
13
13
  self.aggregate_reflections = {}
14
14
  end
@@ -40,9 +40,9 @@ module ActiveRecord
40
40
  ar.aggregate_reflections = ar.aggregate_reflections.merge(name.to_s => reflection)
41
41
  end
42
42
 
43
- # \Reflection enables interrogating of Active Record classes and objects
44
- # about their associations and aggregations. This information can,
45
- # for example, be used in a form builder that takes an Active Record object
43
+ # \Reflection enables the ability to examine the associations and aggregations of
44
+ # Active Record classes and objects. This information, for example,
45
+ # can be used in a form builder that takes an Active Record object
46
46
  # and creates input fields for all of the attributes depending on their type
47
47
  # and displays the associations to other objects.
48
48
  #
@@ -62,20 +62,20 @@ module ActiveRecord
62
62
  aggregate_reflections[aggregation.to_s]
63
63
  end
64
64
 
65
- # Returns a Hash of name of the reflection as the key and a AssociationReflection as the value.
65
+ # Returns a Hash of name of the reflection as the key and an AssociationReflection as the value.
66
66
  #
67
67
  # Account.reflections # => {"balance" => AggregateReflection}
68
68
  #
69
- # @api public
70
69
  def reflections
71
70
  @__reflections ||= begin
72
71
  ref = {}
73
72
 
74
73
  _reflections.each do |name, reflection|
75
- parent_name, parent_reflection = reflection.parent_reflection
74
+ parent_reflection = reflection.parent_reflection
76
75
 
77
- if parent_name
78
- ref[parent_name] = parent_reflection
76
+ if parent_reflection
77
+ parent_name = parent_reflection.name
78
+ ref[parent_name.to_s] = parent_reflection
79
79
  else
80
80
  ref[name] = reflection
81
81
  end
@@ -95,10 +95,10 @@ module ActiveRecord
95
95
  # Account.reflect_on_all_associations # returns an array of all associations
96
96
  # Account.reflect_on_all_associations(:has_many) # returns an array of all has_many associations
97
97
  #
98
- # @api public
99
98
  def reflect_on_all_associations(macro = nil)
100
99
  association_reflections = reflections.values
101
- macro ? association_reflections.select { |reflection| reflection.macro == macro } : association_reflections
100
+ association_reflections.select! { |reflection| reflection.macro == macro } if macro
101
+ association_reflections
102
102
  end
103
103
 
104
104
  # Returns the AssociationReflection object for the +association+ (use the symbol).
@@ -106,24 +106,20 @@ module ActiveRecord
106
106
  # Account.reflect_on_association(:owner) # returns the owner AssociationReflection
107
107
  # Invoice.reflect_on_association(:line_items).macro # returns :has_many
108
108
  #
109
- # @api public
110
109
  def reflect_on_association(association)
111
110
  reflections[association.to_s]
112
111
  end
113
112
 
114
- # @api private
115
113
  def _reflect_on_association(association) #:nodoc:
116
114
  _reflections[association.to_s]
117
115
  end
118
116
 
119
117
  # Returns an array of AssociationReflection objects for all associations which have <tt>:autosave</tt> enabled.
120
- #
121
- # @api public
122
118
  def reflect_on_all_autosave_associations
123
119
  reflections.values.select { |reflection| reflection.options[:autosave] }
124
120
  end
125
121
 
126
- def clear_reflections_cache #:nodoc:
122
+ def clear_reflections_cache # :nodoc:
127
123
  @__reflections = nil
128
124
  end
129
125
  end
@@ -159,17 +155,24 @@ module ActiveRecord
159
155
 
160
156
  JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
161
157
 
162
- def join_keys(assoc_klass)
158
+ def join_keys(association_klass)
163
159
  JoinKeys.new(foreign_key, active_record_primary_key)
164
160
  end
165
161
 
166
- def source_macro
167
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
168
- ActiveRecord::Base.source_macro is deprecated and will be removed
169
- without replacement.
170
- MSG
162
+ def constraints
163
+ scope_chain.flatten
164
+ end
171
165
 
172
- macro
166
+ def counter_cache_column
167
+ if belongs_to?
168
+ if options[:counter_cache] == true
169
+ "#{active_record.name.demodulize.underscore.pluralize}_count"
170
+ elsif options[:counter_cache]
171
+ options[:counter_cache].to_s
172
+ end
173
+ else
174
+ options[:counter_cache] ? options[:counter_cache].to_s : "#{name}_count"
175
+ end
173
176
  end
174
177
 
175
178
  def inverse_of
@@ -185,13 +188,54 @@ module ActiveRecord
185
188
  end
186
189
  end
187
190
  end
191
+
192
+ # This shit is nasty. We need to avoid the following situation:
193
+ #
194
+ # * An associated record is deleted via record.destroy
195
+ # * Hence the callbacks run, and they find a belongs_to on the record with a
196
+ # :counter_cache options which points back at our owner. So they update the
197
+ # counter cache.
198
+ # * In which case, we must make sure to *not* update the counter cache, or else
199
+ # it will be decremented twice.
200
+ #
201
+ # Hence this method.
202
+ def inverse_which_updates_counter_cache
203
+ return @inverse_which_updates_counter_cache if defined?(@inverse_which_updates_counter_cache)
204
+ @inverse_which_updates_counter_cache = klass.reflect_on_all_associations(:belongs_to).find do |inverse|
205
+ inverse.counter_cache_column == counter_cache_column
206
+ end
207
+ end
208
+ alias inverse_updates_counter_cache? inverse_which_updates_counter_cache
209
+
210
+ def inverse_updates_counter_in_memory?
211
+ inverse_of && inverse_which_updates_counter_cache == inverse_of
212
+ end
213
+
214
+ # Returns whether a counter cache should be used for this association.
215
+ #
216
+ # The counter_cache option must be given on either the owner or inverse
217
+ # association, and the column must be present on the owner.
218
+ def has_cached_counter?
219
+ options[:counter_cache] ||
220
+ inverse_which_updates_counter_cache && inverse_which_updates_counter_cache.options[:counter_cache] &&
221
+ !!active_record.columns_hash[counter_cache_column]
222
+ end
223
+
224
+ def counter_must_be_updated_by_has_many?
225
+ !inverse_updates_counter_in_memory? && has_cached_counter?
226
+ end
227
+
228
+ def alias_candidate(name)
229
+ "#{plural_name}_#{name}"
230
+ end
188
231
  end
232
+
189
233
  # Base class for AggregateReflection and AssociationReflection. Objects of
190
234
  # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods.
191
235
  #
192
236
  # MacroReflection
237
+ # AggregateReflection
193
238
  # AssociationReflection
194
- # AggregateReflection
195
239
  # HasManyReflection
196
240
  # HasOneReflection
197
241
  # BelongsToReflection
@@ -228,7 +272,7 @@ module ActiveRecord
228
272
  def autosave=(autosave)
229
273
  @automatic_inverse_of = false
230
274
  @options[:autosave] = autosave
231
- _, parent_reflection = self.parent_reflection
275
+ parent_reflection = self.parent_reflection
232
276
  if parent_reflection
233
277
  parent_reflection.autosave = autosave
234
278
  end
@@ -296,7 +340,7 @@ module ActiveRecord
296
340
  end
297
341
 
298
342
  attr_reader :type, :foreign_type
299
- attr_accessor :parent_reflection # [:name, Reflection]
343
+ attr_accessor :parent_reflection # Reflection
300
344
 
301
345
  def initialize(name, scope, options, active_record)
302
346
  super
@@ -343,14 +387,6 @@ module ActiveRecord
343
387
  @active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
344
388
  end
345
389
 
346
- def counter_cache_column
347
- if options[:counter_cache] == true
348
- "#{active_record.name.demodulize.underscore.pluralize}_count"
349
- elsif options[:counter_cache]
350
- options[:counter_cache].to_s
351
- end
352
- end
353
-
354
390
  def check_validity!
355
391
  check_validity_of_inverse!
356
392
  end
@@ -359,13 +395,10 @@ module ActiveRecord
359
395
  return unless scope
360
396
 
361
397
  if scope.arity > 0
362
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
398
+ raise ArgumentError, <<-MSG.squish
363
399
  The association scope '#{name}' is instance dependent (the scope
364
- block takes an argument). Preloading happens before the individual
365
- instances are created. This means that there is no instance being
366
- passed to the association scope. This will most likely result in
367
- broken or incorrect behavior. Joining, Preloading and eager loading
368
- of these associations is deprecated and will be removed in the future.
400
+ block takes an argument). Preloading instance dependent scopes is
401
+ not supported.
369
402
  MSG
370
403
  end
371
404
  end
@@ -389,6 +422,12 @@ module ActiveRecord
389
422
  [self]
390
423
  end
391
424
 
425
+ # This is for clearing cache on the reflection. Useful for tests that need to compare
426
+ # SQL queries on associations.
427
+ def clear_association_scope_cache # :nodoc:
428
+ @association_scope_cache.clear
429
+ end
430
+
392
431
  def nested?
393
432
  false
394
433
  end
@@ -611,8 +650,8 @@ module ActiveRecord
611
650
 
612
651
  def belongs_to?; true; end
613
652
 
614
- def join_keys(assoc_klass)
615
- key = polymorphic? ? association_primary_key(assoc_klass) : association_primary_key
653
+ def join_keys(association_klass)
654
+ key = polymorphic? ? association_primary_key(association_klass) : association_primary_key
616
655
  JoinKeys.new(key, foreign_key)
617
656
  end
618
657
 
@@ -707,13 +746,27 @@ module ActiveRecord
707
746
  def chain
708
747
  @chain ||= begin
709
748
  a = source_reflection.chain
710
- b = through_reflection.chain
749
+ b = through_reflection.chain.map(&:dup)
750
+
751
+ if options[:source_type]
752
+ b[0] = PolymorphicReflection.new(b[0], self)
753
+ end
754
+
711
755
  chain = a + b
712
756
  chain[0] = self # Use self so we don't lose the information from :source_type
713
757
  chain
714
758
  end
715
759
  end
716
760
 
761
+ # This is for clearing cache on the reflection. Useful for tests that need to compare
762
+ # SQL queries on associations.
763
+ def clear_association_scope_cache # :nodoc:
764
+ @chain = nil
765
+ delegate_reflection.clear_association_scope_cache
766
+ source_reflection.clear_association_scope_cache
767
+ through_reflection.clear_association_scope_cache
768
+ end
769
+
717
770
  # Consider the following example:
718
771
  #
719
772
  # class Person
@@ -755,18 +808,8 @@ module ActiveRecord
755
808
  end
756
809
  end
757
810
 
758
- def join_keys(assoc_klass)
759
- source_reflection.join_keys(assoc_klass)
760
- end
761
-
762
- # The macro used by the source association
763
- def source_macro
764
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
765
- ActiveRecord::Base.source_macro is deprecated and will be removed
766
- without replacement.
767
- MSG
768
-
769
- source_reflection.source_macro
811
+ def join_keys(association_klass)
812
+ source_reflection.join_keys(association_klass)
770
813
  end
771
814
 
772
815
  # A through association is nested if there would be more than one join table
@@ -801,7 +844,7 @@ module ActiveRecord
801
844
  def source_reflection_name # :nodoc:
802
845
  return @source_reflection_name if @source_reflection_name
803
846
 
804
- names = [name.to_s.singularize, name].collect { |n| n.to_sym }.uniq
847
+ names = [name.to_s.singularize, name].collect(&:to_sym).uniq
805
848
  names = names.find_all { |n|
806
849
  through_reflection.klass._reflect_on_association(n)
807
850
  }
@@ -865,6 +908,12 @@ module ActiveRecord
865
908
  check_validity_of_inverse!
866
909
  end
867
910
 
911
+ def constraints
912
+ scope_chain = source_reflection.constraints
913
+ scope_chain << scope if scope
914
+ scope_chain
915
+ end
916
+
868
917
  protected
869
918
 
870
919
  def actual_source_reflection # FIXME: this is a horrible name
@@ -889,5 +938,81 @@ module ActiveRecord
889
938
  delegate(*delegate_methods, to: :delegate_reflection)
890
939
 
891
940
  end
941
+
942
+ class PolymorphicReflection < ThroughReflection # :nodoc:
943
+ def initialize(reflection, previous_reflection)
944
+ @reflection = reflection
945
+ @previous_reflection = previous_reflection
946
+ end
947
+
948
+ def klass
949
+ @reflection.klass
950
+ end
951
+
952
+ def scope
953
+ @reflection.scope
954
+ end
955
+
956
+ def table_name
957
+ @reflection.table_name
958
+ end
959
+
960
+ def plural_name
961
+ @reflection.plural_name
962
+ end
963
+
964
+ def join_keys(association_klass)
965
+ @reflection.join_keys(association_klass)
966
+ end
967
+
968
+ def type
969
+ @reflection.type
970
+ end
971
+
972
+ def constraints
973
+ [source_type_info]
974
+ end
975
+
976
+ def source_type_info
977
+ type = @previous_reflection.foreign_type
978
+ source_type = @previous_reflection.options[:source_type]
979
+ lambda { |object| where(type => source_type) }
980
+ end
981
+ end
982
+
983
+ class RuntimeReflection < PolymorphicReflection # :nodoc:
984
+ attr_accessor :next
985
+
986
+ def initialize(reflection, association)
987
+ @reflection = reflection
988
+ @association = association
989
+ end
990
+
991
+ def klass
992
+ @association.klass
993
+ end
994
+
995
+ def table_name
996
+ klass.table_name
997
+ end
998
+
999
+ def constraints
1000
+ @reflection.constraints
1001
+ end
1002
+
1003
+ def source_type_info
1004
+ @reflection.source_type_info
1005
+ end
1006
+
1007
+ def alias_candidate(name)
1008
+ "#{plural_name}_#{name}_join"
1009
+ end
1010
+
1011
+ def alias_name
1012
+ Arel::Table.new(table_name)
1013
+ end
1014
+
1015
+ def all_includes; yield; end
1016
+ end
892
1017
  end
893
1018
  end