Ruby on Rails 5.2.0.beta2が出て久しい。

僕はRails大好きっ子なので

社内の新規事業や、社外のお手伝いしているベンチャー企業では
もちろん、Rails5.2を使って開発をしている。

すでに、新しいRailsに関する記事はいくつか挙がっているが
個人的に、一番インパクトが大きかったのはActiveModel::Attributesが導入されたことである。

:yellow_heart: 待望のActiveModel::Attributes :yellow_heart:

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 を通じてか
多くのプロジェクトでFormObjectServiceObject(っぽいもの)を見る機会が増えた。

みんな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(value).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使いたいーって話があったので

それっぽいものを使えるようにしました。
(サクッと作っただけなので、安定するのは来週かも)

https://github.com/alpaca-tc/active_model_attributes

# 来週ぐらいにはruby gemsに出そうかな
gem 'active_model_attributes', github: 'alpaca-tc/active_model_attributes'
class YourModel
  include ActiveModel::Model
  include ActiveModelAttributes # Rails5.2になったら、消すだけ。

  attribute :accepted, :boolean, default: false
end

これで、日々の開発が少し幸せになりそうです。

毎年、とても興奮するアップデートをいれてくださるRailsコミュニティには
本当に感謝しています。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.