activerecord 4.2.2 → 4.2.3.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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +116 -1
  3. data/lib/active_record.rb +1 -0
  4. data/lib/active_record/association_relation.rb +13 -0
  5. data/lib/active_record/associations.rb +1 -1
  6. data/lib/active_record/associations/belongs_to_association.rb +5 -1
  7. data/lib/active_record/associations/builder/association.rb +1 -1
  8. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -1
  9. data/lib/active_record/associations/collection_proxy.rb +8 -7
  10. data/lib/active_record/associations/has_many_through_association.rb +1 -1
  11. data/lib/active_record/associations/join_dependency.rb +6 -1
  12. data/lib/active_record/associations/through_association.rb +1 -1
  13. data/lib/active_record/attribute_assignment.rb +1 -1
  14. data/lib/active_record/attribute_methods/dirty.rb +6 -1
  15. data/lib/active_record/base.rb +4 -5
  16. data/lib/active_record/callbacks.rb +6 -6
  17. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +6 -2
  18. data/lib/active_record/connection_adapters/abstract/database_statements.rb +4 -0
  19. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +14 -22
  20. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +27 -13
  21. data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
  22. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +6 -0
  23. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -1
  24. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
  25. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +17 -5
  26. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +2 -4
  27. data/lib/active_record/connection_adapters/postgresql_adapter.rb +7 -3
  28. data/lib/active_record/core.rb +17 -12
  29. data/lib/active_record/errors.rb +2 -2
  30. data/lib/active_record/explain_subscriber.rb +1 -1
  31. data/lib/active_record/fixtures.rb +8 -6
  32. data/lib/active_record/gem_version.rb +2 -2
  33. data/lib/active_record/migration.rb +1 -2
  34. data/lib/active_record/persistence.rb +5 -3
  35. data/lib/active_record/railties/databases.rake +1 -1
  36. data/lib/active_record/reflection.rb +2 -2
  37. data/lib/active_record/relation/delegation.rb +1 -1
  38. data/lib/active_record/relation/finder_methods.rb +3 -15
  39. data/lib/active_record/relation/predicate_builder.rb +11 -2
  40. data/lib/active_record/relation/query_methods.rb +13 -16
  41. data/lib/active_record/tasks/database_tasks.rb +1 -1
  42. data/lib/active_record/transactions.rb +14 -6
  43. data/lib/active_record/type/boolean.rb +1 -0
  44. data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
  45. data/lib/active_record/type/serialized.rb +7 -1
  46. data/lib/active_record/validations/uniqueness.rb +9 -5
  47. metadata +8 -8
@@ -40,7 +40,7 @@ module ActiveRecord
40
40
  BLACKLISTED_ARRAY_METHODS = [
41
41
  :compact!, :flatten!, :reject!, :reverse!, :rotate!, :map!,
42
42
  :shuffle!, :slice!, :sort!, :sort_by!, :delete_if,
43
- :keep_if, :pop, :shift, :delete_at, :compact, :select!
43
+ :keep_if, :pop, :shift, :delete_at, :select!
44
44
  ].to_set # :nodoc:
45
45
 
46
46
  delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :join, to: :to_a
@@ -114,23 +114,11 @@ module ActiveRecord
114
114
  # Find the first record (or first N records if a parameter is supplied).
115
115
  # If no order is defined it will order by primary key.
116
116
  #
117
- # Person.first # returns the first object fetched by SELECT * FROM people
117
+ # Person.first # returns the first object fetched by SELECT * FROM people ORDER BY people.id LIMIT 1
118
118
  # Person.where(["user_name = ?", user_name]).first
119
119
  # Person.where(["user_name = :u", { u: user_name }]).first
120
120
  # Person.order("created_on DESC").offset(5).first
