aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/lib/active_record/attributes.rb13
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/quoting.rb21
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb41
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb4
-rw-r--r--activerecord/test/cases/attribute_decorators_test.rb6
-rw-r--r--activerecord/test/cases/attributes_test.rb42
-rw-r--r--activerecord/test/cases/base_test.rb4
-rw-r--r--activerecord/test/cases/calculations_test.rb6
-rw-r--r--activerecord/test/cases/dirty_test.rb2
-rw-r--r--activerecord/test/cases/migration_test.rb4
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb5
-rw-r--r--activerecord/test/cases/type/integer_test.rb2
-rw-r--r--activerecord/test/cases/validations_test.rb2
16 files changed, 148 insertions, 22 deletions
diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb
index 7cb6b075a0..f34e6cf912 100644
--- a/activerecord/lib/active_record/attributes.rb
+++ b/activerecord/lib/active_record/attributes.rb
@@ -44,7 +44,7 @@ module ActiveRecord
# store_listing.price_in_cents # => BigDecimal.new(10.1)
#
# class StoreListing < ActiveRecord::Base
- # attribute :price_in_cents, Type::Integer.new
+ # attribute :price_in_cents, :integer
# end
#
# # after
@@ -77,7 +77,10 @@ module ActiveRecord
name = name.to_s
reload_schema_from_cache
- self.attributes_to_define_after_schema_loads = attributes_to_define_after_schema_loads.merge(name => [cast_type, options])
+ self.attributes_to_define_after_schema_loads =
+ attributes_to_define_after_schema_loads.merge(
+ name => [cast_type, options]
+ )
end
def define_attribute(
@@ -93,7 +96,11 @@ module ActiveRecord
def load_schema!
super
attributes_to_define_after_schema_loads.each do |name, (type, options)|
- define_attribute(name, type, **options)
+ if type.is_a?(Symbol)
+ type = connection.type_for_attribute_options(type, **options.except(:default))
+ end
+
+ define_attribute(name, type, **options.slice(:default))
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
index 2c013a074a..55d3360070 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
@@ -134,8 +134,29 @@ module ActiveRecord
binds.map(&:value_for_database)
end
+ def type_for_attribute_options(type_name, **options)
+ klass = type_classes_with_standard_constructor.fetch(type_name, Type::Value)
+ klass.new(**options)
+ end
+
private
+ def type_classes_with_standard_constructor
+ {
+ big_integer: Type::BigInteger,
+ binary: Type::Binary,
+ boolean: Type::Boolean,
+ date: Type::Date,
+ date_time: Type::DateTime,
+ decimal: Type::Decimal,
+ float: Type::Float,
+ integer: Type::Integer,
+ string: Type::String,
+ text: Type::Text,
+ time: Type::Time,
+ }
+ end
+
def types_which_need_no_typecasting
[nil, Numeric, String]
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 5c8c4b883a..61bac6741f 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -947,6 +947,10 @@ module ActiveRecord
end
end
end
+
+ def type_classes_with_standard_constructor
+ super.merge(string: MysqlString, date_time: MysqlDateTime)
+ end
end
end
end
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 e45a2f59d9..0a0a7fdbb3 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb
@@ -48,6 +48,12 @@ module ActiveRecord
end
end
+ def ==(other)
+ other.is_a?(Array) &&
+ subtype == other.subtype &&
+ delimiter == other.delimiter
+ end
+
private
def type_cast_array(value, method)
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 3adfb8b9d8..2a5a59fbc6 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb
@@ -7,7 +7,7 @@ module ActiveRecord
class Range < Type::Value # :nodoc:
attr_reader :subtype, :type
- def initialize(subtype, type)
+ def initialize(subtype, type = :range)
@subtype = subtype
@type = type
end
@@ -40,6 +40,12 @@ module ActiveRecord
end
end
+ def ==(other)
+ other.is_a?(Range) &&
+ other.subtype == subtype &&
+ other.type == type
+ end
+
private
def type_cast_single(value)
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
index 464adb4e23..11114f32fe 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
@@ -65,6 +65,23 @@ module ActiveRecord
type_map.lookup(column.oid, column.fmod, column.sql_type)
end
+ def type_for_attribute_options(
+ type_name,
+ array: false,
+ range: false,
+ **options
+ )
+ if array
+ subtype = type_for_attribute_options(type_name, **options)
+ OID::Array.new(subtype)
+ elsif range
+ subtype = type_for_attribute_options(type_name, **options)
+ OID::Range.new(subtype)
+ else
+ super(type_name, **options)
+ end
+ end
+
private
def _quote(value)
@@ -103,6 +120,30 @@ module ActiveRecord
super
end
end
+
+ def type_classes_with_standard_constructor
+ super.merge(
+ bit: OID::Bit,
+ bit_varying: OID::BitVarying,
+ binary: OID::Bytea,
+ cidr: OID::Cidr,
+ date: OID::Date,
+ date_time: OID::DateTime,
+ decimal: OID::Decimal,
+ enum: OID::Enum,
+ float: OID::Float,
+ hstore: OID::Hstore,
+ inet: OID::Inet,
+ json: OID::Json,
+ jsonb: OID::Jsonb,
+ money: OID::Money,
+ point: OID::Point,
+ time: OID::Time,
+ uuid: OID::Uuid,
+ vector: OID::Vector,
+ xml: OID::Xml,
+ )
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index c06213a7bf..edd060248f 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -240,6 +240,10 @@ module ActiveRecord
end
end
+ def type_classes_with_standard_constructor
+ super.merge(binary: SQLite3Binary)
+ end
+
def quote_string(s) #:nodoc:
@connection.class.quote(s)
end
diff --git a/activerecord/test/cases/attribute_decorators_test.rb b/activerecord/test/cases/attribute_decorators_test.rb
index 9ad02ffae8..0b96319cbd 100644
--- a/activerecord/test/cases/attribute_decorators_test.rb
+++ b/activerecord/test/cases/attribute_decorators_test.rb
@@ -51,7 +51,7 @@ module ActiveRecord
end
test "undecorated columns are not touched" do
- Model.attribute :another_string, Type::String.new, default: 'something or other'
+ Model.attribute :another_string, :string, default: 'something or other'
Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
assert_equal 'something or other', Model.new.another_string
@@ -86,7 +86,7 @@ module ActiveRecord
end
test "decorating attributes does not modify parent classes" do
- Model.attribute :another_string, Type::String.new, default: 'whatever'
+ Model.attribute :another_string, :string, default: 'whatever'
Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
child_class = Class.new(Model)
child_class.decorate_attribute_type(:another_string, :test) { |t| StringDecorator.new(t) }
@@ -110,7 +110,7 @@ module ActiveRecord
end
test "decorating with a proc" do
- Model.attribute :an_int, Type::Integer.new
+ Model.attribute :an_int, :integer
type_is_integer = proc { |_, type| type.type == :integer }
Model.decorate_matching_attribute_types type_is_integer, :multiplier do |type|
Multiplier.new(type)
diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb
index 6f331c5985..a753e8b74e 100644
--- a/activerecord/test/cases/attributes_test.rb
+++ b/activerecord/test/cases/attributes_test.rb
@@ -1,17 +1,17 @@
require 'cases/helper'
class OverloadedType < ActiveRecord::Base
- attribute :overloaded_float, Type::Integer.new
- attribute :overloaded_string_with_limit, Type::String.new(limit: 50)
- attribute :non_existent_decimal, Type::Decimal.new
- attribute :string_with_default, Type::String.new, default: 'the overloaded default'
+ attribute :overloaded_float, :integer
+ attribute :overloaded_string_with_limit, :string, limit: 50
+ attribute :non_existent_decimal, :decimal
+ attribute :string_with_default, :string, default: 'the overloaded default'
end
class ChildOfOverloadedType < OverloadedType
end
class GrandchildOfOverloadedType < ChildOfOverloadedType
- attribute :overloaded_float, Type::Float.new
+ attribute :overloaded_float, :float
end
class UnoverloadedType < ActiveRecord::Base
@@ -124,5 +124,37 @@ module ActiveRecord
assert_equal "from user", model.wibble
end
+
+ if current_adapter?(:PostgreSQLAdapter)
+ test "arrays types can be specified" do
+ klass = Class.new(OverloadedType) do
+ attribute :my_array, :string, limit: 50, array: true
+ attribute :my_int_array, :integer, array: true
+ end
+
+ string_array = ConnectionAdapters::PostgreSQL::OID::Array.new(
+ Type::String.new(limit: 50))
+ int_array = ConnectionAdapters::PostgreSQL::OID::Array.new(
+ Type::Integer.new)
+ refute_equal string_array, int_array
+ assert_equal string_array, klass.type_for_attribute("my_array")
+ assert_equal int_array, klass.type_for_attribute("my_int_array")
+ end
+
+ test "range types can be specified" do
+ klass = Class.new(OverloadedType) do
+ attribute :my_range, :string, limit: 50, range: true
+ attribute :my_int_range, :integer, range: true
+ end
+
+ string_range = ConnectionAdapters::PostgreSQL::OID::Range.new(
+ Type::String.new(limit: 50))
+ int_range = ConnectionAdapters::PostgreSQL::OID::Range.new(
+ Type::Integer.new)
+ refute_equal string_range, int_range
+ assert_equal string_range, klass.type_for_attribute("my_range")
+ assert_equal int_range, klass.type_for_attribute("my_int_range")
+ end
+ end
end
end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 7c5939fc47..ef1173a2ba 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -903,8 +903,8 @@ class BasicsTest < ActiveRecord::TestCase
class NumericData < ActiveRecord::Base
self.table_name = 'numeric_data'
- attribute :my_house_population, Type::Integer.new
- attribute :atoms_in_universe, Type::Integer.new
+ attribute :my_house_population, :integer
+ attribute :atoms_in_universe, :integer
end
def test_big_decimal_conditions
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index f47568f2f5..f0393aa6b1 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -15,9 +15,9 @@ require 'models/treasure'
class NumericData < ActiveRecord::Base
self.table_name = 'numeric_data'
- attribute :world_population, Type::Integer.new
- attribute :my_house_population, Type::Integer.new
- attribute :atoms_in_universe, Type::Integer.new
+ attribute :world_population, :integer
+ attribute :my_house_population, :integer
+ attribute :atoms_in_universe, :integer
end
class CalculationsTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb
index 192ba6f7cd..c2573ac72b 100644
--- a/activerecord/test/cases/dirty_test.rb
+++ b/activerecord/test/cases/dirty_test.rb
@@ -711,7 +711,7 @@ class DirtyTest < ActiveRecord::TestCase
test "attribute_will_change! doesn't try to save non-persistable attributes" do
klass = Class.new(ActiveRecord::Base) do
self.table_name = 'people'
- attribute :non_persisted_attribute, ActiveRecord::Type::String.new
+ attribute :non_persisted_attribute, :string
end
record = klass.new(first_name: "Sean")
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index d969345361..51b0034755 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -15,9 +15,9 @@ require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers"
class BigNumber < ActiveRecord::Base
unless current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter)
- attribute :value_of_e, Type::Integer.new
+ attribute :value_of_e, :integer
end
- attribute :my_house_population, Type::Integer.new
+ attribute :my_house_population, :integer
end
class Reminder < ActiveRecord::Base; end
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index bafc9fa81b..5ca3f91cf0 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -78,6 +78,11 @@ class SchemaDumperTest < ActiveRecord::TestCase
end
end.compact
+ if lengths.uniq.length != 1
+ p lengths.uniq.length
+ puts column_set
+ end
+
assert_equal 1, lengths.uniq.length
end
end
diff --git a/activerecord/test/cases/type/integer_test.rb b/activerecord/test/cases/type/integer_test.rb
index 0c60f0690c..1e836f2142 100644
--- a/activerecord/test/cases/type/integer_test.rb
+++ b/activerecord/test/cases/type/integer_test.rb
@@ -113,7 +113,7 @@ module ActiveRecord
test "values which are out of range can be re-assigned" do
klass = Class.new(ActiveRecord::Base) do
self.table_name = 'posts'
- attribute :foo, Type::Integer.new
+ attribute :foo, :integer
end
model = klass.new
diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb
index b0f34e5f47..f4f316f393 100644
--- a/activerecord/test/cases/validations_test.rb
+++ b/activerecord/test/cases/validations_test.rb
@@ -150,7 +150,7 @@ class ValidationsTest < ActiveRecord::TestCase
def test_numericality_validation_with_mutation
Topic.class_eval do
- attribute :wibble, ActiveRecord::Type::String.new
+ attribute :wibble, :string
validates_numericality_of :wibble, only_integer: true
end