activerecord 5.1.4 → 5.1.5.rc1

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 (38) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +151 -0
  3. data/lib/active_record/associations/belongs_to_association.rb +2 -2
  4. data/lib/active_record/associations/builder/belongs_to.rb +7 -3
  5. data/lib/active_record/associations/has_many_association.rb +1 -1
  6. data/lib/active_record/associations/join_dependency.rb +3 -3
  7. data/lib/active_record/associations/join_dependency/join_association.rb +1 -9
  8. data/lib/active_record/associations/preloader/association.rb +11 -34
  9. data/lib/active_record/associations/preloader/through_association.rb +10 -3
  10. data/lib/active_record/attribute_methods/dirty.rb +3 -2
  11. data/lib/active_record/collection_cache_key.rb +2 -2
  12. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -0
  13. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -1
  14. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
  15. data/lib/active_record/connection_adapters/abstract_adapter.rb +2 -1
  16. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +5 -4
  17. data/lib/active_record/connection_adapters/column.rb +1 -1
  18. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +7 -0
  19. data/lib/active_record/connection_adapters/postgresql/column.rb +28 -1
  20. data/lib/active_record/connection_adapters/postgresql/quoting.rb +1 -1
  21. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +2 -1
  22. data/lib/active_record/connection_adapters/postgresql_adapter.rb +5 -3
  23. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +11 -4
  24. data/lib/active_record/gem_version.rb +2 -2
  25. data/lib/active_record/locking/pessimistic.rb +1 -1
  26. data/lib/active_record/log_subscriber.rb +3 -4
  27. data/lib/active_record/migration/compatibility.rb +34 -20
  28. data/lib/active_record/model_schema.rb +33 -33
  29. data/lib/active_record/persistence.rb +1 -5
  30. data/lib/active_record/query_cache.rb +6 -6
  31. data/lib/active_record/railties/databases.rake +2 -2
  32. data/lib/active_record/reflection.rb +24 -10
  33. data/lib/active_record/relation.rb +14 -2
  34. data/lib/active_record/relation/calculations.rb +16 -11
  35. data/lib/active_record/relation/finder_methods.rb +1 -11
  36. data/lib/active_record/relation/query_methods.rb +19 -14
  37. data/lib/active_record/tasks/database_tasks.rb +11 -10
  38. metadata +12 -10
@@ -311,7 +311,7 @@ db_namespace = namespace :db do
311
311
  begin
312
312
  should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
313
313
  ActiveRecord::Schema.verbose = false
314
- ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations["test"], :ruby, ENV["SCHEMA"]
314
+ ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations["test"], :ruby, ENV["SCHEMA"], "test"
315
315
  ensure
316
316
  if should_reconnect
317
317
  ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[ActiveRecord::Tasks::DatabaseTasks.env])
@@ -321,7 +321,7 @@ db_namespace = namespace :db do
321
321
 
322
322
  # desc "Recreate the test database from an existent structure.sql file"
323
323
  task load_structure: %w(db:test:purge) do
324
- ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations["test"], :sql, ENV["SCHEMA"]
324
+ ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations["test"], :sql, ENV["SCHEMA"], "test"
325
325
  end
326
326
 
327
327
  # desc "Empty the test database"
@@ -35,7 +35,8 @@ module ActiveRecord
35
35
 
36
36
  def self.add_reflection(ar, name, reflection)
37
37
  ar.clear_reflections_cache
38
- ar._reflections = ar._reflections.merge(name.to_s => reflection)
38
+ name = name.to_s
39
+ ar._reflections = ar._reflections.except(name).merge!(name => reflection)
39
40
  end
40
41
 
41
42
  def self.add_aggregate_reflection(ar, name, reflection)
@@ -187,17 +188,24 @@ module ActiveRecord
187
188
  end
188
189
  deprecate :scope_chain
189
190
 
191
+ def join_scope(table)
192
+ predicate_builder = predicate_builder(table)
193
+ scope_chain_items = join_scopes(table, predicate_builder)
194
+ klass_scope = klass_join_scope(table, predicate_builder)
195
+
196
+ scope_chain_items.inject(klass_scope || scope_chain_items.shift, &:merge!)
197
+ end
198
+
190
199
  def join_scopes(table, predicate_builder) # :nodoc:
