【问题标题】:validates_presence_of fails with enumvalidates_presence_of 因枚举而失败
【发布时间】:2015-11-04 03:45:47
【问题描述】:

使用 Rails 4.2.1。我有一个带有枚举字段的模型:

class MyModel < ActiveRecord::Base
  enum my_enum: { first_value: 0, second_value: 1 }
  validates_presence_of :my_id, :username, :my_enum
end

在控制器中,我正在尝试保存模型:

my_model = MyModel.find_or_initialize_by(my_id: my_id)
my_model.update(username: username, my_enum: :first_value)

这给了我Validation failed: My enum can't be blank

在保存之前将所需的属性分配给对象,如下所示:

my_model.username = username
my_model.first_value!

甚至

my_model.username = username
my_model.my_enum = 0
my_model.save!

产生相同的结果。

这是否意味着validates_presence_of 不能与枚举一起使用?如果确实如此,那么根本原因是什么?

【问题讨论】:

    标签: ruby-on-rails validation activerecord enums


    【解决方案1】:

    这不是错误。问题是my_enum 列的类型是string,而我试图保存一个整数。替换

    enum my_enum: { first_value: 0, second_value: 1 }
    

    enum my_enum: { first_value: '0', second_value: '1' }
    

    修复了问题,更改列也修复了它。

    显然,使用字符串作为枚举是/曾经是“秘密未记录的功能”。请参阅this pull request(在撰写本文时仍然开放)了解更多详情。

    【讨论】:

      【解决方案2】:

      我看到 validates_presence_of 仍然适用于枚举。这是我的模型

      # production.rb
      class Production < ActiveRecord::Base
        enum status: {active: 1, deactive: 0}
        validates_presence_of :status
      end
      

      我在rails console上测试了你的案例

      案例 1:

      2.2.0 :001 > Production.create!
         (0.1ms)  begin transaction
         (0.1ms)  rollback transaction
      ActiveRecord::RecordInvalid: Validation failed: Status can't be blank
      

      案例 2:

      2.2.0 :001 > prod = Production.find_or_initialize_by(title: "abc")
        Production Load (0.8ms)  SELECT  "productions".* FROM "productions" WHERE "productions"."title" = ? LIMIT 1  [["title", "abc"]]
       => #<Production id: nil, title: "abc", price: nil, description: nil, status: nil, created_at: nil, updated_at: nil>
      2.2.0 :002 > prod.update(price: 23, status: :active)
         (0.3ms)  begin transaction
        SQL (0.8ms)  INSERT INTO "productions" ("title", "price", "status", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?)  [["title", "abc"], ["price", 23], ["status", 1], ["created_at", "2015-11-04 05:58:43.851364"], ["updated_at", "2015-11-04 05:58:43.851364"]]
         (0.7ms)  commit transaction
       => true
      

      案例 3:

      2.2.0 :001 > prod = Production.find_or_initialize_by(title: "def")
        Production Load (0.6ms)  SELECT  "productions".* FROM "productions" WHERE "productions"."title" = ? LIMIT 1  [["title", "def"]]
       => #<Production id: nil, title: "def", price: nil, description: nil, status: nil, created_at: nil, updated_at: nil>
      2.2.0 :002 > prod.description = "bla"
       => "bla"
      2.2.0 :003 > prod.save!
         (0.2ms)  begin transaction
         (0.1ms)  rollback transaction
      ActiveRecord::RecordInvalid: Validation failed: Status can't be blank
      

      案例 4:

      2.2.0 :001 > prod = Production.find_or_initialize_by(title: "def")
        Production Load (0.6ms)  SELECT  "productions".* FROM "productions" WHERE "productions"."title" = ? LIMIT 1  [["title", "def"]]
       => #<Production id: nil, title: "def", price: nil, description: nil, status: nil, created_at: nil, updated_at: nil>
      2.2.0 :002 > prod.status = 0
       => 0
      2.2.0 :003 > prod.save!
         (0.2ms)  begin transaction
        SQL (0.8ms)  INSERT INTO "productions" ("title", "status", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["title", "def"], ["status", 0], ["created_at", "2015-11-04 06:01:16.391026"], ["updated_at", "2015-11-04 06:01:16.391026"]]
         (0.7ms)  commit transaction
       => true
      

      我使用的是 Rails 4.2.4。

      【讨论】:

      • 很奇怪,案例 2 对我来说已经失败了,验证错误。也许是 4.2.1 中的一个 bug 已经修复?
      • 我也测试了这个4.2.4,结果和你一样。
      • 这不是bug,我发现了问题,请看我的回答。感谢您的帮助!
      猜你喜欢
      • 1970-01-01
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      • 2012-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多