activerecord 4.2.0 → 4.2.1.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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +206 -1
  3. data/lib/active_record/associations.rb +4 -3
  4. data/lib/active_record/associations/belongs_to_association.rb +9 -5
  5. data/lib/active_record/associations/builder/collection_association.rb +5 -1
  6. data/lib/active_record/associations/collection_association.rb +17 -2
  7. data/lib/active_record/associations/collection_proxy.rb +5 -0
  8. data/lib/active_record/associations/foreign_association.rb +11 -0
  9. data/lib/active_record/associations/has_many_association.rb +22 -14
  10. data/lib/active_record/associations/has_many_through_association.rb +2 -2
  11. data/lib/active_record/associations/has_one_association.rb +1 -0
  12. data/lib/active_record/associations/through_association.rb +11 -0
  13. data/lib/active_record/attribute.rb +15 -1
  14. data/lib/active_record/attribute_methods/before_type_cast.rb +5 -0
  15. data/lib/active_record/attribute_methods/dirty.rb +7 -3
  16. data/lib/active_record/attribute_methods/time_zone_conversion.rb +5 -1
  17. data/lib/active_record/attribute_set/builder.rb +11 -1
  18. data/lib/active_record/attributes.rb +7 -0
  19. data/lib/active_record/autosave_association.rb +23 -8
  20. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +7 -5
  21. data/lib/active_record/connection_adapters/abstract/database_statements.rb +12 -1
  22. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  23. data/lib/active_record/connection_adapters/abstract/savepoints.rb +1 -1
  24. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +25 -7
  25. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +38 -6
  26. data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -1
  27. data/lib/active_record/connection_adapters/abstract_adapter.rb +13 -6
  28. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +23 -1
  29. data/lib/active_record/connection_adapters/column.rb +1 -1
  30. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -1
  31. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -1
  32. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -0
  33. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -0
  34. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -1
  35. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -0
  36. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +3 -3
  37. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +6 -7
  38. data/lib/active_record/connection_adapters/postgresql_adapter.rb +3 -3
  39. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +10 -16
  40. data/lib/active_record/connection_handling.rb +1 -1
  41. data/lib/active_record/core.rb +13 -7
  42. data/lib/active_record/counter_cache.rb +1 -1
  43. data/lib/active_record/fixtures.rb +1 -1
  44. data/lib/active_record/gem_version.rb +2 -2
  45. data/lib/active_record/locking/optimistic.rb +16 -14
  46. data/lib/active_record/migration.rb +1 -1
  47. data/lib/active_record/nested_attributes.rb +1 -1
  48. data/lib/active_record/no_touching.rb +1 -1
  49. data/lib/active_record/persistence.rb +2 -1
  50. data/lib/active_record/railties/databases.rake +2 -2
  51. data/lib/active_record/reflection.rb +1 -1
  52. data/lib/active_record/relation.rb +1 -1
  53. data/lib/active_record/relation/finder_methods.rb +1 -1
  54. data/lib/active_record/relation/predicate_builder.rb +15 -0
  55. data/lib/active_record/relation/predicate_builder/array_handler.rb +1 -1
  56. data/lib/active_record/relation/query_methods.rb +19 -18
  57. data/lib/active_record/schema_dumper.rb +1 -1
  58. data/lib/active_record/transactions.rb +6 -8
  59. data/lib/active_record/type/date_time.rb +14 -3
  60. data/lib/active_record/type/decimal.rb +9 -1
  61. data/lib/active_record/type/integer.rb +9 -5
  62. data/lib/active_record/type/numeric.rb +1 -1
  63. data/lib/active_record/type/serialized.rb +1 -1
  64. data/lib/active_record/type/string.rb +4 -0
  65. data/lib/active_record/type/value.rb +4 -0
  66. data/lib/active_record/validations/uniqueness.rb +1 -1
  67. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -3
  68. data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -6
  69. metadata +10 -9
@@ -39,7 +39,7 @@ module ActiveRecord
39
39
 
40
40
  class PendingMigrationError < MigrationError#:nodoc:
41
41
  def initialize
42
- if defined?(Rails)
42
+ if defined?(Rails.env)
43
43
  super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate RAILS_ENV=#{::Rails.env}")
44
44
  else
45
45
  super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate")
