如何在rails模型中保持代码DRY



当涉及到在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

当我将它粘贴到任何模型中时,它都能很好地工作,这正是问题所在。我使用它很多次,所以我想保持代码干。

我试着把它复制到application_helper.rb,但它不起作用。在不重复所有其他模型的情况下,让它工作的最佳方法是什么?

代码来源:http://www.kensodev.com/tag/enum/

这些代码可以抽象成一个模块。

# 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

默认情况下,Rails不会自动从lib加载。将其添加到应用程序配置中。

# 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} 

最新更新