191
200
  if scope
192
- [ActiveRecord::Relation.create(klass, table, predicate_builder)
193
- .instance_exec(&scope)]
201
+ [build_scope(table, predicate_builder).instance_exec(&scope)]
194
202
  else
195
203
  []
196
204
  end
197
205
  end
198
206
 
199
207
  def klass_join_scope(table, predicate_builder) # :nodoc:
200
- relation = ActiveRecord::Relation.create(klass, table, predicate_builder)
208
+ relation = build_scope(table, predicate_builder)
201
209
  klass.scope_for_association(relation)
202
210
  end
203
211
 
@@ -279,7 +287,14 @@ module ActiveRecord
279
287
  JoinKeys.new(join_pk(association_klass), join_fk)
280
288
  end
281
289
 
290
+ def build_scope(table, predicate_builder = predicate_builder(table))
291
+ Relation.create(klass, table, predicate_builder)
292
+ end
293
+
282
294
  private
295
+ def predicate_builder(table)
296
+ PredicateBuilder.new(TableMetadata.new(klass, table))
297
+ end
283
298
 
284
299
  def join_pk(_)
285
300
  foreign_key
@@ -398,7 +413,6 @@ module ActiveRecord
398
413
 
399
414
  def initialize(name, scope, options, active_record)
400
415
  super
401
- @automatic_inverse_of = nil
402
416
  @type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
403
417
  @foreign_type = options[:foreign_type] || "#{name}_type"
404
418
  @constructable = calculate_constructable(macro, options)
@@ -591,12 +605,14 @@ module ActiveRecord
591
605
  # If it cannot find a suitable inverse association name, it returns
592
606
  # +nil+.
593
607
  def inverse_name
594
- options.fetch(:inverse_of) do
595
- @automatic_inverse_of ||= automatic_inverse_of
608
+ unless defined?(@inverse_name)
609
+ @inverse_name = options.fetch(:inverse_of) { automatic_inverse_of }
596
610
  end
611
+
612
+ @inverse_name
597
613
  end
598
614
 
599
- # returns either false or the inverse association name that it finds.
615
+ # returns either +nil+ or the inverse association name that it finds.
600
616
  def automatic_inverse_of
601
617
  if can_find_inverse_of_automatically?(self)
602
618
  inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym
@@ -613,8 +629,6 @@ module ActiveRecord
613
629
  return inverse_name
614
630
  end
615
631
  end
616
-
617
- false
618
632
  end
619
633
 
620
634
  # Checks if the inverse reflection that is returned from the
@@ -571,7 +571,7 @@ module ActiveRecord
571
571
  relation = self
572
572
 
573
573
  if eager_loading?
574
- find_with_associations { |rel| relation = rel }
574
+ find_with_associations { |rel, _| relation = rel }
575
575
  end
576
576
 
577
577
  conn = klass.connection
@@ -664,7 +664,19 @@ module ActiveRecord
664
664
  end
665
665
 
666
666
  def exec_queries(&block)
667
- @records = eager_loading? ? find_with_associations.freeze : @klass.find_by_sql(arel, bound_attributes, &block).freeze
667
+ @records =
668
+ if eager_loading?
669
+ find_with_associations do |relation, join_dependency|
670
+ if ActiveRecord::NullRelation === relation
671
+ []
672
+ else
673
+ rows = connection.select_all(relation.arel, "SQL", relation.bound_attributes)
674
+ join_dependency.instantiate(rows, &block)
675
+ end.freeze
676
+ end
677
+ else
678
+ klass.find_by_sql(arel, bound_attributes, &block).freeze
679
+ end
668
680
 
669
681
  preload = preload_values
670
682
  preload += includes_values unless eager_loading?
@@ -111,7 +111,14 @@ module ActiveRecord
111
111
  def calculate(operation, column_name)
112
112
  if has_include?(column_name)
113
113
  relation = construct_relation_for_association_calculations
