Mic*_*ans 2 ruby activerecord ruby-on-rails
enum在 Rails 和 ActiveRecord 中,我正在努力解决模型中的行为。首先,default当我运行测试时,我在 AR 迁移中在数据库级别设置的 没有生效,其次,我根本无法更新它。这是一些代码,为了简洁起见,进行了简化。
在我的模型中,枚举声明如下:
class MyModel < ApplicationRecord
# as you can see this is a join table for different_model and another_model
belongs_to :different_model
belongs_to :another_model
enum blocked: %w[no yes] # also tried with symbols, like: %i[no yes]
end
Run Code Online (Sandbox Code Playgroud)
迁移如下:
class AddBlockedToMyModel < ActiveRecord::Migration[5.2]
def change
add_column :my_models, :blocked, :integer, default: 0
end
end
Run Code Online (Sandbox Code Playgroud)
我使用以下方法创建对象:
my_model = MyModel.where(different_model: @different_model, another_model: @another_model).first_or_create
Run Code Online (Sandbox Code Playgroud)
这有效,我曾经byebug检查过该记录是否持久存在(因此也有效)
然后尝试更新blocked它的枚举:
my_model.update(blocked: 'yes')
Run Code Online (Sandbox Code Playgroud)
但blocked属性仍保持为nil.
我重构,尝试使用:
my_model.blocked = 'yes'
my_model.save
Run Code Online (Sandbox Code Playgroud)
并卡byebug在中间看看它是否无效,但事实并非如此。改为后.valid?返回,所以我也尝试将其改为整数,保存后仍然返回为。trueblocked'yes'1nil
仅在运行测试时才会出现此问题。当rails console一切都按照我的预期运行时——default数据库级别接管并实例化模型,并且它也可以以任何常见的blocked: 'no'AR 方式进行更新,只是不在测试中。我在这里错过了一些非常明显的东西,还是我没有得到一些奇怪的副作用?enum
DB 是 Postgres,以防有所不同。
1)尽量避免使用yesandno作为枚举值。Rails 将为每个值创建方法,例如#yes?、 、#no!,并且如果您需要为不同的字段添加另一个是/否枚举,它可能无法按您的预期工作。
更好地定义它就像
enum status: [:released, :blocked]
Run Code Online (Sandbox Code Playgroud)
或者我实际上更喜欢哈希表示来明确存储哪些数据库值:
enum status: {
released: 0,
blocked: 1
}
Run Code Online (Sandbox Code Playgroud)
然后,不用调用update!,只需调用
your_instance.blocked!
Run Code Online (Sandbox Code Playgroud)
它会做到这一点。
2)作为一般建议,在数据库中将此字段设置为不可为空(因为我假设您不希望此字段此时具有三种状态):
change_column_null :table_name, :column_name, true
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5494 次 |
| 最近记录: |