121
- # Person.first(3) # returns the first three objects fetched by SELECT * FROM people LIMIT 3
122
- #
123
- # ==== Rails 3
124
- #
125
- # Person.first # SELECT "people".* FROM "people" LIMIT 1
126
- #
127
- # NOTE: Rails 3 may not order this query by the primary key and the order
128
- # will depend on the database implementation. In order to ensure that behavior,
129
- # use <tt>User.order(:id).first</tt> instead.
130
- #
131
- # ==== Rails 4
132
- #
133
- # Person.first # SELECT "people".* FROM "people" ORDER BY "people"."id" ASC LIMIT 1
121
+ # Person.first(3) # returns the first three objects fetched by SELECT * FROM people ORDER BY people.id LIMIT 3
134
122
  #
135
123
  def first(limit = nil)
136
124
  if limit
@@ -379,7 +367,7 @@ module ActiveRecord
379
367
  def construct_relation_for_association_calculations
380
368
  from = arel.froms.first
381
369
  if Arel::Table === from
382
- apply_join_dependency(self, construct_join_dependency)
370
+ apply_join_dependency(self, construct_join_dependency(joins_values))
383
371
  else
384
372
  # FIXME: as far as I can tell, `from` will always be an Arel::Table.
385
373
  # There are no tests that test this branch, but presumably it's
@@ -6,7 +6,9 @@ module ActiveRecord
6
6
  autoload :ArrayHandler, 'active_record/relation/predicate_builder/array_handler'
7
7
 
8
8
  def self.resolve_column_aliases(klass, hash)
9
- hash = hash.dup
9
+ # This method is a hot spot, so for now, use Hash[] to dup the hash.
10
+ # https://bugs.ruby-lang.org/issues/7166
11
+ hash = Hash[hash]
10
12
  hash.keys.grep(Symbol) do |key|
11
13
  if klass.attribute_alias? key
12
14
  hash[klass.attribute_alias(key)] = hash.delete key
@@ -112,7 +114,8 @@ module ActiveRecord
112
114
  @handlers.unshift([klass, handler])
113
115
  end
114
116
 
115
- register_handler(BasicObject, ->(attribute, value) { attribute.eq(value) })
117
+ BASIC_OBJECT_HANDLER = ->(attribute, value) { attribute.eq(value) } # :nodoc:
118
+ register_handler(BasicObject, BASIC_OBJECT_HANDLER)
116
119
  # FIXME: I think we need to deprecate this behavior
117
120
  register_handler(Class, ->(attribute, value) { attribute.eq(value.name) })
118
121
  register_handler(Base, ->(attribute, value) { attribute.eq(value.id) })
@@ -142,5 +145,11 @@ module ActiveRecord
142
145
  value
143
146
  end
144
147
  end
148
+
149
+ def self.can_be_bound?(value) # :nodoc:
150
+ !value.nil? &&
151
+ !value.is_a?(Hash) &&
152
+ handler_for(value) == BASIC_OBJECT_HANDLER
153
+ end
145
154
  end
146
155
  end
@@ -909,7 +909,7 @@ module ActiveRecord
909
909
 
910
910
  where_values.reject! do |rel|
911
911
  case rel
912
- when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThanOrEqual
912
+ when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
913
913
  subrelation = (rel.left.kind_of?(Arel::Attributes::Attribute) ? rel.left : rel.right)
914
914
  subrelation.name == target_value
915
915
  end
@@ -965,12 +965,9 @@ module ActiveRecord
965
965
 
966
966
  def create_binds(opts)
967
967
  bindable, non_binds = opts.partition do |column, value|
968
- case value
969
- when String, Integer, ActiveRecord::StatementCache::Substitute
970
- @klass.columns_hash.include? column.to_s
971
- else
972
- false
973
- end
968
+ PredicateBuilder.can_be_bound?(value) &&
969
+ @klass.columns_hash.include?(column.to_s) &&
970
+ !@klass.reflect_on_aggregation(column)
974
971
  end
975
972
 
976
973
  association_binds, non_binds = non_binds.partition do |column, value|
