概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Rails 6.1 allows attribute's default to be configured but keeping its type | Saeloun Blog
- 原文公開日: 2020/11/15
- 著者: Romil Mehta
- サイト: Saeloun Blog
Rails 6.1: 属性にデフォルト値を設定しても型が失われなくなった(翻訳)
Railsでは、属性の型を変更することも、デフォルト値を設定することもできます。
以下のように、Message
クラスにdatetime
型のsent_at
属性があるとしましょう。
class Message
end
> Message.type_for_attribute(:sent_at)
=> <ActiveRecord::Type::DateTime:0x00007fa01c1fd650 @precision=6, @scale=nil, @limit=nil>
> Message.new.sent_at
=> nil
このsent_at
属性の型を以下の方法でinteger
に変更できます。
class Message
attribute :sent_at, :integer
end
> Message.type_for_attribute(:sent_at)
=> <ActiveModel::Type::Integer:0x00007fa01bd86ba8 @precision=nil, @scale=nil, @limit=nil, @range=-2147483648...2147483648>
default:
オプションを指定すればデフォルト値も設定できます。
class Message
attribute :sent_at, default: -> { Time.now.utc }
end
> Time.now.utc
=> 2020-10-15 12:10:16 UTC
> Message.new.sent_at
=> 2020-10-15 12:10:16 UTC
しかしここで問題なのは、Railsは属性にデフォルト値を設定するときに属性の型も変更しますが、そのときに正しい型が失われてしまうことです(訳注: 型がType::Value
になってしまいます)。
> Message.type_for_attribute(:sent_at)
=> <ActiveModel::Type::Value:0x00007fd16d255418 @precision=nil, @scale=nil, @limit=nil>
⚓ Rails 6.1での変更
Rails 6.1でこの問題が修正されました(#39830)。
class Message
attribute :sent_at, default: -> { Time.now.utc }
end
> Time.now.utc
=> 2020-10-15 12:10:16 UTC
> Message.new.sent_at
=> 2020-10-15 12:10:16 UTC
> Message.type_for_attribute(:sent_at)
=> <ActiveRecord::Type::DateTime:0x00007fa01c1fd650 @precision=6, @scale=nil, @limit=nil>
上のように、デフォルト値に基づいてActiveRecord::Type::DateTime
が設定され、型が失われなくなります。