@@ -307,7 +307,7 @@ module ActiveRecord
307
307
  attr_names.each do |association_name|
308
308
  if reflection = _reflect_on_association(association_name)
309
309
  reflection.autosave = true
310
- add_autosave_association_callbacks(reflection)
310
+ define_autosave_validation_callbacks(reflection)
311
311
 
312
312
  nested_attributes_options = self.nested_attributes_options.dup
313
313
  nested_attributes_options[association_name.to_sym] = options
@@ -45,7 +45,7 @@ module ActiveRecord
45
45
  NoTouching.applied_to?(self.class)
46
46
  end
47
47
 
48
- def touch(*)
48
+ def touch(*) # :nodoc:
49
49
  super unless no_touching?
50
50
  end
51
51
  end
@@ -197,7 +197,8 @@ module ActiveRecord
197
197
  def becomes(klass)
198
198
  became = klass.new
199
199
  became.instance_variable_set("@attributes", @attributes)
200
- became.instance_variable_set("@changed_attributes", @changed_attributes) if defined?(@changed_attributes)
200
+ changed_attributes = @changed_attributes if defined?(@changed_attributes)
201
+ became.instance_variable_set("@changed_attributes", changed_attributes || {})
201
202
  became.instance_variable_set("@new_record", new_record?)
202
203
  became.instance_variable_set("@destroyed", destroyed?)
203
204
  became.instance_variable_set("@errors", errors)
@@ -240,7 +240,7 @@ db_namespace = namespace :db do
240
240
  end
241
241
 
242
242
  desc 'Load a schema.rb file into the database'
243
- task :load => [:environment, :load_config] do
243
+ task :load => [:load_config] do
244
244
  ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV['SCHEMA'])
245
245
  end
246
246
 
@@ -286,7 +286,7 @@ db_namespace = namespace :db do
286
286
  end
287
287
 
288
288
  desc "Recreate the databases from the structure.sql file"
289
- task :load => [:environment, :load_config] do
289
+ task :load => [:load_config] do
290
290
  ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV['DB_STRUCTURE'])
291
291
  end
292
292
 
@@ -499,7 +499,7 @@ module ActiveRecord
499
499
  # returns either nil or the inverse association name that it finds.
500
500
  def automatic_inverse_of
501
501
  if can_find_inverse_of_automatically?(self)
502
- inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name).to_sym
502
+ inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym
503
503
 
504
504
  begin
505
505
  reflection = klass._reflect_on_association(inverse_name)
@@ -568,7 +568,7 @@ module ActiveRecord
568
568
  [name, binds.fetch(name.to_s) {
569
569
  case where.right
570
570
  when Array then where.right.map(&:val)
571
- else
571
+ when Arel::Nodes::Casted
572
572
  where.right.val
573
573
  end
574
574
  }]
@@ -307,7 +307,7 @@ module ActiveRecord
307
307
  relation = relation.where(conditions)
308
308
  else
309
309
  unless conditions == :none
310
- relation = where(primary_key => conditions)
310
+ relation = relation.where(primary_key => conditions)
311
311
  end
312
312
  end
313
313
 
@@ -61,6 +61,8 @@ module ActiveRecord
61
61
  end
62
62
 
63
63
  column = reflection.foreign_key
64
+ primary_key = reflection.association_primary_key(base_class)
65
+ value = convert_value_to_association_ids(value, primary_key)
64
66
  end
65
67
 
66
68
  queries << build(table[column], value)
@@ -122,5 +124,18 @@ module ActiveRecord
122
124
  @handlers.detect { |klass, _| klass === object }.last
123
125
  end
124
126
  private_class_method :handler_for
127
+
128
+ def self.convert_value_to_association_ids(value, primary_key)
129
+ case value
130
+ when Relation
131
+ value.select(primary_key)
132
+ when Array
133
+ value.map { |v| convert_value_to_association_ids(v, primary_key) }
134
+ when Base
135
+ value._read_attribute(primary_key)
136
+ else
137
+ value
138
+ end
139
+ end
125
140
  end
126
141
  end
@@ -37,7 +37,7 @@ module ActiveRecord
37
37
  array_predicates.inject { |composite, predicate| composite.or(predicate) }
38
38
  end
39
39
 
40
- module NullPredicate
40
+ module NullPredicate # :nodoc:
41
41
  def self.or(other)
