【问题标题】:rails - apply default value for enum fieldrails - 为枚举字段应用默认值
【发布时间】:2016-05-08 19:36:34
【问题描述】:

我想为我的枚举字段设置一个默认值,以防止它为 nil。我做了以下事情:

# db/schema.rb
create_table "templates", force: :cascade do |t|
  t.integer  "status"
end

# app/models/template.rb
class Template < ActiveRecord::Base
  STATUSES = [:draft, :published]
  enum status: STATUSES
  after_initialize :init

  def init
    self.status ||= STATUSES.index(:draft)
  end
end

我在本地环境中得到了预期的结果。但不完全在heroku中。在将状态更新为nil 后,我需要将其设为默认值draft,但在这种情况下,它变为nil,但published 范围仍包含更新后的行。

$ heroku run rails console

> Template.published.pluck :id
=> [1, 2]

> Template.find(1).update(status:nil)
Template Load (4.4ms)  SELECT  "templates".* FROM "templates" WHERE "templates"."id" = $1 LIMIT 1  [["id", 1]]
Template Load (4.4ms)  SELECT  "templates".* FROM "templates" WHERE "templates"."id" = $1 LIMIT 1  [["id", 1]]
(1.7ms)  BEGIN
(1.7ms)  BEGIN
(1.1ms)  COMMIT
(1.1ms)  COMMIT
=> true

> Template.find(1).status
=> nil

> Template.published.pluck :id
=> [1, 2]

这是使用枚举的正确用例吗?我的 heroku 环境是否有我遗漏的特殊性?

【问题讨论】:

  • 您是否考虑过直接从数据库级别执行此操作,通过为迁移中的状态列提供默认整数值(对应于 :draft 的值)?类似:t.integer :status, default: 1?你可能不得不做一个 change_column 相当于那个。
  • @SunnyK 我想到了,但我把它放在模型中因为索引号取决于枚举数组元素的排列,它在模型中。正在考虑这将使将来更容易更改枚举值,因为无需创建迁移来更改默认值的索引。但既然你这么说了,在我看来,更容易同意 0 处的元素是所有情况下的默认值。谢谢!
  • @SunnyK 我把它改成了那个,但我还是有同样的问题。
  • 在本地还是在推送到 Heroku 之后?如果在推送到 Heroku 后,请尝试再次手动在 Heroku 上运行迁移

标签: ruby-on-rails enums rails-activerecord


【解决方案1】:

您可以从数据库声明中设置默认值。

create_table :templates do |t|
  t.column :status, :integer, default: 0
end

然后,将关系映射如下

class Template < ActiveRecord::Base
  enum status: { draft: 0, published: 1 }
end

【讨论】:

  • 我使用了这种方法,但我仍然有问题。 @Jefferson Choi
  • 已经工作了。但是我改变了我的方法,因为枚举数组有可能改变。 Sting 比枚举更适合我的情况。
  • @MartinVerdejo 你有没有弄清楚heroku 出了什么问题?我刚刚在我的应用程序上尝试了 enumerable 并且我从 heroku 得到了一些奇怪的行为。即使我在数据库中有default: 0,如果我在属性中运行u = User.new,我也会看到role="guest" 作为字符串。然后运行u.role 得到nil。不知道发生了什么。
  • 这是一个选项,它改变数据库不是一个选项?
  • 在不编写新迁移的情况下如何实现这一目标?
【解决方案2】:

Rails 6.1+

从 Rails 6.1 开始,可以在模型中设置默认枚举值。例如:

class Template < ActiveRecord::Base
  enum status: [:draft, :published], _default: :draft
end

这里是a link to relative PRa link to the docs

导轨 7+

从 Rails 7 开始,不再需要使用前导下划线。例如:

class Template < ActiveRecord::Base
  enum status: [:draft, :published], default: :draft
end

这里是a link to relative PRa link to the docs

【讨论】:

【解决方案3】:

导轨 7

Rails 6.1 允许在模型中设置默认枚举值。

Rails 7 引入了用于定义枚举的新语法。例如

class Template < ActiveRecord::Base
  enum :status, [:draft, :published], default: :draft
end

这是link to the relevant PRlink to the edge docs

【讨论】:

    猜你喜欢
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 2013-11-21
    • 1970-01-01
    • 2011-10-14
    相关资源
    最近更新 更多