1

RailsモデルでENUMを使用する場合、これは驚くべきコードです

  STATUS = {  approval: 0, 
              rejected: 1, 
              idle: 2, 
            }

  def status
    STATUS.key(read_attribute(:status))
  end

  def status=(s)
    write_attribute(:status, STATUS[s])
  end

どのモデルに貼り付けてもうまく機能し、まさに問題です。私はそれを何度も使用しているので、コードを DRY に保ちたいと思います。

にコピーしようとしましたapplication_helper.rbが、うまくいきません。他のすべてのモデルで繰り返さずに機能させる最良の方法は何ですか

コードクレジット: http://www.kensodev.com/tag/enum/

4

1 に答える 1

1

そのコードは、モジュールに抽象化できます。

# 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

libRails は、デフォルトではオートロードしません。アプリケーション構成に追加します。

# 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} 
于 2012-12-23T18:30:58.440 に答える