@@ -980,6 +977,8 @@ module ActiveRecord
980
977
  new_opts = {}
981
978
  binds = []
982
979
 
980
+ connection = self.connection
981
+
983
982
  bindable.each do |(column,value)|
984
983
  binds.push [@klass.columns_hash[column.to_s], value]
985
984
  new_opts[column] = connection.substitute_at(column)
@@ -1064,15 +1063,13 @@ module ActiveRecord
1064
1063
  end
1065
1064
 
1066
1065
  def arel_columns(columns)
1067
- if from_value
1068
- columns
1069
- else
1070
- columns.map do |field|
1071
- if (Symbol === field || String === field) && columns_hash.key?(field.to_s)
1072
- arel_table[field]
1073
- else
1074
- field
1075
- end
1066
+ columns.map do |field|
1067
+ if (Symbol === field || String === field) && columns_hash.key?(field.to_s) && !from_value
1068
+ arel_table[field]
1069
+ elsif Symbol === field
1070
+ connection.quote_table_name(field.to_s)
1071
+ else
1072
+ field
1076
1073
  end
1077
1074
  end
1078
1075
  end
@@ -197,7 +197,7 @@ module ActiveRecord
197
197
  load_schema_current(format, file)
198
198
  end
199
199
 
200
- def schema_file(format = ActiveSupport::Base.schema_format)
200
+ def schema_file(format = ActiveRecord::Base.schema_format)
201
201
  case format
202
202
  when :ruby
203
203
  File.join(db_dir, "schema.rb")
@@ -311,7 +311,7 @@ module ActiveRecord
311
311
  # Ensure that it is not called if the object was never persisted (failed create),
312
312
  # but call it after the commit of a destroyed object.
313
313
  def committed!(should_run_callbacks = true) #:nodoc:
314
- _run_commit_callbacks if should_run_callbacks && destroyed? || persisted?
314
+ run_callbacks(:commit) if should_run_callbacks && destroyed? || persisted?
315
315
  ensure
316
316
  force_clear_transaction_record_state
317
317
  end
@@ -319,7 +319,7 @@ module ActiveRecord
319
319
  # Call the +after_rollback+ callbacks. The +force_restore_state+ argument indicates if the record
320
320
  # state should be rolled back to the beginning or just to the last savepoint.
321
321
  def rolledback!(force_restore_state = false, should_run_callbacks = true) #:nodoc:
322
- _run_rollback_callbacks if should_run_callbacks
322
+ run_callbacks(:rollback) if should_run_callbacks
323
323
  ensure
324
324
  restore_transaction_record_state(force_restore_state)
325
325
  clear_transaction_record_state
@@ -328,9 +328,13 @@ module ActiveRecord
328
328
  # Add the record to the current transaction so that the +after_rollback+ and +after_commit+ callbacks
329
329
  # can be called.
330
330
  def add_to_transaction
331
- if self.class.connection.add_transaction_record(self)
332
- remember_transaction_record_state
331
+ if has_transactional_callbacks?
332
+ self.class.connection.add_transaction_record(self)
333
+ else
334
+ sync_with_transaction_state
335
+ set_transaction_state(self.class.connection.transaction_state)
333
336
  end
337
+ remember_transaction_record_state
334
338
  end
335
339
 
336
340
  # Executes +method+ within a transaction and captures its return value as a
@@ -385,10 +389,14 @@ module ActiveRecord
385
389
  transaction_level = (@_start_transaction_state[:level] || 0) - 1
386
390
  if transaction_level < 1 || force
387
391
  restore_state = @_start_transaction_state
388
- thaw unless restore_state[:frozen?]
392
+ thaw
389
393
  @new_record = restore_state[:new_record]
390
394
  @destroyed = restore_state[:destroyed]
