Ruby on Rails 5.2.0.beta2
が出て久しい。
僕はRails大好きっ子なので
社内の新規事業や、社外のお手伝いしているベンチャー企業では
もちろん、Rails5.2を使って開発をしている。
すでに、新しいRailsに関する記事はいくつか挙がっているが
個人的に、一番インパクトが大きかったのはActiveModel::Attributes
が導入されたことである。
待望のActiveModel::Attributes
ActiveModel::Attributes
でなにが変わったの?というと、
いままでActiveRecordでしか使えなかった一部の機能が、ActiveModelでも使えるようになっただけである。
いや、しかし!
今までのActiveModelの最大の弱点は
まさにこの ActiveModel::Attributes
が無かったことだと思う。
それが、Rails5.2で使えるようになったのだ。
こんな嬉しいことはない。
みんな大好き .attribute
Rails5.1系でも使えた.attribute
を改めてみてみよう
ActiveRecordには、Attribute APIというインターフェース(?)があり、
型情報の変換は、あまり考えることなく透過的に扱うことができる。
class User < ApplicationRecord; end
id = '1' # 文字列
user = User.new(id: '1')
user.id #=> 1 数値に変換されている
そして、この型変換は定義を上書きすることもできる
class User < ApplicationRecord
attribute :time_zone, :string, default: -> { Time.zone.name }
attribute :confirmed, :boolean, default: false
end
user = User.new
user.time_zone == Time.zone.name #=> true
user.confirmed == false #=> true
独自の型変換もOKなので、 Money
などのクラスを定義して型変換を行わせることもできる。
カラムがなくてもOKなので、attr_accesor
の代わりに使える。
すこぶる便利である。
しかし、ActiveRecordでしか使えないのである。
さて、ActiveModelの話ですよ。
7 Patterns to Refactor Fat ActiveRecord Models を通じてか
多くのプロジェクトでFormObject
やServiceObject(っぽいもの)
を見る機会が増えた。
みんなFormObject
をActiveModelで定義するのだが
その型変換には定まった方法が無かった。
class RegistrationForm
include ActiveModel::Model
attr_accessor :accepted
end
RegistrationForm.new(xxx_params).accepted #=> 型はなに??
そして、その解決策は人によって様々で
これといった最善策は無かった。
class RegistrationForm
include ActiveModel::Model
attr_reader :accepted
# まともな変換
def accepted=(value)
@accepted = ActiveModel::Type.lookup(:boolean).cast(value)
end
# なんてこった...
def accepted=(value)
@accepted = value == '1'
end
end
そもそも、記述量も多いしイケテナイ感がありました。
ほら、ここでActiveModel::Attributes
ですよ。
ようやく、秩序が保たれる時代になりました。
.attribute
がActiveModelでも使えるようになったのです。
class RegistrationForm
include ActiveModel::Model
include ActiveModel::Attributes
attribute :accepted, :boolean, default: false
end
もうね、大興奮です。
めっちゃシンプル。
誰でも同じ書き方になる。
AttributeMethodsも使える...。
ありがてぇ。ありがてぇよ。
Rails5.1だとまだ使えない
使えないんです、そうなんです。
社内の人と話していて、他のプロジェクトでも.attribute
使いたいーって話があったので
それっぽいものを使えるようにしました。
# 来週ぐらいにはruby gemsに出そうかな 同じ名前ですでにgemが存在したため、gem pushできず...!みんな同じようなこと考えるのね。。
https://github.com/alpaca-tc/active_model_attributes
gem 'active_model_attributes', github: 'alpaca-tc/active_model_attributes'
class YourModel
include ActiveModel::Model
include ActiveModelAttributes # Rails5.2になったら、ActiveModel::Attributesに置き換えるだけ。
attribute :accepted, :boolean, default: false
end
これで、日々の開発が少し幸せになりそうです。
毎年、とても興奮するアップデートをいれてくださるRailsコミュニティには
本当に感謝しています。