114
- relation.distinct! if operation.to_s.downcase == "count"
114
+
115
+ if operation.to_s.downcase == "count" && !distinct_value
116
+ relation.distinct!
117
+ # PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT
118
+ if (column_name == :all || column_name.nil?) && select_values.empty?
119
+ relation.order_values = []
120
+ end
121
+ end
115
122
 
116
123
  relation.calculate(operation, column_name)
117
124
  else
@@ -195,7 +202,7 @@ module ActiveRecord
195
202
  if operation == "count"
196
203
  column_name ||= select_for_count
197
204
  if column_name == :all
198
- if distinct && !(has_limit_or_offset? && order_values.any?)
205
+ if distinct && (group_values.any? || select_values.empty? && order_values.empty?)
199
206
  column_name = primary_key
200
207
  end
201
208
  elsif column_name =~ /\s*DISTINCT[\s(]+/i
@@ -227,7 +234,7 @@ module ActiveRecord
227
234
  def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
228
235
  column_alias = column_name
229
236
 
230
- if operation == "count" && has_limit_or_offset?
237
+ if operation == "count" && (column_name == :all && distinct || has_limit_or_offset?)
231
238
  # Shortcut when limit is zero.
232
239
  return 0 if limit_value == 0
233
240
 
@@ -369,14 +376,12 @@ module ActiveRecord
369
376
  end
370
377
 
371
378
  def build_count_subquery(relation, column_name, distinct)
372
- relation.select_values = [
373
- if column_name == :all
374
- distinct ? table[Arel.star] : Arel.sql("1")
375
- else
376
- column_alias = Arel.sql("count_column")
377
- aggregate_column(column_name).as(column_alias)
378
- end
379
- ]
379
+ if column_name == :all
380
+ relation.select_values = [ Arel.sql(FinderMethods::ONE_AS_ONE) ] unless distinct
381
+ else
382
+ column_alias = Arel.sql("count_column")
383
+ relation.select_values = [ aggregate_column(column_name).as(column_alias) ]
384
+ end
380
385
 
381
386
  subquery = relation.arel.as(Arel.sql("subquery_for_count"))
382
387
  select_value = operation_over_aggregate_column(column_alias || Arel.star, "count", false)
@@ -371,17 +371,7 @@ module ActiveRecord
371
371
  relation = select aliases.columns
372
372
  relation = apply_join_dependency(relation, join_dependency)
373
373
 
374
- if block_given?
375
- yield relation
376
- else
377
- if ActiveRecord::NullRelation === relation
378
- []
379
- else
380
- arel = relation.arel
381
- rows = connection.select_all(arel, "SQL", relation.bound_attributes)
382
- join_dependency.instantiate(rows, aliases)
383
- end
384
- end
374
+ yield relation, join_dependency
385
375
  end
386
376
 
387
377
  def construct_relation_for_exists(relation, conditions)
@@ -1041,6 +1041,8 @@ module ActiveRecord
1041
1041
  def build_select(arel)
1042
1042
  if select_values.any?
1043
1043
  arel.project(*arel_columns(select_values.uniq))
1044
+ elsif klass.ignored_columns.any?
1045
+ arel.project(*klass.column_names.map { |field| arel_attribute(field) })
1044
1046
  else
1045
1047
  arel.project(@klass.arel_table[Arel.star])
1046
1048
  end
@@ -1177,21 +1179,24 @@ module ActiveRecord
1177
1179
  end
1178
1180
  alias having_clause_factory where_clause_factory
1179
1181
 
1182
+ DEFAULT_VALUES = {
1183
+ create_with: FROZEN_EMPTY_HASH,
1184
+ readonly: false,
1185
+ where: Relation::WhereClause.empty,
1186
+ having: Relation::WhereClause.empty,
1187
+ from: Relation::FromClause.empty
1188
+ }
1189
+
1190
+ Relation::MULTI_VALUE_METHODS.each do |value|
1191
+ DEFAULT_VALUES[value] ||= FROZEN_EMPTY_ARRAY
1192
+ end
1193
+
1194
+ Relation::SINGLE_VALUE_METHODS.each do |value|
1195
+ DEFAULT_VALUES[value] = nil if DEFAULT_VALUES[value].nil?
1196
+ end
1197
+
1180
1198
  def default_value_for(name)
1181
- case name
1182
- when :create_with
1183
- FROZEN_EMPTY_HASH
1184
- when :readonly
1185
- false
1186
- when :where, :having
1187
- Relation::WhereClause.empty
1188
- when :from
1189
- Relation::FromClause.empty
1190
- when *Relation::MULTI_VALUE_METHODS
1191
- FROZEN_EMPTY_ARRAY
1192
- when *Relation::SINGLE_VALUE_METHODS
1193
- nil
1194
- else
1199
+ DEFAULT_VALUES.fetch(name) do
1195
1200
  raise ArgumentError, "unknown relation value #{name.inspect}"
1196
1201
  end
1197
1202
  end
@@ -223,22 +223,22 @@ module ActiveRecord
223
223
  class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
224
224
  end
225
225
 
226
- def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
226
+ def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env) # :nodoc:
227
227
  file ||= schema_file(format)