391
- write_attribute(self.class.primary_key, restore_state[:id]) if self.class.primary_key
395
+ pk = self.class.primary_key
396
+ if pk && read_attribute(pk) != restore_state[:id]
397
+ write_attribute(pk, restore_state[:id])
398
+ end
399
+ freeze if restore_state[:frozen?]
392
400
  end
393
401
  end
394
402
  end
@@ -16,6 +16,7 @@ module ActiveRecord
16
16
  if !ConnectionAdapters::Column::FALSE_VALUES.include?(value)
17
17
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
18
18
  You attempted to assign a value which is not explicitly `true` or `false`
19
+ (#{value.inspect})
19
20
  to a boolean column. Currently this value casts to `false`. This will
20
21
  change to match Ruby's semantics, and will cast to `true` in Rails 5.
21
22
  If you would like to maintain the current behavior, you should
@@ -1,12 +1,18 @@
1
1
  module ActiveRecord
2
2
  module Type
3
3
  class HashLookupTypeMap < TypeMap # :nodoc:
4
- delegate :key?, to: :@mapping
5
-
6
4
  def alias_type(type, alias_type)
7
5
  register_type(type) { |_, *args| lookup(alias_type, *args) }
8
6
  end
9
7
 
8
+ def key?(key)
9
+ @mapping.key?(key)
10
+ end
11
+
12
+ def keys
13
+ @mapping.keys
14
+ end
15
+
10
16
  private
11
17
 
12
18
  def perform_fetch(type, *args, &block)
@@ -27,9 +27,15 @@ module ActiveRecord
27
27
  end
28
28
  end
29
29
 
30
+ def inspect
31
+ Kernel.instance_method(:inspect).bind(self).call
32
+ end
33
+
30
34
  def changed_in_place?(raw_old_value, value)
31
35
  return false if value.nil?
32
- subtype.changed_in_place?(raw_old_value, type_cast_for_database(value))
36
+ raw_new_value = type_cast_for_database(value)
37
+ raw_old_value.nil? != raw_new_value.nil? ||
38
+ subtype.changed_in_place?(raw_old_value, raw_new_value)
33
39
  end
34
40
 
35
41
  def accessor
@@ -15,11 +15,15 @@ module ActiveRecord
15
15
  table = finder_class.arel_table
16
16
  value = map_enum_attribute(finder_class, attribute, value)
17
17
 
18
- relation = build_relation(finder_class, table, attribute, value)
19
- relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id)) if record.persisted?
20
- relation = scope_relation(record, table, relation)
21
- relation = finder_class.unscoped.where(relation)
22
- relation = relation.merge(options[:conditions]) if options[:conditions]
18
+ begin
19
+ relation = build_relation(finder_class, table, attribute, value)
20
+ relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id)) if record.persisted?
21
+ relation = scope_relation(record, table, relation)
22
+ relation = finder_class.unscoped.where(relation)
23
+ relation = relation.merge(options[:conditions]) if options[:conditions]
24
+ rescue RangeError
25
+ relation = finder_class.none
26
+ end
23
27
 
24
28
  if relation.exists?
25
29
  error_options = options.except(:case_sensitive, :scope, :conditions)
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: 4.2.2
4
+ version: 4.2.3.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: 2015-06-16 00:00:00.000000000 Z
11
+ date: 2015-06-22 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: 4.2.2
19
+ version: 4.2.3.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: 4.2.2
26
+ version: 4.2.3.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: 4.2.2
33
+ version: 4.2.3.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: 4.2.2
40
+ version: 4.2.3.rc1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: arel
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -298,9 +298,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
298
298
  version: 1.9.3
299
299
  required_rubygems_version: !ruby/object:Gem::Requirement
300
300
  requirements:
301
- - - ">="
301
+ - - ">"
302
302
  - !ruby/object:Gem::Version
303
- version: '0'
303
+ version: 1.3.1
304
304
  requirements: []
305
305
  rubyforge_project:
306
306
  rubygems_version: 2.4.5