Ruby on rails 妥善贮存“废物”;“枚举”;Rails中的模型

Ruby on rails 妥善贮存“废物”;“枚举”;Rails中的模型,ruby-on-rails,Ruby On Rails,如果问题有点不准确,我深表歉意,但我将在下面描述我的问题 我在一个Rails项目中设置了一些模型,我注意到我多次遇到的一件事是处理满足以下条件的属性: 可以将它们设置为一组预定义的小值之一 这些值需要有名称和标识符(无论是数字id、代码还是其他) 这些值只有在大量代码更改后才会更改 例如,我的一个模型应该有一个状态字段,该字段可以设置为:定义、执行或完成。我需要在接口中显示这些特定的单词,但我不想将字符串存储在DB中,以防将来需要更改它们(或国际化,或其他) 显而易见的选择是为这些模型中的每

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

我在一个Rails项目中设置了一些模型,我注意到我多次遇到的一件事是处理满足以下条件的属性:

  • 可以将它们设置为一组预定义的小值之一
  • 这些值需要有名称和标识符(无论是数字id、代码还是其他)
  • 这些值只有在大量代码更改后才会更改
例如,我的一个模型应该有一个
状态
字段,该字段可以设置为:定义、执行或完成。我需要在接口中显示这些特定的单词,但我不想将字符串存储在DB中,以防将来需要更改它们(或国际化,或其他)

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

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


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

听起来您可能需要一台状态机,请参阅此处:

把它放在一个模块中并混合到模型中如何:

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
并检索一个字符串:

m.status # "Defining"

看看我一直在开发的ruby gem。我很确定这正是你想要的。自述文件有一些示例用法,但前提是它允许您将多个枚举成员定义为具有不同属性的类。

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


(用于与Jason合作,我们在几个rails应用程序中使用了这一功能的前身,特别是当用户从选择标记中选择选项时)

在数据库中定义
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
class Foo

如果比这更复杂,你应该试试@Beerlington's gem。

当我遇到这个问题时,我正在寻找类似的解决方案。我喜欢它干净简单的DSL


如果您的州包含大量特定于州的知识,那么scaney建议的状态机gen可能是一个好主意。另一个选择是使用好的旧的

为了完整起见,Rails从4.1开始就有了一个类。

这种方式的问题是,您只得到一堆字符串,这些字符串不告诉您每个状态的含义。您仍然需要向应用程序添加逻辑来处理每个状态的行为。在这一点上,你最好使用gem。@Beerlington是的,这取决于业务逻辑有多复杂。我们没有足够的信息来判断这一点,所以我建议采用最简单的方法。对于更复杂的场景,我认为您的gem会运行得很好。比灵顿是对的,我的情况可能会变得更复杂,但这仍然值得投票,因为这是一个非常好的解决方案,如果不存在复杂性,应该考虑。@elsurudo谢谢!自从我第一次发布这篇文章以来,它已经走过了很长的一段路,如果你最终使用它,我将非常希望得到反馈。@Beerlington我终于找到了正确的提问方式,这样我就可以找到你的宝石;这是一个优雅、简单、强大的解决方案,解决了我在众多Rails项目中反复解决的问题。我强烈推荐给别人!
class Foo < ActiveRecord::Base
  STATUS_DESCRIPTIONS = %w(Defining Executed Completed)

  def status
    STATUS_DESCRIPTIONS[ read_attribute(:status) ]
  end
end