【问题标题】:How to handle rails enums?如何处理 Rails 枚举?
【发布时间】:2014-01-17 08:59:31
【问题描述】:

如何处理 Rails 中的枚举?我用谷歌搜索了这个,但没有找到任何干净的解决方案。到目前为止,我已经提出了以下对使用interaction_type_id 模型的关注。这是我在数据库中的枚举表的外键。使用这种方法,我不必在我的代码中使用 id,但是当保存与 interact_type 相关的对象时,我可以说

myobject.interaction_type = :file_download

这可以使用正确的 id 持久化数据库,因为关注点(请参阅下面的关注点 - 包含在使用枚举的模型中)将返回正确的 id。

module InteractionTypeEnum
  extend ActiveSupport::Concern

  included do
    INTERACTION_TYPE = { file_download: 1, email: 2, telesales: 3, registration: 4, enrolment: 5 }
  end

  def interaction_type
    INTERACTION_TYPE.key(read_attribute(:interaction_type_id)).to_s.gsub('_',' ').capitalize
  end

  def interaction_type=(s)
    write_attribute(:interaction_type_id, INTERACTION_TYPE[s])
  end
end    

这只是感觉很重。必须有一种更简单/更清洁的方式。现在,当尝试为此编写测试时,它变得更加混乱。

在代码和数据库中需要我的枚举的大多数原因是性能(代码)和报告(数据库)。

任何帮助表示赞赏。谢谢。

【问题讨论】:

    标签: ruby-on-rails enums ruby-on-rails-4


    【解决方案1】:

    我推荐active_enum gem。

    他们文档中的示例,如果您在类 User 上有一个名为 sex 的整数列:

    class User < ActiveRecord::Base
      enumerate :sex do
        value :name => 'Male'
        value :name => 'Female'
      end
    end
    

    或者您可以在单独的类中定义枚举:

    class Sex < ActiveEnum::Base
      value 1 => 'Male'
      value 2 => 'Female'
    end
    
    class User < ActiveRecord::Base
      enumerate :sex, :with => Sex
    end
    

    我喜欢它提供的抽象,它使您不必为了存储枚举值而创建整个数据库表。

    【讨论】:

    • 不错的解决方案,但是假设您现在将用户存储在数据库中,并且您想通过后端访问用户的性别。你是说这应该作为字符串存储在数据库中 - 男性,女性。如果您的枚举集增加到 10 个项目并且在那之后不会改变会发生什么。您不希望数据库中的表中包含此信息吗?在某些情况下,您可能还希望扩展枚举以包含其他信息,例如排名/顺序或描述。我知道这是多么有用和干净,但它可能有点有限。
    • 它以整数形式存储在数据库中,并且比我在此处复制粘贴的功能要多得多(例如,您可以像您描述的那样向枚举添加扩展信息。)我建议如果只是为了了解更多信息并查看它是否适合您的目的,请尝试一下;我在多个项目中使用过它,从来没有遇到过问题。但当然这不是唯一的解决方案(我确信还有其他枚举宝石,或者您可以像其他答案一样滚动自己的)而且我并没有投入太多,其他建议也可以。跨度>
    • 我已经查看了 github。看起来真的很好,但它似乎不支持 rails 4。当我在代码中启用 config.extend_classes = [ ActiveRecord::Base ] 并尝试运行 rails console 我得到 /Users/ryanme/.rvm/gems/ruby -2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.2/lib/active_record/dynamic_matchers.rb:22:in method_missing': undefined method class_inheritable_accessor' for ActiveRecord::Base:Class (NoMethodError) -------根据我的阅读,class_inheritable_accessor 已被弃用。
    • 我看到 rails 4.1.0.beta1 内置了枚举。可能是个好方法。
    • 哦,是的,Rubygems 上的版本与 Rails 4 不兼容,这让我很困惑。尝试将 gem 'active_enum', github: 'adzap/active_enum' 添加到您的 Gemfile 中,这对我有用。该死的,我听起来像是这颗宝石的传道者,我真的不在乎,这只是我曾经费心学习的唯一解决方案!不知道 4.1.0 中会出现枚举,这听起来是一个不错的改进。
    【解决方案2】:

    我用下面的方法,说我有

    class PersonInfo < ActiveRecord::Base
      belongs_to :person_info_type
    end
    

    PersonInfoType 是一个简单的域表,包含可能的信息类型。

    然后我将我的模型编码如下:

    class PersonInfoType < ActiveRecord::Base
    
      PHONE = 1
      EMAIL = 2
      URL = 3
    
    end
    

    我有一个种子用相应的数据填充数据库。

    所以当分配一些人信息时可以做类似的事情

    person.person_infos << PersonInfo.create(:info => 'http://www.some-url.com', :person_info_type_id => PersonInfoType::URL)
    

    然后可以使用关系进一步清理此代码:

    class PersonInfo
    
      belongs_to :person_info_type
    
      def self.phones
        PersonInfo.where(:person_info_type_id => PersonInfoType::PHONE)
      end
    
    end
    
    person.person_infos << PersonInfo.phones.create(:info => '555 12345')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-02
      相关资源
      最近更新 更多