Ruby on rails Rails 5更新枚举未更新
在Rails和ActiveRecord中,我正在努力解决模型中Ruby on rails Rails 5更新枚举未更新,ruby-on-rails,ruby,activerecord,Ruby On Rails,Ruby,Activerecord,在Rails和ActiveRecord中,我正在努力解决模型中enum的行为。首先,我在AR迁移中在数据库级别设置的default在我运行测试时没有生效,其次,我根本无法更新它。下面是一些代码,为了简洁起见进行了简化 在我的模型中,枚举声明如下: class MyModel?一般不需要,但是如果你手动改变了迁移,Rails不能推断测试数据库必须重新初始化。你也可以通过:(已阻止:我的_模型。已阻止[:是]“关于布尔值在不断变化的需求中出现问题的说法是绝对正确的。您经常看到人们创建可为空的三状态布
enum
的行为。首先,我在AR迁移中在数据库级别设置的default
在我运行测试时没有生效,其次,我根本无法更新它。下面是一些代码,为了简洁起见进行了简化
在我的模型中,枚举声明如下:
class MyModel
迁移情况如下:
class AddBlockedToMyModel
我使用以下方法创建对象:
my\u model=MyModel.where(不同的\u model:@不同的\u model,另一个\u model:@另一个\u model)。首先\u或\u创建
这是有效的,我使用byebug
来检查该记录是否被持久化,并且它是否有效(因此也是有效的)
然后尝试更新其上的enumblocked
:
my_model.update(已阻止:“是”)
但是blocked
属性保持为nil
我进行了重构,尝试使用:
my_model.blocked='yes'
my_model.save
和Cux<代码> Byebug <代码>中间,看看它是否无效,它不是。code>.valid?在将
blocked
更改为'yes'
后返回true
,因此我也尝试将其更改为整数1
,保存后,它仍然返回到nil
此问题仅在运行测试时发生。在rails控制台中运行时
一切正常-数据库级别的默认值
接管并实例化模型,并使用阻塞:'no'
,它也可以以任何常规AR方式更新,只是不在测试中。我是否遗漏了一些非常明显的东西,或者是我没有得到的enum
的一些奇怪的副作用
DB是Postgres,以防产生影响。1)尽量避免使用yes
和no
作为枚举值。Rails将为每个值创建方法,例如#yes?
,#no代码>,如果您需要为不同的字段添加另一个yes/no枚举,它可能无法正常工作
最好像这样定义它
enum status: [:released, :blocked]
或者我实际上更喜欢哈希表示,以明确存储哪些DB值:
enum status: {
released: 0,
blocked: 1
}
然后,不要调用update代码>,打电话就可以了
your_instance.blocked!
它会成功的
2) 作为一般建议,在数据库中使此字段不可为空(因为我假设您现在不希望此字段具有三种状态):
change_column_null :table_name, :column_name, true
1) 尽量避免将yes
和no
作为枚举值。Rails将为每个值创建方法,例如#yes?
,#no代码>,如果您需要为不同的字段添加另一个yes/no枚举,它可能无法正常工作
最好像这样定义它
enum status: [:released, :blocked]
或者我实际上更喜欢哈希表示,以明确存储哪些DB值:
enum status: {
released: 0,
blocked: 1
}
然后,不要调用update代码>,打电话就可以了
your_instance.blocked!
它会成功的
2) 作为一般建议,在数据库中使此字段不可为空(因为我假设您现在不希望此字段具有三种状态):
change_column_null :table_name, :column_name, true
为什么不对blocked使用布尔真/假值而不是enum?同样对于enum,在散列样式中使用它们是一个很好的实践,比如enum blocked:{no:0,yes:1}
感谢@nuaky的评论,我最初考虑过这一点,但已经读到boolean可能会因需求的变化而出现问题。这个属性是通过第三方API获得的,我只是想在某一点上需求可能会发生变化。但是,不值得浪费太多的时间,所以我现在可以用一个布尔值来考虑,如果时间到了,就考虑重构。谢谢你关于散列的注释,注意到了!您是否运行了rake db:test:prepare
?通常不需要,但如果您手动更改迁移,rails无法推断测试数据库必须重新初始化。您还可以通过以下方式更新它:my\u model.update(blocked:my\u model.blocked[:yes]“
关于布尔值在不断变化的需求中存在问题的说法是完全正确的。您经常看到人们创建可为空的三状态布尔值列,这是一个很大的禁忌,因为布尔逻辑发生故障或向对象添加了大量潜在冲突的开关。为什么不使用布尔值true/false来表示blocked而不是enum?同样对于枚举,在哈希样式中使用它们是一个很好的实践,比如enum blocked:{no:0,yes:1}
感谢@nuaky的评论,我最初考虑过这一点,但我已经了解到布尔值可能会随着需求的变化而出现问题。这个属性是通过第三方API获得的,我只是认为在某个时候需求可能会发生变化。但是,这不值得浪费太多时间,所以我可能会选择布尔值现在,并考虑一个重构,如果时间到了,谢谢你的注释,注意,你运行了<代码> RAK:DB:测试:准备< /COD>?一般不需要,但是如果你手动改变了迁移,Rails不能推断测试数据库必须重新初始化。你也可以通过:(已阻止:我的_模型。已阻止[:是]“
关于布尔值在不断变化的需求中出现问题的说法是绝对正确的。您经常看到人们创建可为空的三状态布尔值列,这是一个很大的禁忌,因为布尔逻辑发生故障,或者向对象添加了大量可能冲突的开关。使用哈希并显式声明枚举是一个好主意,因为对数组进行重新排序将破坏一切