228
228
 
229
+ check_schema_file(file)
230
+ ActiveRecord::Base.establish_connection(configuration)
231
+
229
232
  case format
230
233
  when :ruby
231
- check_schema_file(file)
232
- ActiveRecord::Base.establish_connection(configuration)
233
234
  load(file)
234
235
  when :sql
235
- check_schema_file(file)
236
236
  structure_load(configuration, file)
237
237
  else
238
238
  raise ArgumentError, "unknown format #{format.inspect}"
239
239
  end
240
240
  ActiveRecord::InternalMetadata.create_table
241
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
241
+ ActiveRecord::InternalMetadata[:environment] = environment
242
242
  end
243
243
 
244
244
  def schema_file(format = ActiveRecord::Base.schema_format)
@@ -251,8 +251,8 @@ module ActiveRecord
251
251
  end
252
252
 
253
253
  def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
254
- each_current_configuration(environment) { |configuration|
255
- load_schema configuration, format, file
254
+ each_current_configuration(environment) { |configuration, configuration_environment|
255
+ load_schema configuration, format, file, configuration_environment
256
256
  }
257
257
  ActiveRecord::Base.establish_connection(environment.to_sym)
258
258
  end
@@ -299,9 +299,10 @@ module ActiveRecord
299
299
  environments = [environment]
300
300
  environments << "test" if environment == "development"
301
301
 
302
- configurations = ActiveRecord::Base.configurations.values_at(*environments)
303
- configurations.compact.each do |configuration|
304
- yield configuration unless configuration["database"].blank?
302
+ ActiveRecord::Base.configurations.slice(*environments).each do |configuration_environment, configuration|
303
+ next unless configuration["database"]
304
+
305
+ yield configuration, configuration_environment
305
306
  end
306
307
  end
307
308
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.4
4
+ version: 5.1.5.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-08 00:00:00.000000000 Z
11
+ date: 2018-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 5.1.4
19
+ version: 5.1.5.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 5.1.4
26
+ version: 5.1.5.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 5.1.4
33
+ version: 5.1.5.rc1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 5.1.4
40
+ version: 5.1.5.rc1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: arel
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -319,7 +319,9 @@ files:
319
319
  homepage: http://rubyonrails.org
320
320
  licenses:
321
321
  - MIT
322
- metadata: {}
322
+ metadata:
323
+ source_code_uri: https://github.com/rails/rails/tree/v5.1.5.rc1/activerecord
324
+ changelog_uri: https://github.com/rails/rails/blob/v5.1.5.rc1/activerecord/CHANGELOG.md
323
325
  post_install_message:
324
326
  rdoc_options:
325
327
  - "--main"
@@ -333,12 +335,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
333
335
  version: 2.2.2
334
336
  required_rubygems_version: !ruby/object:Gem::Requirement
335
337
  requirements:
336
- - - ">="
338
+ - - ">"
337
339
  - !ruby/object:Gem::Version
338
- version: '0'
340
+ version: 1.3.1
339
341
  requirements: []
340
342
  rubyforge_project:
341
- rubygems_version: 2.6.13
343
+ rubygems_version: 2.7.3
342
344
  signing_key:
343
345
  specification_version: 4
344
346
  summary: Object-relational mapper framework (part of Rails).