Help us understand the problem. What is going on with this article?

ActiveModel::Attributes が最高すぎるんだよな。

More than 1 year has passed since last update.

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(: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コミュニティには
本当に感謝しています。

alpaca_taichou
アルパカ隊長だぞーう
https://alpaca.tc
moneyforward
「お金を前へ。人生をもっと前へ。」をMissionとして、個人向け、法人向け様々なFintechサービスを開発、提供しています。
https://moneyforward.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした