代码之家  ›  专栏  ›  技术社区  ›  Ryan Brunner

“枚举”模型在Rails中的正确存储

  •  18
  • Ryan Brunner  · 技术社区  · 14 年前

    如果这个问题有点不准确,我深表歉意,但我将在下面描述我的问题。

    我在一个Rails项目中建立了一些模型,我注意到有一件事我遇到过很多次,那就是处理满足以下条件的属性:

    • 它们可以设置为一个小的预定义值集
    • 这些值需要有一个名称和一个标识符(无论是数字id、代码还是其他什么)
    • 这些值只会因为大量代码更改而更改。

    例如,我的一个模型应该有 status 可设置为以下之一的字段:定义、执行或完成。我需要在接口中显示这些特定的单词,但我不想将字符串存储在数据库中,以防将来需要更改它们(或国际化,或其他)

    显而易见的选择是为这些模型中的每一个定义模型,但这似乎会在维护模型、确保我为每一个模型编写环境之间的迁移等方面带来很大的开销,这似乎是一个很大的开销。

    另一个选择是将其存储为整数,并创建一个“枚举”类型类来存储这些值的转换-这可能会很好,但我担心会丢失关联和从ActiveRecord模型中获得的其他方便的东西。

    关于处理这种情况的最佳方法有什么建议吗?

    7 回复  |  直到 14 年前
        1
  •  13
  •   Peter Brown    14 年前

    看看我一直在做的红宝石 classy_enum . 我很确定它正是你想要的。自述文件有一些示例用法,但前提是它允许您将多个枚举成员定义为可以具有不同属性的类。

        2
  •  12
  •   Adam Lassek    14 年前

    定义 varchar ENUM 在数据库中并验证模型中的字段:

    validates_inclusion_of :status, :in => %w(Defining Executed Completed)
    

    Rails将把它视为一个字符串字段,但它仍然验证值是什么。

    如果确实需要提取状态字段的文本,可以将其保存为整数:

    class Foo < ActiveRecord::Base
      STATUS_DESCRIPTIONS = %w(Defining Executed Completed)
    
      def status
        STATUS_DESCRIPTIONS[ read_attribute(:status) ]
      end
    end
    

    如果事情变得更复杂,你应该试试“比灵顿的宝石”。

        3
  •  2
  •   Pascal Lindelauf    11 年前

    当我遇到 enumerize gem . 我喜欢简洁的DSL。

    如果您的状态包含很多特定于状态的知识,那么scaney建议的状态机gen可能是一个好主意。另一种选择是使用旧的 state pattern state_pattern gem .

        4
  •  1
  •   scaney    14 年前

    听起来你可能想要一台状态机,请看这里: https://github.com/pluginaweek/state_machine

        5
  •  1
  •   zetetic    14 年前

    把它放在一个模块中并把它混合成模型:

    module StatusCodes
      DEFINING = 1
      EXECUTING = 2
      COMPLETED = 3
    
      def status
        return "" unless self[:status] # handle nil
        const_lookup = self[:status] - 1 # index to module constants
        StatusCodes.constants[const_lookup].to_s.downcase.camelcase # note: needs Ruby 1.9
      end
    end
    
    class MyModel < ActiveRecord::Base
      include StatusCodes
    end
    

    现在添加一个整数 status 列到模型,您可以这样分配:

    m = MyModel.new(:status=>StatusCodes::DEFINING)
    

    并检索字符串:

    m.status # "Defining"
    
        6
  •  0
  •   Jed Schneider    14 年前

    与其他优秀选项一起,如果您选择了最后一个选项,则可以使用此选项:

    http://github.com/jasondew/coded_options

    (以前和Jason一起工作,我们在几个rails应用程序中使用了它的前身,特别是当用户从select标记中选择选项时)

        7
  •  0
  •   ldnunes    9 年前

    为了完整起见,Rails有一个 Enum 从4.1开始上课。