activerecord 4.2.11.3 → 5.0.7.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1638 -1132
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -8
- data/examples/performance.rb +2 -3
- data/examples/simple.rb +0 -1
- data/lib/active_record.rb +7 -2
- data/lib/active_record/aggregations.rb +34 -21
- data/lib/active_record/association_relation.rb +7 -4
- data/lib/active_record/associations.rb +347 -218
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +22 -10
- data/lib/active_record/associations/association_scope.rb +75 -104
- data/lib/active_record/associations/belongs_to_association.rb +21 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +43 -18
- data/lib/active_record/associations/builder/collection_association.rb +7 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +16 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +11 -6
- data/lib/active_record/associations/builder/singular_association.rb +13 -11
- data/lib/active_record/associations/collection_association.rb +85 -69
- data/lib/active_record/associations/collection_proxy.rb +104 -46
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +21 -78
- data/lib/active_record/associations/has_many_through_association.rb +6 -47
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency.rb +38 -22
- data/lib/active_record/associations/join_dependency/join_association.rb +15 -14
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +14 -4
- data/lib/active_record/associations/preloader/association.rb +52 -71
- data/lib/active_record/associations/preloader/collection_association.rb +0 -7
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/singular_association.rb +0 -1
- data/lib/active_record/associations/preloader/through_association.rb +36 -17
- data/lib/active_record/associations/singular_association.rb +13 -1
- data/lib/active_record/associations/through_association.rb +12 -4
- data/lib/active_record/attribute.rb +69 -19
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute_assignment.rb +19 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods.rb +69 -44
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +16 -3
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +31 -59
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
- data/lib/active_record/attribute_methods/write.rb +13 -37
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set.rb +32 -3
- data/lib/active_record/attribute_set/builder.rb +42 -16
- data/lib/active_record/attributes.rb +199 -81
- data/lib/active_record/autosave_association.rb +54 -17
- data/lib/active_record/base.rb +32 -23
- data/lib/active_record/callbacks.rb +39 -43
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +467 -189
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +66 -62
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +39 -4
- data/lib/active_record/connection_adapters/abstract/quoting.rb +86 -13
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -188
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +407 -156
- data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +177 -71
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +433 -399
- data/lib/active_record/connection_adapters/column.rb +28 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +108 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +25 -166
- data/lib/active_record/connection_adapters/postgresql/column.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -72
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +37 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +13 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +56 -19
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +250 -154
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +264 -170
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +151 -194
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +37 -14
- data/lib/active_record/core.rb +92 -108
- data/lib/active_record/counter_cache.rb +13 -24
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +116 -76
- data/lib/active_record/errors.rb +87 -48
- data/lib/active_record/explain.rb +20 -9
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +26 -5
- data/lib/active_record/fixtures.rb +77 -41
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +32 -40
- data/lib/active_record/integration.rb +17 -14
- data/lib/active_record/internal_metadata.rb +56 -0
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +15 -15
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +48 -24
- data/lib/active_record/migration.rb +362 -111
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/model_schema.rb +270 -73
- data/lib/active_record/nested_attributes.rb +58 -29
- data/lib/active_record/no_touching.rb +4 -0
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +152 -90
- data/lib/active_record/query_cache.rb +18 -23
- data/lib/active_record/querying.rb +12 -11
- data/lib/active_record/railtie.rb +23 -16
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +52 -41
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +302 -115
- data/lib/active_record/relation.rb +187 -120
- data/lib/active_record/relation/batches.rb +141 -36
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/calculations.rb +92 -117
- data/lib/active_record/relation/delegation.rb +8 -20
- data/lib/active_record/relation/finder_methods.rb +173 -89
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +16 -42
- data/lib/active_record/relation/predicate_builder.rb +120 -107
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +308 -244
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -7
- data/lib/active_record/relation/where_clause.rb +174 -0
- data/lib/active_record/relation/where_clause_factory.rb +38 -0
- data/lib/active_record/result.rb +11 -4
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +105 -66
- data/lib/active_record/schema.rb +26 -22
- data/lib/active_record/schema_dumper.rb +54 -37
- data/lib/active_record/schema_migration.rb +11 -14
- data/lib/active_record/scoping.rb +34 -16
- data/lib/active_record/scoping/default.rb +28 -10
- data/lib/active_record/scoping/named.rb +59 -26
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +3 -5
- data/lib/active_record/statement_cache.rb +17 -15
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +58 -0
- data/lib/active_record/table_metadata.rb +69 -0
- data/lib/active_record/tasks/database_tasks.rb +66 -49
- data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
- data/lib/active_record/tasks/postgresql_database_tasks.rb +12 -3
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +20 -9
- data/lib/active_record/touch_later.rb +63 -0
- data/lib/active_record/transactions.rb +139 -57
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -45
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +33 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +15 -14
- data/lib/active_record/type/time.rb +10 -16
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record/validations/absence.rb +23 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +24 -0
- data/lib/active_record/validations/presence.rb +11 -12
- data/lib/active_record/validations/uniqueness.rb +33 -33
- data/lib/rails/generators/active_record/migration.rb +15 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +33 -16
- data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +58 -34
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -110
@@ -19,10 +19,10 @@ module ActiveRecord
|
|
19
19
|
if Numeric === value || value !~ /[^0-9]/
|
20
20
|
!value.to_i.zero?
|
21
21
|
else
|
22
|
-
return false if
|
22
|
+
return false if ActiveModel::Type::Boolean::FALSE_VALUES.include?(value)
|
23
23
|
!value.blank?
|
24
24
|
end
|
25
|
-
elsif
|
25
|
+
elsif value.respond_to?(:zero?)
|
26
26
|
!value.zero?
|
27
27
|
else
|
28
28
|
!value.blank?
|
@@ -1,10 +1,11 @@
|
|
1
|
-
require 'active_support/core_ext/module/method_transplanting'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module AttributeMethods
|
5
3
|
module Read
|
6
|
-
|
7
|
-
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
protected
|
8
|
+
|
8
9
|
# We want to generate the methods via module_eval rather than
|
9
10
|
# define_method, because define_method is slower on dispatch.
|
10
11
|
# Evaluating many similar methods may use more memory as the instruction
|
@@ -23,81 +24,52 @@ module ActiveRecord
|
|
23
24
|
# to allocate an object on each call to the attribute method.
|
24
25
|
# Making it frozen means that it doesn't get duped when used to
|
25
26
|
# key the @attributes in read_attribute.
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{const_name}
|
30
|
-
_read_attribute(name) { |n| missing_attribute(n, caller) }
|
31
|
-
end
|
32
|
-
EOMETHOD
|
33
|
-
end
|
34
|
-
}.new
|
35
|
-
|
36
|
-
extend ActiveSupport::Concern
|
37
|
-
|
38
|
-
module ClassMethods
|
39
|
-
[:cache_attributes, :cached_attributes, :cache_attribute?].each do |method_name|
|
40
|
-
define_method method_name do |*|
|
41
|
-
cached_attributes_deprecation_warning(method_name)
|
42
|
-
true
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
protected
|
47
|
-
|
48
|
-
def cached_attributes_deprecation_warning(method_name)
|
49
|
-
ActiveSupport::Deprecation.warn "Calling `#{method_name}` is no longer necessary. All attributes are cached."
|
50
|
-
end
|
51
|
-
|
52
|
-
if Module.methods_transplantable?
|
53
|
-
def define_method_attribute(name)
|
54
|
-
method = ReaderMethodCache[name]
|
55
|
-
generated_attribute_methods.module_eval { define_method name, method }
|
56
|
-
end
|
57
|
-
else
|
58
|
-
def define_method_attribute(name)
|
59
|
-
safe_name = name.unpack('h*').first
|
60
|
-
temp_method = "__temp__#{safe_name}"
|
27
|
+
def define_method_attribute(name)
|
28
|
+
safe_name = name.unpack('h*'.freeze).first
|
29
|
+
temp_method = "__temp__#{safe_name}"
|
61
30
|
|
62
|
-
|
31
|
+
ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
|
63
32
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
69
|
-
STR
|
70
|
-
|
71
|
-
generated_attribute_methods.module_eval do
|
72
|
-
alias_method name, temp_method
|
73
|
-
undef_method temp_method
|
33
|
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
34
|
+
def #{temp_method}
|
35
|
+
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
|
36
|
+
_read_attribute(name) { |n| missing_attribute(n, caller) }
|
74
37
|
end
|
38
|
+
STR
|
39
|
+
|
40
|
+
generated_attribute_methods.module_eval do
|
41
|
+
alias_method name, temp_method
|
42
|
+
undef_method temp_method
|
75
43
|
end
|
76
44
|
end
|
77
45
|
end
|
78
46
|
|
79
|
-
ID = 'id'.freeze
|
80
|
-
|
81
47
|
# Returns the value of the attribute identified by <tt>attr_name</tt> after
|
82
48
|
# it has been typecast (for example, "2004-12-12" in a date column is cast
|
83
49
|
# to a date object, like Date.new(2004, 12, 12)).
|
84
50
|
def read_attribute(attr_name, &block)
|
85
51
|
name = attr_name.to_s
|
86
|
-
name = self.class.primary_key if name ==
|
52
|
+
name = self.class.primary_key if name == "id".freeze && self.class.primary_key
|
87
53
|
_read_attribute(name, &block)
|
88
54
|
end
|
89
55
|
|
90
56
|
# This method exists to avoid the expensive primary_key check internally, without
|
91
57
|
# breaking compatibility with the read_attribute API
|
92
|
-
|
93
|
-
|
58
|
+
if defined?(JRUBY_VERSION)
|
59
|
+
# This form is significantly faster on JRuby, and this is one of our biggest hotspots.
|
60
|
+
# https://github.com/jruby/jruby/pull/2562
|
61
|
+
def _read_attribute(attr_name, &block) # :nodoc
|
62
|
+
@attributes.fetch_value(attr_name.to_s, &block)
|
63
|
+
end
|
64
|
+
else
|
65
|
+
def _read_attribute(attr_name) # :nodoc:
|
66
|
+
@attributes.fetch_value(attr_name.to_s) { |n| yield n if block_given? }
|
67
|
+
end
|
94
68
|
end
|
95
69
|
|
96
|
-
|
70
|
+
alias :attribute :_read_attribute
|
71
|
+
private :attribute
|
97
72
|
|
98
|
-
def attribute(attribute_name)
|
99
|
-
_read_attribute(attribute_name)
|
100
|
-
end
|
101
73
|
end
|
102
74
|
end
|
103
75
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/core_ext/string/filters'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module AttributeMethods
|
5
3
|
module Serialization
|
@@ -11,7 +9,19 @@ module ActiveRecord
|
|
11
9
|
# attribute using this method and it will be handled automatically. The
|
12
10
|
# serialization is done through YAML. If +class_name+ is specified, the
|
13
11
|
# serialized object must be of that class on assignment and retrieval.
|
14
|
-
# Otherwise
|
12
|
+
# Otherwise SerializationTypeMismatch will be raised.
|
13
|
+
#
|
14
|
+
# Empty objects as <tt>{}</tt>, in the case of +Hash+, or <tt>[]</tt>, in the case of
|
15
|
+
# +Array+, will always be persisted as null.
|
16
|
+
#
|
17
|
+
# Keep in mind that database adapters handle certain serialization tasks
|
18
|
+
# for you. For instance: +json+ and +jsonb+ types in PostgreSQL will be
|
19
|
+
# converted between JSON object/array syntax and Ruby +Hash+ or +Array+
|
20
|
+
# objects transparently. There is no need to use #serialize in this
|
21
|
+
# case.
|
22
|
+
#
|
23
|
+
# For more complex cases, such as conversion to or from your application
|
24
|
+
# domain objects, consider using the ActiveRecord::Attributes API.
|
15
25
|
#
|
16
26
|
# ==== Parameters
|
17
27
|
#
|
@@ -51,19 +61,6 @@ module ActiveRecord
|
|
51
61
|
Type::Serialized.new(type, coder)
|
52
62
|
end
|
53
63
|
end
|
54
|
-
|
55
|
-
def serialized_attributes
|
56
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
57
|
-
`serialized_attributes` is deprecated without replacement, and will
|
58
|
-
be removed in Rails 5.0.
|
59
|
-
MSG
|
60
|
-
|
61
|
-
@serialized_attributes ||= Hash[
|
62
|
-
columns.select { |t| t.cast_type.is_a?(Type::Serialized) }.map { |c|
|
63
|
-
[c.name, c.cast_type.coder]
|
64
|
-
}
|
65
|
-
]
|
66
|
-
end
|
67
64
|
end
|
68
65
|
end
|
69
66
|
end
|
@@ -1,32 +1,54 @@
|
|
1
|
+
require 'active_support/core_ext/string/strip'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module AttributeMethods
|
3
5
|
module TimeZoneConversion
|
4
6
|
class TimeZoneConverter < DelegateClass(Type::Value) # :nodoc:
|
5
|
-
|
6
|
-
|
7
|
-
def type_cast_from_database(value)
|
7
|
+
def deserialize(value)
|
8
8
|
convert_time_to_time_zone(super)
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
if value.
|
13
|
-
|
11
|
+
def cast(value)
|
12
|
+
return if value.nil?
|
13
|
+
|
14
|
+
if value.is_a?(Hash)
|
15
|
+
set_time_zone_without_conversion(super)
|
14
16
|
elsif value.respond_to?(:in_time_zone)
|
15
17
|
begin
|
16
|
-
value
|
18
|
+
super(user_input_in_time_zone(value)) || super
|
17
19
|
rescue ArgumentError
|
18
20
|
nil
|
19
21
|
end
|
22
|
+
else
|
23
|
+
map_avoiding_infinite_recursion(super) { |v| cast(v) }
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
27
|
+
private
|
28
|
+
|
23
29
|
def convert_time_to_time_zone(value)
|
24
|
-
if value.
|
25
|
-
|
26
|
-
|
30
|
+
return if value.nil?
|
31
|
+
|
32
|
+
if value.acts_like?(:time)
|
27
33
|
value.in_time_zone
|
28
|
-
|
34
|
+
elsif value.is_a?(::Float)
|
29
35
|
value
|
36
|
+
else
|
37
|
+
map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def set_time_zone_without_conversion(value)
|
42
|
+
::Time.zone.local_to_utc(value).in_time_zone if value
|
43
|
+
end
|
44
|
+
|
45
|
+
def map_avoiding_infinite_recursion(value)
|
46
|
+
map(value) do |v|
|
47
|
+
if value.equal?(v)
|
48
|
+
nil
|
49
|
+
else
|
50
|
+
yield(v)
|
51
|
+
end
|
30
52
|
end
|
31
53
|
end
|
32
54
|
end
|
@@ -39,6 +61,9 @@ module ActiveRecord
|
|
39
61
|
|
40
62
|
class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false
|
41
63
|
self.skip_time_zone_conversion_for_attributes = []
|
64
|
+
|
65
|
+
class_attribute :time_zone_aware_types, instance_writer: false
|
66
|
+
self.time_zone_aware_types = [:datetime, :not_explicitly_configured]
|
42
67
|
end
|
43
68
|
|
44
69
|
module ClassMethods
|
@@ -59,9 +84,31 @@ module ActiveRecord
|
|
59
84
|
end
|
60
85
|
|
61
86
|
def create_time_zone_conversion_attribute?(name, cast_type)
|
62
|
-
time_zone_aware_attributes &&
|
63
|
-
!self.skip_time_zone_conversion_for_attributes.include?(name.to_sym)
|
64
|
-
|
87
|
+
enabled_for_column = time_zone_aware_attributes &&
|
88
|
+
!self.skip_time_zone_conversion_for_attributes.include?(name.to_sym)
|
89
|
+
result = enabled_for_column &&
|
90
|
+
time_zone_aware_types.include?(cast_type.type)
|
91
|
+
|
92
|
+
if enabled_for_column &&
|
93
|
+
!result &&
|
94
|
+
cast_type.type == :time &&
|
95
|
+
time_zone_aware_types.include?(:not_explicitly_configured)
|
96
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
|
97
|
+
Time columns will become time zone aware in Rails 5.1. This
|
98
|
+
still causes `String`s to be parsed as if they were in `Time.zone`,
|
99
|
+
and `Time`s to be converted to `Time.zone`.
|
100
|
+
|
101
|
+
To keep the old behavior, you must add the following to your initializer:
|
102
|
+
|
103
|
+
config.active_record.time_zone_aware_types = [:datetime]
|
104
|
+
|
105
|
+
To use the new behavior, add the following:
|
106
|
+
|
107
|
+
config.active_record.time_zone_aware_types = [:datetime, :time]
|
108
|
+
MESSAGE
|
109
|
+
end
|
110
|
+
|
111
|
+
result
|
65
112
|
end
|
66
113
|
end
|
67
114
|
end
|
@@ -1,21 +1,6 @@
|
|
1
|
-
require 'active_support/core_ext/module/method_transplanting'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module AttributeMethods
|
5
3
|
module Write
|
6
|
-
WriterMethodCache = Class.new(AttributeMethodCache) {
|
7
|
-
private
|
8
|
-
|
9
|
-
def method_body(method_name, const_name)
|
10
|
-
<<-EOMETHOD
|
11
|
-
def #{method_name}(value)
|
12
|
-
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{const_name}
|
13
|
-
write_attribute(name, value)
|
14
|
-
end
|
15
|
-
EOMETHOD
|
16
|
-
end
|
17
|
-
}.new
|
18
|
-
|
19
4
|
extend ActiveSupport::Concern
|
20
5
|
|
21
6
|
included do
|
@@ -25,27 +10,18 @@ module ActiveRecord
|
|
25
10
|
module ClassMethods
|
26
11
|
protected
|
27
12
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
}
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
41
|
-
def __temp__#{safe_name}=(value)
|
42
|
-
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
|
43
|
-
write_attribute(name, value)
|
44
|
-
end
|
45
|
-
alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
|
46
|
-
undef_method :__temp__#{safe_name}=
|
47
|
-
STR
|
48
|
-
end
|
13
|
+
def define_method_attribute=(name)
|
14
|
+
safe_name = name.unpack('h*'.freeze).first
|
15
|
+
ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
|
16
|
+
|
17
|
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
18
|
+
def __temp__#{safe_name}=(value)
|
19
|
+
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
|
20
|
+
write_attribute(name, value)
|
21
|
+
end
|
22
|
+
alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
|
23
|
+
undef_method :__temp__#{safe_name}=
|
24
|
+
STR
|
49
25
|
end
|
50
26
|
end
|
51
27
|
|
@@ -56,7 +32,7 @@ module ActiveRecord
|
|
56
32
|
write_attribute_with_type_cast(attr_name, value, true)
|
57
33
|
end
|
58
34
|
|
59
|
-
def raw_write_attribute(attr_name, value)
|
35
|
+
def raw_write_attribute(attr_name, value) # :nodoc:
|
60
36
|
write_attribute_with_type_cast(attr_name, value, false)
|
61
37
|
end
|
62
38
|
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class AttributeMutationTracker # :nodoc:
|
3
|
+
def initialize(attributes)
|
4
|
+
@attributes = attributes
|
5
|
+
end
|
6
|
+
|
7
|
+
def changed_values
|
8
|
+
attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
|
9
|
+
if changed?(attr_name)
|
10
|
+
result[attr_name] = attributes[attr_name].original_value
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def changes
|
16
|
+
attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
|
17
|
+
if changed?(attr_name)
|
18
|
+
result[attr_name] = [attributes[attr_name].original_value, attributes.fetch_value(attr_name)]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def changed?(attr_name)
|
24
|
+
attr_name = attr_name.to_s
|
25
|
+
attributes[attr_name].changed?
|
26
|
+
end
|
27
|
+
|
28
|
+
def changed_in_place?(attr_name)
|
29
|
+
attributes[attr_name].changed_in_place?
|
30
|
+
end
|
31
|
+
|
32
|
+
def forget_change(attr_name)
|
33
|
+
attr_name = attr_name.to_s
|
34
|
+
attributes[attr_name] = attributes[attr_name].forgetting_assignment
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
attr_reader :attributes
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def attr_names
|
44
|
+
attributes.keys
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class NullMutationTracker # :nodoc:
|
49
|
+
include Singleton
|
50
|
+
|
51
|
+
def changed_values
|
52
|
+
{}
|
53
|
+
end
|
54
|
+
|
55
|
+
def changes
|
56
|
+
{}
|
57
|
+
end
|
58
|
+
|
59
|
+
def changed?(*)
|
60
|
+
false
|
61
|
+
end
|
62
|
+
|
63
|
+
def changed_in_place?(*)
|
64
|
+
false
|
65
|
+
end
|
66
|
+
|
67
|
+
def forget_change(*)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -2,6 +2,8 @@ require 'active_record/attribute_set/builder'
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
class AttributeSet # :nodoc:
|
5
|
+
delegate :fetch, :except, to: :attributes
|
6
|
+
|
5
7
|
def initialize(attributes)
|
6
8
|
@attributes = attributes
|
7
9
|
end
|
@@ -10,6 +12,10 @@ module ActiveRecord
|
|
10
12
|
attributes[name] || Attribute.null(name)
|
11
13
|
end
|
12
14
|
|
15
|
+
def []=(name, value)
|
16
|
+
attributes[name] = value
|
17
|
+
end
|
18
|
+
|
13
19
|
def values_before_type_cast
|
14
20
|
attributes.transform_values(&:value_before_type_cast)
|
15
21
|
end
|
@@ -24,11 +30,19 @@ module ActiveRecord
|
|
24
30
|
end
|
25
31
|
|
26
32
|
def keys
|
27
|
-
attributes.
|
33
|
+
attributes.each_key.select { |name| self[name].initialized? }
|
28
34
|
end
|
29
35
|
|
30
|
-
|
31
|
-
|
36
|
+
if defined?(JRUBY_VERSION)
|
37
|
+
# This form is significantly faster on JRuby, and this is one of our biggest hotspots.
|
38
|
+
# https://github.com/jruby/jruby/pull/2562
|
39
|
+
def fetch_value(name, &block)
|
40
|
+
self[name].value(&block)
|
41
|
+
end
|
42
|
+
else
|
43
|
+
def fetch_value(name)
|
44
|
+
self[name].value { |n| yield n if block_given? }
|
45
|
+
end
|
32
46
|
end
|
33
47
|
|
34
48
|
def write_from_database(name, value)
|
@@ -48,6 +62,12 @@ module ActiveRecord
|
|
48
62
|
super
|
49
63
|
end
|
50
64
|
|
65
|
+
def deep_dup
|
66
|
+
dup.tap do |copy|
|
67
|
+
copy.instance_variable_set(:@attributes, attributes.deep_dup)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
51
71
|
def initialize_dup(_)
|
52
72
|
@attributes = attributes.dup
|
53
73
|
super
|
@@ -64,6 +84,15 @@ module ActiveRecord
|
|
64
84
|
end
|
65
85
|
end
|
66
86
|
|
87
|
+
def accessed
|
88
|
+
attributes.select { |_, attr| attr.has_been_read? }.keys
|
89
|
+
end
|
90
|
+
|
91
|
+
def map(&block)
|
92
|
+
new_attributes = attributes.transform_values(&block)
|
93
|
+
AttributeSet.new(new_attributes)
|
94
|
+
end
|
95
|
+
|
67
96
|
def ==(other)
|
68
97
|
attributes == other.attributes
|
69
98
|
end
|