42
42
  other
43
43
  end
@@ -757,6 +757,9 @@ module ActiveRecord
757
757
 
758
758
  def from!(value, subquery_name = nil) # :nodoc:
759
759
  self.from_value = [value, subquery_name]
760
+ if value.is_a? Relation
761
+ self.bind_values = value.arel.bind_values + value.bind_values + bind_values
762
+ end
760
763
  self
761
764
  end
762
765
 
@@ -868,12 +871,11 @@ module ActiveRecord
868
871
 
869
872
  arel.take(connection.sanitize_limit(limit_value)) if limit_value
870
873
  arel.skip(offset_value.to_i) if offset_value
871
-
872
- arel.group(*group_values.uniq.reject(&:blank?)) unless group_values.empty?
874
+ arel.group(*arel_columns(group_values.uniq.reject(&:blank?))) unless group_values.empty?
873
875
 
874
876
  build_order(arel)
875
877
 
876
- build_select(arel, select_values.uniq)
878
+ build_select(arel)
877
879
 
878
880
  arel.distinct(distinct_value)
879
881
  arel.from(build_from) if from_value
@@ -1006,7 +1008,6 @@ module ActiveRecord
1006
1008
  case opts
1007
1009
  when Relation
1008
1010
  name ||= 'subquery'
1009
- self.bind_values = opts.bind_values + self.bind_values
1010
1011
  opts.arel.as(name.to_s)
1011
1012
  else
1012
1013
  opts
@@ -1054,22 +1055,24 @@ module ActiveRecord
1054
1055
  manager
1055
1056
  end
1056
1057
 
1057
- def build_select(arel, selects)
1058
- if !selects.empty?
1059
- expanded_select = selects.map do |field|
1060
- if (Symbol === field || String === field) && columns_hash.key?(field.to_s)
1061
- arel_table[field]
1062
- else
1063
- field
1064
- end
1065
- end
1066
-
1067
- arel.project(*expanded_select)
1058
+ def build_select(arel)
1059
+ if select_values.any?
1060
+ arel.project(*arel_columns(select_values.uniq))
1068
1061
  else
1069
1062
  arel.project(@klass.arel_table[Arel.star])
1070
1063
  end
1071
1064
  end
1072
1065
 
1066
+ def arel_columns(columns)
1067
+ columns.map do |field|
1068
+ if (Symbol === field || String === field) && columns_hash.key?(field.to_s)
1069
+ arel_table[field]
1070
+ else
1071
+ field
1072
+ end
1073
+ end
1074
+ end
1075
+
1073
1076
  def reverse_sql_order(order_query)
1074
1077
  order_query = ["#{quoted_table_name}.#{quoted_primary_key} ASC"] if order_query.empty?
1075
1078
 
@@ -1159,13 +1162,11 @@ module ActiveRecord
1159
1162
  end
1160
1163
  end
1161
1164
 
1162
- # This function is recursive just for better readablity.
1163
- # #where argument doesn't support more than one level nested hash in real world.
1164
1165
  def add_relations_to_bind_values(attributes)
1165
1166
  if attributes.is_a?(Hash)
1166
1167
  attributes.each_value do |value|
1167
1168
  if value.is_a?(ActiveRecord::Relation)
1168
- self.bind_values += value.bind_values
1169
+ self.bind_values += value.arel.bind_values + value.bind_values
1169
1170
  else
1170
1171
  add_relations_to_bind_values(value)
1171
1172
  end
@@ -122,7 +122,7 @@ HEADER
122
122
  tbl.print ", id: :bigserial"
123
123
  elsif pkcol.sql_type == 'uuid'
124
124
  tbl.print ", id: :uuid"
