aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/associations.rb4
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb2
-rw-r--r--activerecord/lib/active_record/attribute.rb6
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb6
-rw-r--r--activerecord/lib/active_record/attributes.rb28
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/quoting.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb5
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb13
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb12
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/bytea.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/cidr.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/vector.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/xml.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb11
-rw-r--r--activerecord/lib/active_record/enum.rb6
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb2
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb2
-rw-r--r--activerecord/lib/active_record/relation/batches.rb48
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb4
-rw-r--r--activerecord/lib/active_record/result.rb2
-rw-r--r--activerecord/lib/active_record/sanitization.rb2
-rw-r--r--activerecord/lib/active_record/type.rb15
-rw-r--r--activerecord/lib/active_record/type/binary.rb6
-rw-r--r--activerecord/lib/active_record/type/date_time.rb2
-rw-r--r--activerecord/lib/active_record/type/float.rb2
-rw-r--r--activerecord/lib/active_record/type/helpers/accepts_multiparameter_time.rb2
-rw-r--r--activerecord/lib/active_record/type/helpers/mutable.rb6
-rw-r--r--activerecord/lib/active_record/type/helpers/numeric.rb2
-rw-r--r--activerecord/lib/active_record/type/integer.rb6
-rw-r--r--activerecord/lib/active_record/type/serialized.rb6
-rw-r--r--activerecord/lib/active_record/type/string.rb2
-rw-r--r--activerecord/lib/active_record/type/value.rb32
-rw-r--r--activerecord/lib/active_record/type_caster/map.rb2
-rw-r--r--activerecord/lib/active_record/validations/uniqueness.rb2
45 files changed, 162 insertions, 139 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 260ef71e64..a146d78a5a 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1386,7 +1386,7 @@ module ActiveRecord
# has_one :last_comment, -> { order 'posted_on' }, class_name: "Comment"
# has_one :project_manager, -> { where role: 'project_manager' }, class_name: "Person"
# has_one :attachment, as: :attachable
- # has_one :boss, readonly: :true
+ # has_one :boss, -> { readonly }
# has_one :club, through: :membership
# has_one :primary_address, -> { where primary: true }, through: :addressables, source: :addressable
# has_one :credit_card, required: true
@@ -1514,7 +1514,7 @@ module ActiveRecord
# belongs_to :valid_coupon, ->(o) { where "discounts > ?", o.payments_count },
# class_name: "Coupon", foreign_key: "coupon_id"
# belongs_to :attachable, polymorphic: true
- # belongs_to :project, readonly: true
+ # belongs_to :project, -> { readonly }
# belongs_to :post, counter_cache: true
# belongs_to :comment, touch: true
# belongs_to :company, touch: :employees_last_updated_at
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 33e4516bd1..eea847cfa3 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -63,7 +63,7 @@ module ActiveRecord
def ids_writer(ids)
pk_type = reflection.primary_key_type
ids = Array(ids).reject(&:blank?)
- ids.map! { |i| pk_type.type_cast_from_user(i) }
+ ids.map! { |i| pk_type.cast(i) }
replace(klass.find(ids).index_by(&:id).values_at(*ids))
end
diff --git a/activerecord/lib/active_record/attribute.rb b/activerecord/lib/active_record/attribute.rb
index 91886f1324..73dd3fa041 100644
--- a/activerecord/lib/active_record/attribute.rb
+++ b/activerecord/lib/active_record/attribute.rb
@@ -43,7 +43,7 @@ module ActiveRecord
end
def value_for_database
- type.type_cast_for_database(value)
+ type.serialize(value)
end
def changed_from?(old_value)
@@ -108,13 +108,13 @@ module ActiveRecord
class FromDatabase < Attribute # :nodoc:
def type_cast(value)
- type.type_cast_from_database(value)
+ type.deserialize(value)
end
end
class FromUser < Attribute # :nodoc:
def type_cast(value)
- type.type_cast_from_user(value)
+ type.cast(value)
end
def came_from_user?
diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
index 90c36e4b02..f9beb43e4b 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -2,13 +2,13 @@ module ActiveRecord
module AttributeMethods
module TimeZoneConversion
class TimeZoneConverter < DelegateClass(Type::Value) # :nodoc:
- def type_cast_from_database(value)
+ def deserialize(value)
convert_time_to_time_zone(super)
end
- def type_cast_from_user(value)
+ def cast(value)
if value.is_a?(Array)
- value.map { |v| type_cast_from_user(v) }
+ value.map { |v| cast(v) }
elsif value.is_a?(Hash)
set_time_zone_without_conversion(super)
elsif value.respond_to?(:in_time_zone)
diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb
index 87d4bc8578..c8979a60d7 100644
--- a/activerecord/lib/active_record/attributes.rb
+++ b/activerecord/lib/active_record/attributes.rb
@@ -102,14 +102,14 @@ module ActiveRecord
#
# Users may also define their own custom types, as long as they respond
# to the methods defined on the value type. The method
- # +type_cast_from_database+ or +type_cast_from_user+ will be called on
+ # +deserialize+ or +cast+ will be called on
# your type object, with raw input from the database or from your
# controllers. See ActiveRecord::Type::Value for the expected API. It is
# recommended that your type objects inherit from an existing type, or
# from ActiveRecord::Type::Value
#
# class MoneyType < ActiveRecord::Type::Integer
- # def type_cast_from_user(value)
+ # def cast(value)
# if value.include?('$')
# price_in_dollars = value.gsub(/\$/, '').to_f
# super(price_in_dollars * 100)
@@ -119,21 +119,27 @@ module ActiveRecord
# end
# end
#
+ # # config/initializers/types.rb
+ # ActiveRecord::Type.register(:money, MoneyType)
+ #
+ # # /app/models/store_listing.rb
# class StoreListing < ActiveRecord::Base
- # attribute :price_in_cents, MoneyType.new
+ # attribute :price_in_cents, :money
# end
#
# store_listing = StoreListing.new(price_in_cents: '$10.00')
# store_listing.price_in_cents # => 1000
#
# For more details on creating custom types, see the documentation for
- # ActiveRecord::Type::Value.
+ # ActiveRecord::Type::Value. For more details on registering your types
+ # to be referenced by a symbol, see ActiveRecord::Type.register. You can
+ # also pass a type object directly, in place of a symbol.
#
# ==== Querying
#
# When ActiveRecord::QueryMethods#where is called, it will
# use the type defined by the model class to convert the value to SQL,
- # calling +type_cast_for_database+ on your type object. For example:
+ # calling +serialize+ on your type object. For example:
#
# class Money < Struct.new(:amount, :currency)
# end
@@ -143,18 +149,20 @@ module ActiveRecord
# @currency_converter = currency_converter
# end
#
- # # value will be the result of +type_cast_from_database+ or
- # # +type_cast_from_user+. Assumed to be in instance of +Money+ in
+ # # value will be the result of +deserialize+ or
+ # # +cast+. Assumed to be in instance of +Money+ in
# # this case.
- # def type_cast_for_database(value)
+ # def serialize(value)
# value_in_bitcoins = @currency_converter.convert_to_bitcoins(value)
# value_in_bitcoins.amount
# end
# end
#
+ # ActiveRecord::Type.register(:money, MoneyType)
+ #
# class Product < ActiveRecord::Base
# currency_converter = ConversionRatesFromTheInternet.new
- # attribute :price_in_bitcoins, MoneyType.new(currency_converter)
+ # attribute :price_in_bitcoins, :money, currency_converter
# end
#
# Product.where(price_in_bitcoins: Money.new(5, "USD"))
@@ -195,7 +203,7 @@ module ActiveRecord
# Otherwise, the default will be +nil+.
#
# +user_provided_default+ Whether the default value should be cast using
- # +type_cast_from_user+ or +type_cast_from_database+.
+ # +cast+ or +deserialize+.
def define_attribute(
name,
cast_type,
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
index 1ac909da2e..d2840b9498 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
@@ -52,7 +52,7 @@ module ActiveRecord
def type_cast_from_column(column, value) # :nodoc:
if column
type = lookup_cast_type_from_column(column)
- type.type_cast_for_database(value)
+ type.serialize(value)
else
value
end
@@ -103,7 +103,7 @@ module ActiveRecord
end
def quote_default_expression(value, column) #:nodoc:
- value = lookup_cast_type(column.sql_type).type_cast_for_database(value)
+ value = lookup_cast_type(column.sql_type).serialize(value)
quote(value)
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb
index 932aaf7aa7..af7ef7cbaa 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb
@@ -47,7 +47,7 @@ module ActiveRecord
def schema_default(column)
type = lookup_cast_type_from_column(column)
- default = type.type_cast_from_database(column.default)
+ default = type.deserialize(column.default)
unless default.nil?
type.type_cast_for_schema(default)
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index 0438c95bd7..503b09d1fc 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -851,12 +851,6 @@ module ActiveRecord
raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale is specified"
end
- elsif [:datetime, :time].include?(type) && precision ||= native[:precision]
- if (0..6) === precision
- column_type_sql << "(#{precision})"
- else
- raise(ActiveRecordError, "No #{native[:name]} type has precision of #{precision}. The allowed range of precision is from 0 to 6")
- end
elsif (type != :primary_key) && (limit ||= native.is_a?(Hash) && native[:limit])
column_type_sql << "(#{limit})"
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index c307189980..ee11c0efa4 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -245,11 +245,6 @@ module ActiveRecord
false
end
- # Does this adapter support datetime with precision?
- def supports_datetime_with_precision?
- false
- end
-
# This is meant to be implemented by the adapters that support extensions
def disable_extension(name)
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 84bfab43bb..0a1c66be1e 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -251,10 +251,6 @@ module ActiveRecord
version[0] >= 5
end
- def supports_datetime_with_precision?
- (version[0] == 5 && version[1] >= 6) || version[0] >= 6
- end
-
def native_database_types
NATIVE_DATABASE_TYPES
end
@@ -627,6 +623,13 @@ module ActiveRecord
when 0x1000000..0xffffffff; 'longtext'
else raise(ActiveRecordError, "No text type has character length #{limit}")
end
+ when 'datetime'
+ return super unless precision
+
+ case precision
+ when 0..6; "datetime(#{precision})"
+ else raise(ActiveRecordError, "No datetime type has precision of #{precision}. The allowed range of precision is from 0 to 6.")
+ end
else
super
end
@@ -923,7 +926,7 @@ module ActiveRecord
end
class MysqlString < Type::String # :nodoc:
- def type_cast_for_database(value)
+ def serialize(value)
case value
when true then "1"
when false then "0"
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb
index 2608a2abab..fb4e0de2a8 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb
@@ -25,22 +25,22 @@ module ActiveRecord
@delimiter = delimiter
end
- def type_cast_from_database(value)
+ def deserialize(value)
if value.is_a?(::String)
- type_cast_array(parse_pg_array(value), :type_cast_from_database)
+ type_cast_array(parse_pg_array(value), :deserialize)
else
super
end
end
- def type_cast_from_user(value)
+ def cast(value)
if value.is_a?(::String)
value = parse_pg_array(value)
end
- type_cast_array(value, :type_cast_from_user)
+ type_cast_array(value, :cast)
end
- def type_cast_for_database(value)
+ def serialize(value)
if value.is_a?(::Array)
cast_value_for_database(value)
else
@@ -69,7 +69,7 @@ module ActiveRecord
casted_values = value.map { |item| cast_value_for_database(item) }
"{#{casted_values.join(delimiter)}}"
else
- quote_and_escape(subtype.type_cast_for_database(value))
+ quote_and_escape(subtype.serialize(value))
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb
index 1dbb40ca1d..ea0fa2517f 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb
@@ -7,7 +7,7 @@ module ActiveRecord
:bit
end
- def type_cast(value)
+ def cast(value)
if ::String === value
case value
when /^0x/i
@@ -20,7 +20,7 @@ module ActiveRecord
end
end
- def type_cast_for_database(value)
+ def serialize(value)
Data.new(super) if value
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/bytea.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/bytea.rb
index 6bd1b8ecae..8f9d6e7f9b 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/bytea.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/bytea.rb
@@ -3,7 +3,7 @@ module ActiveRecord
module PostgreSQL
module OID # :nodoc:
class Bytea < Type::Binary # :nodoc:
- def type_cast_from_database(value)
+ def deserialize(value)
return if value.nil?
return value.to_s if value.is_a?(Type::Binary::Data)
PGconn.unescape_bytea(super)
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/cidr.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/cidr.rb
index 222f10fa8f..eeccb09bdf 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/cidr.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/cidr.rb
@@ -18,7 +18,7 @@ module ActiveRecord
end
end
- def type_cast_for_database(value)
+ def serialize(value)
if IPAddr === value
"#{value}/#{value.instance_variable_get(:@mask_addr).to_s(2).count('1')}"
else
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb
index 77d5038efd..b3b610a5f6 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb
@@ -7,7 +7,7 @@ module ActiveRecord
:enum
end
- def type_cast(value)
+ def cast(value)
value.to_s
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb
index b46e50c865..9270fc9f21 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb
@@ -9,7 +9,7 @@ module ActiveRecord
:hstore
end
- def type_cast_from_database(value)
+ def deserialize(value)
if value.is_a?(::String)
::Hash[value.scan(HstorePair).map { |k, v|
v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
@@ -21,7 +21,7 @@ module ActiveRecord
end
end
- def type_cast_for_database(value)
+ def serialize(value)
if value.is_a?(::Hash)
value.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(', ')
else
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb
index 13dd037314..8e1256baad 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb
@@ -9,19 +9,19 @@ module ActiveRecord
:json
end
- def type_cast_from_database(value)
+ def deserialize(value)
if value.is_a?(::String)
::ActiveSupport::JSON.decode(value) rescue nil
else
- super
+ value
end
end
- def type_cast_for_database(value)
+ def serialize(value)
if value.is_a?(::Array) || value.is_a?(::Hash)
::ActiveSupport::JSON.encode(value)
else
- super
+ value
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb
index 380c50fc14..afc9383f91 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb
@@ -13,7 +13,7 @@ module ActiveRecord
# the comparison here. Therefore, we need to parse and re-dump the
# raw value here to ensure the insignificant whitespaces are
# consistent with our encoder's output.
- raw_old_value = type_cast_for_database(type_cast_from_database(raw_old_value))
+ raw_old_value = serialize(deserialize(raw_old_value))
super(raw_old_value, new_value)
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb
index 4084725ed7..bf565bcf47 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb
@@ -9,13 +9,13 @@ module ActiveRecord
:point
end
- def type_cast(value)
+ def cast(value)
case value
when ::String
if value[0] == '(' && value[-1] == ')'
value = value[1...-1]
end
- type_cast(value.split(','))
+ cast(value.split(','))
when ::Array
value.map { |v| Float(v) }
else
@@ -23,7 +23,7 @@ module ActiveRecord
end
end
- def type_cast_for_database(value)
+ def serialize(value)
if value.is_a?(::Array)
"(#{number_for_point(value[0])},#{number_for_point(value[1])})"
else
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb
index 9d3633d109..fc201f8fb9 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb
@@ -30,7 +30,7 @@ module ActiveRecord
::Range.new(from, to, extracted[:exclude_end])
end
- def type_cast_for_database(value)
+ def serialize(value)
if value.is_a?(::Range)
from = type_cast_single_for_database(value.begin)
to = type_cast_single_for_database(value.end)
@@ -49,11 +49,11 @@ module ActiveRecord
private
def type_cast_single(value)
- infinity?(value) ? value : @subtype.type_cast_from_database(value)
+ infinity?(value) ? value : @subtype.deserialize(value)
end
def type_cast_single_for_database(value)
- infinity?(value) ? '' : @subtype.type_cast_for_database(value)
+ infinity?(value) ? '' : @subtype.serialize(value)
end
def extract_bounds(value)
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb
index 97b4fd3d08..5e839228e9 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb
@@ -5,13 +5,13 @@ module ActiveRecord
class Uuid < Type::Value # :nodoc:
ACCEPTABLE_UUID = %r{\A\{?([a-fA-F0-9]{4}-?){8}\}?\z}x
- alias_method :type_cast_for_database, :type_cast_from_database
+ alias_method :serialize, :deserialize
def type
:uuid
end
- def type_cast(value)
+ def cast(value)
value.to_s[ACCEPTABLE_UUID, 0]
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/vector.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/vector.rb
index de4187b028..b26e876b54 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/vector.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/vector.rb
@@ -16,7 +16,7 @@ module ActiveRecord
# FIXME: this should probably split on +delim+ and use +subtype+
# to cast the values. Unfortunately, the current Rails behavior
# is to just return the string.
- def type_cast(value)
+ def cast(value)
value
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/xml.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/xml.rb
index 334af7c598..d40d837cee 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/xml.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/xml.rb
@@ -7,7 +7,7 @@ module ActiveRecord
:xml
end
- def type_cast_for_database(value)
+ def serialize(value)
return unless value
Data.new(super)
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index 503dda60f4..81fde18f64 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -534,6 +534,13 @@ module ActiveRecord
when 5..8; 'bigint'
else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
end
+ when 'datetime'
+ return super unless precision
+
+ case precision
+ when 0..6; "timestamp(#{precision})"
+ else raise(ActiveRecordError, "No timestamp type has precision of #{precision}. The allowed range of precision is from 0 to 6")
+ end
else
super
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 6d25b53b21..5a887ea529 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -180,10 +180,6 @@ module ActiveRecord
true
end
- def supports_datetime_with_precision?
- true
- end
-
def index_algorithms
{ concurrently: 'CONCURRENTLY' }
end
@@ -481,6 +477,7 @@ module ActiveRecord
register_class_with_limit m, 'varbit', OID::BitVarying
m.alias_type 'timestamptz', 'timestamp'
m.register_type 'date', Type::Date.new
+ m.register_type 'time', Type::Time.new
m.register_type 'money', OID::Money.new
m.register_type 'bytea', OID::Bytea.new
@@ -506,8 +503,10 @@ module ActiveRecord
m.alias_type 'lseg', 'varchar'
m.alias_type 'box', 'varchar'
- register_class_with_precision m, 'time', Type::Time
- register_class_with_precision m, 'timestamp', OID::DateTime
+ m.register_type 'timestamp' do |_, _, sql_type|
+ precision = extract_precision(sql_type)
+ OID::DateTime.new(precision: precision)
+ end
m.register_type 'numeric' do |_, fmod, sql_type|
precision = extract_precision(sql_type)
diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb
index 470e0b5d29..ea88983917 100644
--- a/activerecord/lib/active_record/enum.rb
+++ b/activerecord/lib/active_record/enum.rb
@@ -93,7 +93,7 @@ module ActiveRecord
@mapping = mapping
end
- def type_cast_from_user(value)
+ def cast(value)
return if value.blank?
if mapping.has_key?(value)
@@ -105,12 +105,12 @@ module ActiveRecord
end
end
- def type_cast_from_database(value)
+ def deserialize(value)
return if value.nil?
mapping.key(value.to_i)
end
- def type_cast_for_database(value)
+ def serialize(value)
mapping.fetch(value, value)
end
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index c5b10fcddf..a58d8355aa 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -185,7 +185,7 @@ module ActiveRecord
end
class LockingType < DelegateClass(Type::Value) # :nodoc:
- def type_cast_from_database(value)
+ def deserialize(value)
# `nil` *should* be changed to 0
super.to_i
end
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index 117a128579..084ef397a8 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -521,7 +521,7 @@ module ActiveRecord
# Determines if a hash contains a truthy _destroy key.
def has_destroy_flag?(hash)
- Type::Boolean.new.type_cast_from_user(hash['_destroy'])
+ Type::Boolean.new.cast(hash['_destroy'])
end
# Determines if a new record should be rejected by checking
diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb
index a543341149..e07580a563 100644
--- a/activerecord/lib/active_record/relation/batches.rb
+++ b/activerecord/lib/active_record/relation/batches.rb
@@ -27,15 +27,15 @@ module ActiveRecord
#
# ==== Options
# * <tt>:batch_size</tt> - Specifies the size of the batch. Default to 1000.
- # * <tt>:start</tt> - Specifies the primary key value to start from, inclusive of the value.
+ # * <tt>:begin_at</tt> - Specifies the primary key value to start from, inclusive of the value.
# * <tt>:end_at</tt> - Specifies the primary key value to end at, inclusive of the value.
# This is especially useful if you want multiple workers dealing with
# the same processing queue. You can make worker 1 handle all the records
# between id 0 and 10,000 and worker 2 handle from 10,000 and beyond
- # (by setting the +:start+ and +:end_at+ option on each worker).
+ # (by setting the +:begin_at+ and +:end_at+ option on each worker).
#
# # Let's process for a batch of 2000 records, skipping the first 2000 rows
- # Person.find_each(start: 2000, batch_size: 2000) do |person|
+ # Person.find_each(begin_at: 2000, batch_size: 2000) do |person|
# person.party_all_night!
# end
#
@@ -46,15 +46,22 @@ module ActiveRecord
#
# NOTE: You can't set the limit either, that's used to control
# the batch sizes.
- def find_each(start: nil, end_at: nil, batch_size: 1000)
+ def find_each(begin_at: nil, end_at: nil, batch_size: 1000, start: nil)
+ if start
+ begin_at = start
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ Passing `start` value to find_each is deprecated, and will be removed in Rails 5.1.
+ Please pass `begin_at` instead.
+ MSG
+ end
if block_given?
- find_in_batches(start: start, end_at: end_at, batch_size: batch_size) do |records|
+ find_in_batches(begin_at: begin_at, end_at: end_at, batch_size: batch_size) do |records|
records.each { |record| yield record }
end
else
- enum_for(:find_each, start: start, end_at: end_at, batch_size: batch_size) do
+ enum_for(:find_each, begin_at: begin_at, end_at: end_at, batch_size: batch_size) do
relation = self
- apply_limits(relation, start, end_at).size
+ apply_limits(relation, begin_at, end_at).size
end
end
end
@@ -79,15 +86,15 @@ module ActiveRecord
#
# ==== Options
# * <tt>:batch_size</tt> - Specifies the size of the batch. Default to 1000.
- # * <tt>:start</tt> - Specifies the primary key value to start from, inclusive of the value.
+ # * <tt>:begin_at</tt> - Specifies the primary key value to start from, inclusive of the value.
# * <tt>:end_at</tt> - Specifies the primary key value to end at, inclusive of the value.
# This is especially useful if you want multiple workers dealing with
# the same processing queue. You can make worker 1 handle all the records
# between id 0 and 10,000 and worker 2 handle from 10,000 and beyond
- # (by setting the +:start+ and +:end_at+ option on each worker).
+ # (by setting the +:begin_at+ and +:end_at+ option on each worker).
#
# # Let's process the next 2000 records
- # Person.find_in_batches(start: 2000, batch_size: 2000) do |group|
+ # Person.find_in_batches(begin_at: 2000, batch_size: 2000) do |group|
# group.each { |person| person.party_all_night! }
# end
#
@@ -98,12 +105,19 @@ module ActiveRecord
#
# NOTE: You can't set the limit either, that's used to control
# the batch sizes.
- def find_in_batches(start: nil, end_at: nil, batch_size: 1000)
- relation = self
+ def find_in_batches(begin_at: nil, end_at: nil, batch_size: 1000, start: nil)
+ if start
+ begin_at = start
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ Passing `start` value to find_in_batches is deprecated, and will be removed in Rails 5.1.
+ Please pass `begin_at` instead.
+ MSG
+ end
+ relation = self
unless block_given?
- return to_enum(:find_in_batches, start: start, end_at: end_at, batch_size: batch_size) do
- total = apply_limits(relation, start, end_at).size
+ return to_enum(:find_in_batches, begin_at: begin_at, end_at: end_at, batch_size: batch_size) do
+ total = apply_limits(relation, begin_at, end_at).size
(total - 1).div(batch_size) + 1
end
end
@@ -113,7 +127,7 @@ module ActiveRecord
end
relation = relation.reorder(batch_order).limit(batch_size)
- relation = apply_limits(relation, start, end_at)
+ relation = apply_limits(relation, begin_at, end_at)
records = relation.to_a
while records.any?
@@ -131,8 +145,8 @@ module ActiveRecord
private
- def apply_limits(relation, start, end_at)
- relation = relation.where(table[primary_key].gteq(start)) if start
+ def apply_limits(relation, begin_at, end_at)
+ relation = relation.where(table[primary_key].gteq(begin_at)) if begin_at
relation = relation.where(table[primary_key].lteq(end_at)) if end_at
relation
end
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index 63e0d2fc21..4a4de86d48 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -353,9 +353,9 @@ module ActiveRecord
def type_cast_calculated_value(value, type, operation = nil)
case operation
when 'count' then value.to_i
- when 'sum' then type.type_cast_from_database(value || 0)
+ when 'sum' then type.deserialize(value || 0)
when 'average' then value.respond_to?(:to_d) ? value.to_d : value
- else type.type_cast_from_database(value)
+ else type.deserialize(value)
end
end
diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb
index 3a3e65ef32..500c478e65 100644
--- a/activerecord/lib/active_record/result.rb
+++ b/activerecord/lib/active_record/result.rb
@@ -81,7 +81,7 @@ module ActiveRecord
def cast_values(type_overrides = {}) # :nodoc:
types = columns.map { |name| column_type(name, type_overrides) }
result = rows.map do |values|
- types.zip(values).map { |type, value| type.type_cast_from_database(value) }
+ types.zip(values).map { |type, value| type.deserialize(value) }
end
columns.one? ? result.map!(&:first) : result
diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb
index 313e767dcb..c7f55ebaa1 100644
--- a/activerecord/lib/active_record/sanitization.rb
+++ b/activerecord/lib/active_record/sanitization.rb
@@ -75,7 +75,7 @@ module ActiveRecord
def sanitize_sql_hash_for_assignment(attrs, table)
c = connection
attrs.map do |attr, value|
- value = type_for_attribute(attr.to_s).type_cast_for_database(value)
+ value = type_for_attribute(attr.to_s).serialize(value)
"#{c.quote_table_name_for_assignment(table, attr)} = #{c.quote(value)}"
end.join(', ')
end
diff --git a/activerecord/lib/active_record/type.rb b/activerecord/lib/active_record/type.rb
index cddd56a20d..2c0cda69d0 100644
--- a/activerecord/lib/active_record/type.rb
+++ b/activerecord/lib/active_record/type.rb
@@ -26,10 +26,21 @@ module ActiveRecord
class << self
attr_accessor :registry # :nodoc:
+ delegate :add_modifier, to: :registry
- delegate :register, :add_modifier, to: :registry
+ # Add a new type to the registry, allowing it to be referenced as a
+ # symbol by ActiveRecord::Attributes::ClassMethods#attribute. If your
+ # type is only meant to be used with a specific database adapter, you can
+ # do so by passing +adapter: :postgresql+. If your type has the same
+ # name as a native type for the current adapter, an exception will be
+ # raised unless you specify an +:override+ option. +override: true+ will
+ # cause your type to be used instead of the native type. +override:
+ # false+ will cause the native type to be used over yours if one exists.
+ def register(type_name, klass = nil, **options, &block)
+ registry.register(type_name, klass, **options, &block)
+ end
- def lookup(*args, adapter: current_adapter_name, **kwargs)
+ def lookup(*args, adapter: current_adapter_name, **kwargs) # :nodoc:
registry.lookup(*args, adapter: adapter, **kwargs)
end
diff --git a/activerecord/lib/active_record/type/binary.rb b/activerecord/lib/active_record/type/binary.rb
index 005a48ef0d..0baf8c63ad 100644
--- a/activerecord/lib/active_record/type/binary.rb
+++ b/activerecord/lib/active_record/type/binary.rb
@@ -9,7 +9,7 @@ module ActiveRecord
true
end
- def type_cast(value)
+ def cast(value)
if value.is_a?(Data)
value.to_s
else
@@ -17,13 +17,13 @@ module ActiveRecord
end
end
- def type_cast_for_database(value)
+ def serialize(value)
return if value.nil?
Data.new(super)
end
def changed_in_place?(raw_old_value, value)
- old_value = type_cast_from_database(raw_old_value)
+ old_value = deserialize(raw_old_value)
old_value != value
end
diff --git a/activerecord/lib/active_record/type/date_time.rb b/activerecord/lib/active_record/type/date_time.rb
index a25f2521bb..05d2af3808 100644
--- a/activerecord/lib/active_record/type/date_time.rb
+++ b/activerecord/lib/active_record/type/date_time.rb
@@ -10,7 +10,7 @@ module ActiveRecord
:datetime
end
- def type_cast_for_database(value)
+ def serialize(value)
if precision && value.respond_to?(:usec)
number_of_insignificant_digits = 6 - precision
round_power = 10 ** number_of_insignificant_digits
diff --git a/activerecord/lib/active_record/type/float.rb b/activerecord/lib/active_record/type/float.rb
index b3928242b7..d88482b85d 100644
--- a/activerecord/lib/active_record/type/float.rb
+++ b/activerecord/lib/active_record/type/float.rb
@@ -7,7 +7,7 @@ module ActiveRecord
:float
end
- alias type_cast_for_database type_cast
+ alias serialize cast
private
diff --git a/activerecord/lib/active_record/type/helpers/accepts_multiparameter_time.rb b/activerecord/lib/active_record/type/helpers/accepts_multiparameter_time.rb
index 640943c5e9..be571fc1c7 100644
--- a/activerecord/lib/active_record/type/helpers/accepts_multiparameter_time.rb
+++ b/activerecord/lib/active_record/type/helpers/accepts_multiparameter_time.rb
@@ -3,7 +3,7 @@ module ActiveRecord
module Helpers
class AcceptsMultiparameterTime < Module # :nodoc:
def initialize(defaults: {})
- define_method(:type_cast_from_user) do |value|
+ define_method(:cast) do |value|
if value.is_a?(Hash)
value_from_multiparameter_assignment(value)
else
diff --git a/activerecord/lib/active_record/type/helpers/mutable.rb b/activerecord/lib/active_record/type/helpers/mutable.rb
index dc37f4a885..88a9099277 100644
--- a/activerecord/lib/active_record/type/helpers/mutable.rb
+++ b/activerecord/lib/active_record/type/helpers/mutable.rb
@@ -2,15 +2,15 @@ module ActiveRecord
module Type
module Helpers
module Mutable # :nodoc:
- def type_cast_from_user(value)
- type_cast_from_database(type_cast_for_database(value))
+ def cast(value)
+ deserialize(serialize(value))
end
# +raw_old_value+ will be the `_before_type_cast` version of the
# value (likely a string). +new_value+ will be the current, type
# cast value.
def changed_in_place?(raw_old_value, new_value)
- raw_old_value != type_cast_for_database(new_value)
+ raw_old_value != serialize(new_value)
end
end
end
diff --git a/activerecord/lib/active_record/type/helpers/numeric.rb b/activerecord/lib/active_record/type/helpers/numeric.rb
index b0d4f03117..a755a02a59 100644
--- a/activerecord/lib/active_record/type/helpers/numeric.rb
+++ b/activerecord/lib/active_record/type/helpers/numeric.rb
@@ -2,7 +2,7 @@ module ActiveRecord
module Type
module Helpers
module Numeric # :nodoc:
- def type_cast(value)
+ def cast(value)
value = case value
when true then 1
when false then 0
diff --git a/activerecord/lib/active_record/type/integer.rb b/activerecord/lib/active_record/type/integer.rb
index 2ab2402dfd..2a1b04ac7f 100644
--- a/activerecord/lib/active_record/type/integer.rb
+++ b/activerecord/lib/active_record/type/integer.rb
@@ -16,13 +16,13 @@ module ActiveRecord
:integer
end
- def type_cast_from_database(value)
+ def deserialize(value)
return if value.nil?
value.to_i
end
- def type_cast_for_database(value)
- result = type_cast(value)
+ def serialize(value)
+ result = cast(value)
if result
ensure_in_range(result)
end
diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb
index 6c6c520048..732029c723 100644
--- a/activerecord/lib/active_record/type/serialized.rb
+++ b/activerecord/lib/active_record/type/serialized.rb
@@ -11,7 +11,7 @@ module ActiveRecord
super(subtype)
end
- def type_cast_from_database(value)
+ def deserialize(value)
if default_value?(value)
value
else
@@ -19,7 +19,7 @@ module ActiveRecord
end
end
- def type_cast_for_database(value)
+ def serialize(value)
return if value.nil?
unless default_value?(value)
super coder.dump(value)
@@ -28,7 +28,7 @@ module ActiveRecord
def changed_in_place?(raw_old_value, value)
return false if value.nil?
- subtype.changed_in_place?(raw_old_value, type_cast_for_database(value))
+ subtype.changed_in_place?(raw_old_value, serialize(value))
end
def accessor
diff --git a/activerecord/lib/active_record/type/string.rb b/activerecord/lib/active_record/type/string.rb
index fbc0af2c5a..2662b7e874 100644
--- a/activerecord/lib/active_record/type/string.rb
+++ b/activerecord/lib/active_record/type/string.rb
@@ -11,7 +11,7 @@ module ActiveRecord
end
end
- def type_cast_for_database(value)
+ def serialize(value)
case value
when ::Numeric, ActiveSupport::Duration then value.to_s
when ::String then ::String.new(value)
diff --git a/activerecord/lib/active_record/type/value.rb b/activerecord/lib/active_record/type/value.rb
index 7338920f3b..fc3ef5e83b 100644
--- a/activerecord/lib/active_record/type/value.rb
+++ b/activerecord/lib/active_record/type/value.rb
@@ -14,12 +14,12 @@ module ActiveRecord
# Convert a value from database input to the appropriate ruby type. The
# return value of this method will be returned from
- # ActiveRecord::AttributeMethods::Read#read_attribute. See also
- # Value#type_cast and Value#cast_value.
+ # ActiveRecord::AttributeMethods::Read#read_attribute. The default
+ # implementation just calls Value#cast.
#
# +value+ The raw input, as provided from the database.
- def type_cast_from_database(value)
- type_cast(value)
+ def deserialize(value)
+ cast(value)
end
# Type casts a value from user input (e.g. from a setter). This value may
@@ -29,18 +29,18 @@ module ActiveRecord
#
# The return value of this method will be returned from
# ActiveRecord::AttributeMethods::Read#read_attribute. See also:
- # Value#type_cast and Value#cast_value.
+ # Value#cast_value.
#
# +value+ The raw input, as provided to the attribute setter.
- def type_cast_from_user(value)
- type_cast(value)
+ def cast(value)
+ cast_value(value) unless value.nil?
end
# Cast a value from the ruby type to a type that the database knows how
# to understand. The returned value from this method should be a
# +String+, +Numeric+, +Date+, +Time+, +Symbol+, +true+, +false+, or
# +nil+.
- def type_cast_for_database(value)
+ def serialize(value)
value
end
@@ -68,16 +68,16 @@ module ActiveRecord
# which could be mutated, you should override this method. You will need
# to either:
#
- # - pass +new_value+ to Value#type_cast_for_database and compare it to
+ # - pass +new_value+ to Value#serialize and compare it to
# +raw_old_value+
#
# or
#
- # - pass +raw_old_value+ to Value#type_cast_from_database and compare it to
+ # - pass +raw_old_value+ to Value#deserialize and compare it to
# +new_value+
#
# +raw_old_value+ The original value, before being passed to
- # +type_cast_from_database+.
+ # +deserialize+.
#
# +new_value+ The current value, after type casting.
def changed_in_place?(raw_old_value, new_value)
@@ -93,16 +93,8 @@ module ActiveRecord
private
- # Convenience method. If you don't need separate behavior for
- # Value#type_cast_from_database and Value#type_cast_from_user, you can override
- # this method instead. The default behavior of both methods is to call
- # this one. See also Value#cast_value.
- def type_cast(value) # :doc:
- cast_value(value) unless value.nil?
- end
-
# Convenience method for types which do not need separate type casting
- # behavior for user and database inputs. Called by Value#type_cast for
+ # behavior for user and database inputs. Called by Value#cast for
# values except +nil+.
def cast_value(value) # :doc:
value
diff --git a/activerecord/lib/active_record/type_caster/map.rb b/activerecord/lib/active_record/type_caster/map.rb
index 03c9e8ff83..4b1941351c 100644
--- a/activerecord/lib/active_record/type_caster/map.rb
+++ b/activerecord/lib/active_record/type_caster/map.rb
@@ -8,7 +8,7 @@ module ActiveRecord
def type_cast_for_database(attr_name, value)
return value if value.is_a?(Arel::Nodes::BindParam)
type = types.type_for_attribute(attr_name.to_s)
- type.type_cast_for_database(value)
+ type.serialize(value)
end
protected
diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb
index a766d77e88..9be4b10a55 100644
--- a/activerecord/lib/active_record/validations/uniqueness.rb
+++ b/activerecord/lib/active_record/validations/uniqueness.rb
@@ -61,7 +61,7 @@ module ActiveRecord
column = klass.columns_hash[attribute_name]
cast_type = klass.type_for_attribute(attribute_name)
- value = cast_type.type_cast_for_database(value)
+ value = cast_type.serialize(value)
value = klass.connection.type_cast(value)
if value.is_a?(String) && column.limit
value = value.to_s[0, column.limit]