そのコードは、モジュールに抽象化できます。
# lib/enumable.rb
module Enumable
extend ActiveSupport::Concern
module ClassMethods
def enum(name, options)
map = Hash[options.each_with_index.map { |e, i| [e, i] }]
const_set(name.to_s.pluralize.upcase, map)
define_method name do
map.key(read_attribute(name))
end
define_method "#{name}=" do |value|
write_attribute(name, map[value])
end
end
end
end
lib
Rails は、デフォルトではオートロードしません。アプリケーション構成に追加します。
# config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
新しいモジュールをモデルに含めます。
# app/models/project.rb
class Project < ActiveRecord::Base
include Enumable
enum :status, [:approval, :rejected, :idle]
end
$ rails c
Loading development environment (Rails 3.2.9)
1.9.3-p327 :001 > project = Project.new
=> #<Project id: nil, status: nil, created_at: nil, updated_at: nil>
1.9.3-p327 :002 > project.status = :rejected
=> :rejected
1.9.3-p327 :003 > project.status
=> :rejected
1.9.3-p327 :004 > Project::STATUSES
=> {:approval=>0, :rejected=>1, :idle=>2}