Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 6.1: 属性にデフォルト値を設定しても型が失われなくなった(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

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が設定され、型が失われなくなります。

関連記事

Rails: ActiveSupport::Concernをextendしたモジュールをprependする機能(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。