125
- tbl.print %Q(, default: "#{pkcol.default_function}") if pkcol.default_function
125
+ tbl.print %Q(, default: #{pkcol.default_function.inspect})
126
126
  end
127
127
  else
128
128
  tbl.print ", id: false"
@@ -360,14 +360,12 @@ module ActiveRecord
360
360
  # Save the new record state and id of a record so it can be restored later if a transaction fails.
361
361
  def remember_transaction_record_state #:nodoc:
362
362
  @_start_transaction_state[:id] = id
363
- unless @_start_transaction_state.include?(:new_record)
364
- @_start_transaction_state[:new_record] = @new_record
365
- end
366
- unless @_start_transaction_state.include?(:destroyed)
367
- @_start_transaction_state[:destroyed] = @destroyed
368
- end
363
+ @_start_transaction_state.reverse_merge!(
364
+ new_record: @new_record,
365
+ destroyed: @destroyed,
366
+ frozen?: frozen?,
367
+ )
369
368
  @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
370
- @_start_transaction_state[:frozen?] = frozen?
371
369
  end
372
370
 
373
371
  # Clear the new record state and id of a record.
@@ -390,7 +388,7 @@ module ActiveRecord
390
388
  thaw unless restore_state[:frozen?]
391
389
  @new_record = restore_state[:new_record]
392
390
  @destroyed = restore_state[:destroyed]
393
- write_attribute(self.class.primary_key, restore_state[:id])
391
+ write_attribute(self.class.primary_key, restore_state[:id]) if self.class.primary_key
394
392
  end
395
393
  end
396
394
  end
@@ -8,17 +8,28 @@ module ActiveRecord
8
8
  end
9
9
 
10
10
  def type_cast_for_database(value)
11
+ return super unless value.acts_like?(:time)
12
+
11
13
  zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
12
14
 
13
- if value.acts_like?(:time)
14
- value.send(zone_conversion_method)
15
+ if value.respond_to?(zone_conversion_method)
16
+ value = value.send(zone_conversion_method)
17
+ end
18
+
19
+ return value unless has_precision?
20
+
21
+ result = value.to_s(:db)
22
+ if value.respond_to?(:usec) && (1..6).cover?(precision)
23
+ "#{result}.#{sprintf("%0#{precision}d", value.usec / 10 ** (6 - precision))}"
15
24
  else
16
- super
25
+ result
17
26
  end
18
27
  end
19
28
 
20
29
  private
21
30
 
31
+ alias has_precision? precision
32
+
22
33
  def cast_value(string)
23
34
  return string unless string.is_a?(::String)
24
35
  return if string.empty?
@@ -16,7 +16,7 @@ module ActiveRecord
16
16
  def cast_value(value)
17
17
  case value
18
18
  when ::Float
19
- BigDecimal(value, float_precision)
19
+ convert_float_to_big_decimal(value)
20
20
  when ::Numeric, ::String
21
21
  BigDecimal(value, precision.to_i)
22
22
  else
@@ -28,6 +28,14 @@ module ActiveRecord
28
28
  end
29
29
  end
30
30
 
31
+ def convert_float_to_big_decimal(value)
32
+ if precision
33
+ BigDecimal(value, float_precision)
34
+ else
35
+ value.to_d
36
+ end
37
+ end
38
+
31
39
  def float_precision
32
40
  if precision.to_i > ::Float::DIG + 1
33
41
  ::Float::DIG + 1
@@ -12,13 +12,19 @@ module ActiveRecord
12
12
  :integer
13
13
  end
14
14
 
15
- alias type_cast_for_database type_cast
16
-
17
15
  def type_cast_from_database(value)
18
16
  return if value.nil?
19
17
  value.to_i
20
18
  end
21
19
 
20
+ def type_cast_for_database(value)
21
+ result = type_cast(value)
22
+ if result
23
+ ensure_in_range(result)
24
+ end
25
+ result
26
+ end
27
+
22
28
  protected
23
29
 
24
30
  attr_reader :range
@@ -30,9 +36,7 @@ module ActiveRecord
30
36
  when true then 1
31
37
  when false then 0
32
38
  else
33
- result = value.to_i rescue nil
34
- ensure_in_range(result) if result
35
- result
39
+ value.to_i rescue nil
36
40
  end
37
41
  end
38
42
 
@@ -29,7 +29,7 @@ module ActiveRecord
29
29
  # 'wibble'.to_i will give zero, we want to make sure
30
30
  # that we aren't marking int zero to string zero as
31
31
  # changed.
32
- value.to_s !~ /\A\d+\.?\d*\z/
32
+ value.to_s !~ /\A-?\d+\.?\d*\z/
33
33
  end
34
34
  end
35
35
  end
@@ -29,7 +29,7 @@ module ActiveRecord
29
29
 
30
30
  def changed_in_place?(raw_old_value, value)
31
31
  return false if value.nil?
32
- subtype.changed_in_place?(raw_old_value, coder.dump(value))
32
+ subtype.changed_in_place?(raw_old_value, type_cast_for_database(value))
33
33
  end
34
34
 
35
35
  def accessor
@@ -21,6 +21,10 @@ module ActiveRecord
21
21
  end
22
22
  end
23
23
 
24
+ def text?
25
+ true
26
+ end
27
+
24
28
  private
25
29
 
26
30
  def cast_value(value)
@@ -50,6 +50,10 @@ module ActiveRecord
50
50
 
51
51
  # These predicates are not documented, as I need to look further into
52
52
  # their use, and see if they can be removed entirely.
53
+ def text? # :nodoc:
54
+ false
55
+ end
56
+
53
57
  def number? # :nodoc:
54
58
  false
55
59
  end
@@ -65,7 +65,7 @@ module ActiveRecord
65
65
  value = value.to_s[0, column.limit]
66
66
  end
67
67
 
68
- if !options[:case_sensitive] && value.is_a?(String)
68
+ if !options[:case_sensitive] && value && column.text?
69
69
  # will use SQL LOWER function before comparison, unless it detects a case insensitive collation
70
70
  klass.connection.case_insensitive_comparison(table, attribute, column, value)
71
71
  else
@@ -14,9 +14,6 @@ class <%= migration_class_name %> < ActiveRecord::Migration
14
14
  end
15
15
  <% attributes_with_index.each do |attribute| -%>
16
16
  add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
17
- <% end -%>
18
- <% attributes.select(&:reference?).reject(&:polymorphic?).each do |attribute| -%>
19
- add_foreign_key :<%= table_name %>, :<%= attribute.name.pluralize %>
20
17
  <% end -%>
21
18
  end
22
19
  end
@@ -4,9 +4,6 @@ class <%= migration_class_name %> < ActiveRecord::Migration
4
4
  <% attributes.each do |attribute| -%>
5
5
  <%- if attribute.reference? -%>
6
6
  add_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %>
7
- <%- unless attribute.polymorphic? -%>
8
- add_foreign_key :<%= table_name %>, :<%= attribute.name.pluralize %>
9
- <%- end -%>
10
7
  <%- else -%>
11
8
  add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %>
12
9
  <%- if attribute.has_index? -%>
@@ -29,9 +26,6 @@ class <%= migration_class_name %> < ActiveRecord::Migration
29
26
  <%- if migration_action -%>
30
27
  <%- if attribute.reference? -%>
31
28
  remove_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %>
32
- <%- unless attribute.polymorphic? -%>
33
- remove_foreign_key :<%= table_name %>, :<%= attribute.name.pluralize %>
34
- <%- end -%>
35
29
  <%- else -%>
36
30
  <%- if attribute.has_index? -%>
37
31
  remove_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
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.0
4
+ version: 4.2.1.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: 2014-12-20 00:00:00.000000000 Z
11
+ date: 2015-02-20 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.0
19
+ version: 4.2.1.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.0
26
+ version: 4.2.1.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.0
33
+ version: 4.2.1.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.0
40
+ version: 4.2.1.rc1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: arel
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -84,6 +84,7 @@ files:
84
84
  - lib/active_record/associations/builder/singular_association.rb
85
85
  - lib/active_record/associations/collection_association.rb
86
86
  - lib/active_record/associations/collection_proxy.rb
87
+ - lib/active_record/associations/foreign_association.rb
87
88
  - lib/active_record/associations/has_many_association.rb
88
89
  - lib/active_record/associations/has_many_through_association.rb
89
90
  - lib/active_record/associations/has_one_association.rb
@@ -297,12 +298,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
297
298
  version: 1.9.3
298
299
  required_rubygems_version: !ruby/object:Gem::Requirement
299
300
  requirements:
300
- - - ">="
301
+ - - ">"
301
302
  - !ruby/object:Gem::Version
302
- version: '0'
303
+ version: 1.3.1
303
304
  requirements: []
304
305
  rubyforge_project:
305
- rubygems_version: 2.2.2
306
+ rubygems_version: 2.4.5
306
307
  signing_key:
307
308
  specification_version: 4
308
309
  summary: Object-relational mapper framework (part of Rails).