From 8c793aa88b9d116f7d17eec23f4038e1f60a8dfb Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 7 Jul 2020 21:15:49 +0900 Subject: [PATCH] Allow attribute's default to be configured but keeping its own type ```ruby class Post < ActiveRecord::Base attribute :written_at, default: -> { Time.now.utc } end # Rails 6.0 Post.type_for_attribute(:written_at) # => # # Rails 6.1 Post.type_for_attribute(:written_at) # => # ``` This is an alternative of #39797. Context https://github.com/rails/rails/pull/39797#issuecomment-655191817. If people intend to override the existing type on the attribute, usually an overriding type is explicitly specified, so I agree that the current behavior (drop existing type information if type is omitted) is practically quite useless, and it is almost like a bug in that there is no way to override just the default. So I'd like to change the current behavior on existing attributes without a deprecation as a fix. Closes #39797. See also https://github.com/kufu/activerecord-bitemporal/pull/57. --- activerecord/CHANGELOG.md | 16 ++++++++++++++++ activerecord/lib/active_record/attributes.rb | 2 +- activerecord/test/cases/attributes_test.rb | 12 ++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index dcf79c7eb7..289b07a29a 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,19 @@ +* Allow attribute's default to be configured but keeping its own type. + + ```ruby + class Post < ActiveRecord::Base + attribute :written_at, default: -> { Time.now.utc } + end + + # Rails 6.0 + Post.type_for_attribute(:written_at) # => # + + # Rails 6.1 + Post.type_for_attribute(:written_at) # => # + ``` + + *Ryuta Kamizono* + * Allow default to be configured for Enum. ```ruby diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb index d0d3d38a78..be19d8b35d 100644 --- a/activerecord/lib/active_record/attributes.rb +++ b/activerecord/lib/active_record/attributes.rb @@ -253,7 +253,7 @@ def load_schema! # :nodoc: when Proc type = type[type_for_attribute(name)] else - type ||= Type::Value.new + type ||= type_for_attribute(name) end define_attribute(name, type, **options.slice(:default)) diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb index 37e6307eb8..18da7c532f 100644 --- a/activerecord/test/cases/attributes_test.rb +++ b/activerecord/test/cases/attributes_test.rb @@ -56,6 +56,18 @@ class CustomPropertiesTest < ActiveRecord::TestCase assert_equal 255, UnoverloadedType.type_for_attribute("overloaded_string_with_limit").limit end + test "overloaded default but keeping its own type" do + klass = Class.new(UnoverloadedType) do + attribute :overloaded_string_with_limit, default: "the overloaded default" + end + + assert_equal 255, UnoverloadedType.type_for_attribute("overloaded_string_with_limit").limit + assert_equal 255, klass.type_for_attribute("overloaded_string_with_limit").limit + + assert_nil UnoverloadedType.new.overloaded_string_with_limit + assert_equal "the overloaded default", klass.new.overloaded_string_with_limit + end + test "extra options are forwarded to the type caster constructor" do klass = Class.new(OverloadedType) do attribute :starts_at, :datetime, precision: 3, limit: 2, scale: 1 -- GitLab