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

问题描述:

我有一个用户模型,它有一个状态。该状态可以是这些:“未经验证的”,“主动”,“删除”]Ruby on Rails ActiveRecord:我应该如何存储对象的状态?

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

我应该创建三个布尔字段吗?这不会有什么意义,因为我可能想要轻松扩展状态的数量,并且只有一个状态可以同时为“真”。

我应该使用state_machine宝石只为固定值的简单切换?

或有任何其他常见的方式,最好的做法,或者一个简单的宝石这样的工作吗?

一个非常简单的解决方案,我已经使用这个:

在迁移

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 

我会将它保留为零,'激活','删除'。如果您希望在切换状态时有额外的进程挂钩,例如发送的电子邮件,那么state_machine gem会很有用。另外,如果您希望有其他分析功能,例如某人从未验证状态变为活动状态,可能会有用'active_on_date',并在转换发生时将其存储为日期时间。

您可以使用一个枚举类型的状态存储为一个简单的整数。我通常使用active_enum宝石来简化。这将是这个样子

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

+0

我真的很喜欢这个实现,除了ID不会以参照完整性存储在数据库中。 – fregas 2012-03-06 21:40:53

+0

这是一个很好的观点。除了实现一个'''State''模型的解决方案,这是正确的吗? – 2012-03-06 22:08:22

请勿使用布尔字段。

如果国家的名字就像一个“钥匙”,并不会改变,你可以将它们存储在数据库中的文本字段。只需使用

add_column :users, :state, :string 

添加迁移当您保存对象时,它会采取user.state和符号存储为“未验证”,“活动”等

如果状态是一个字符串可能会在某个时间点重新命名,那么您可以将它们放入自己的表格中,并为它们制作自己的主动记录模型,而不是使用符号。做一个

rails g model State name:string 

轨道将创建一个模型文件和他们的迁移。然后用这个改变迁移:

add_column :users, :state_id, :integer 

您可以使用未经验证,活跃等直接在SQL或通过种子或现有的迁移填充状态列表。如果需要,您也可以在它们之间创建一个外键。

然后在你的代码,以设置状态,你这样做:

user.state = State.find_by_name(:unverified) 
+0

您确定要将'state'列存储为'text'吗?它看起来好像是一个“字符串”。 – jaredonline 2012-03-06 20:49:29

+0

是的,你是对的。我正是这个意思。现在编辑。 – fregas 2012-03-06 21:21:29

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