はじめに
Rails で User モデルに status というカラムがあるとき、
Rails.env.production?
のように
user.status.active?
と書きたいときがあります。その書き方の例です。
シンプルな実装
ActiveSupport::StringInquirer もしくは、String#inquiry メソッドを使うと簡単に実装できます。
Userモデルには string 型の status というカラムがあるものとします
app/mode/user.rb
class User < ApplicationRecord
def status
attribute(:status).inquiry
end
end
[1] pry(main)> user = User.new
=> #<User:0x3ff520751674>
[2] pry(main)> user.status = :active
=> :active
[3] pry(main)> user.status.active?
=> true
[4] pry(main)> user.status = :inactive
=> :inactive
[5] pry(main)> user.status.active?
=> false
[6] pry(main)> user.status.inactive?
=> true
簡単ですね。
ちょっと凝った実装
1個のモデルの1個の属性だけにこれを適用するならば良いのですが、数が増えてくると同じようなことを何度も書く必要が出て来ます。
そんなときは、クラスマクロを実装して、シンプルに済ませませましょう。
app/mode/application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
class << self
def inquiry *attrs
attrs.each do |attr|
define_method attr.intern do
attribute(attr).inquiry
end
end
end
end
end
app/mode/user.rb
class User < ApplicationRecord
inquiry :status
end
試してみましょう。
[1] pry(main)> user = User.new
=> #<User:0x3fcca0cb0c58>
[2] pry(main)> user.status = :active
=> :active
[3] pry(main)> user.status.active?
=> true
[4] pry(main)> user.status = :inactive
=> :inactive
[5] pry(main)> user.status.active?
=> false
[6] pry(main)> user.status.inactive?
=> true
同じように動きますね。引数は複数取るようにしたので、
class User < ApplicationRecord
inquiry :status, :gender
end
のように書くと
user.gender.female?
=> true
のようなメソッドも使えるようになります。
参考
ActiveSupport::StringInquirer
http://api.rubyonrails.org/classes/ActiveSupport/StringInquirer.html