Ruby on Rails ActiveRecord:我应该如何存储对象的状态?

时间:2012-03-06 19:58:00

标签: ruby-on-rails activerecord state

我有一个用户模型,它有一个状态。州可以是以下任何一种:['未经验证','有效','已删除']

在数据库中存储对象状态的最佳方法是什么?

我应该创建三个布尔字段吗?这没有多大意义,因为我可能想要轻松扩展状态数量,同时只有一个状态可以是“真实”。

我是否应该仅使用state_machine gem来简单地切换常量值?

或者,对于这种工作,还有其他常用的方法,最佳实践或简单的宝石吗?

5 个答案:

答案 0 :(得分:17)

我用过的一个非常简单的解决方案:

在您的迁移中

add_column :users, :state, :string

在你的模特中

class User < ActiveRecord::Base

  STATES = %w{ unverified active deleted }

  STATES.each do |state|
    define_method("#{state}?") do
      self.state == state
    end

    define_method("#{state}!") do
      self.update_attribute(:state, state)
    end
  end
end

然后你可以打电话

@user.active? # => returns true/false

或者

@user.active! # => sets the users state to active

答案 1 :(得分:3)

如果您将Rails3与MySQL数据库一起使用您可以使用enum_column。它提供了:enum列何时用于迁移以及验证方法。它还提供了一个enum_select视图助手。

答案 2 :(得分:1)

我会把它留作零,'主动','删除'。如果你想在切换状态时有额外的进程挂钩,就像发送的电子邮件一样,那么state_machine gem就会很有用。此外,如果您想要进行其他分析,例如当某人从未验证状态变为活动状态时,可能有必要使用“active_on_date”并将其存储为转换发生时的日期时间。

答案 3 :(得分:1)

您可以使用枚举类型将状态存储为简单整数。我通常使用active_enum gem来实现这一点。它看起来像这样

class User

  # An enumerated type representing the current state of the user
  enumerate :state do
    value name: "unverified"
    value name: "active"
    value name: "deleted"
  end

end

这将允许您以下列方式检查状态

# check if active
user.state?(:active)

只需确保state表中有一个名为User的整数字段(或任何您想要调用的枚举类型)。

有关详细信息,请参阅gem documentation

答案 4 :(得分:1)

不要使用布尔字段。

如果状态名称类似于“键”并且不太可能更改,则可以将它们作为文本字段存储在数据库中。只需使用

添加迁移
add_column :users, :state, :string

保存对象时,将使用user.state并将符号存储为“未验证”,“活动”等字符串。

如果某些状态可能会在某个时候被重命名,那么您可以将它们放入自己的表中并为它们创建自己的activerecord模型,而不是使用符号。做一个

rails g model State name:string

rails将为它们创建模型文件和迁移。然后用这个改变迁移:

add_column :users, :state_id, :integer

您可以直接在sql中或通过种子或现有迁移来填充未验证,活动等的状态列表。如果需要,您还可以在它们之间创建外键。

然后在你的代码中,要设置状态,你可以使用它:

user.state = State.find_by_name(:unverified)