首页 > 解决方案 > rails_admin 不允许我将枚举字段保留为 nil

问题描述

模型:

class Reservation < ApplicationRecord
  # https://naturaily.com/blog/ruby-on-rails-enum
  enum recurrence: {
    daily: 0,
    weekly: 1,
    monthly: 2,
    annually: 3
  }, _prefix: :recurring

  belongs_to :user

  validates :name, :user_id, presence: true
  ...
end

移民:

class CreateReservations < ActiveRecord::Migration[5.2]
  def change
    create_table :reservations do |t|
      t.string 'name', null: false
      ...
      t.boolean 'recurring', default: false, null: false
      t.integer 'recurrence', index: true, allow_blank: true, default: nil # trying a lot of things here
      t.datetime 'expire_time'
      ...
    end
  end
end

在控制台中按预期工作:

2.4.5 :002 > res = Reservation.new(name: 'test', user_id: 1)
 => #<Reservation id: nil, name: "test", recurring: false, recurrence: nil, date: nil, start_time: nil, end_time: nil, expire_time: nil, user_id: 1, created_at: nil, updated_at: nil>

2.4.5 :003 > res.valid?
  User Load (0.7ms)  SELECT  "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
 => true

2.4.5 :004 > res.save
   (0.2ms)  BEGIN
  Reservation Create (0.5ms)  INSERT INTO "reservations" ("name", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "test"], ["user_id", 1], ["created_at", "2019-09-24 20:42:40.933959"], ["updated_at", "2019-09-24 20:42:40.933959"]]
   (2.1ms)  COMMIT
 => true

2.4.5 :005 > res.reload
  Reservation Load (0.3ms)  SELECT  "reservations".* FROM "reservations" WHERE "reservations"."id" = $1 LIMIT $2  [["id", 5], ["LIMIT", 1]]
 => #<Reservation id: 5, name: "test", recurring: false, recurrence: nil, date: nil, start_time: nil, end_time: nil, expire_time: nil, user_id: 1, created_at: "2019-09-24 20:42:40", updated_at: "2019-09-24 20:42:40"> 

2.4.5 :006 > res.recurrence
 => nil 

然而,在 Rails Admin 中,当我创建或编辑记录时,它们都被分配给第一个枚举。即使我故意从表单中删除该值,它仍会使用第一个枚举值保存记录。

导轨管理员:

config.model Reservation do
    weight 2
    parent Event
    list do
      field :name
      field :display_date do
        formatted_value { bindings[:object].display_date }
      end
      field :recurrence, :active_record_enum # should be unnecessary, but trying everything
      field :expire_time
      field :user do
        label 'Creator'
        formatted_value { bindings[:object].user.name }
      end
    end
  end

我努力了:

如建议的那样,这是日志的相关部分:

Started POST "/admin/reservation/new" for ::1 at 2019-09-25 10:09:50 -0400
Processing by RailsAdmin::MainController#new as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"VbhHM7YD+oQvwMYIQzMHyT5e0MXFFuN3pyH/1s6yM8n6kqKvywZ5E8zaABMKhOU+oWpfU1Kk55FWYjL9TzbkbQ==", "reservation"=>{"name"=>"logs", "date"=>"", "start_time"=>"", "end_time"=>"", "recurring"=>"0", "recurrence"=>"", "expire_time"=>"", "start_time_of_day"=>"", "end_time_of_day"=>"", "day_of_week"=>"", "date_of_month"=>"", "date_of_year"=>"", "user_id"=>"1"}, "return_to"=>"http://localhost:3000/admin/reservation", "_save"=>"", "model_name"=>"reservation"}
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
   (0.2ms)  BEGIN
  User Load (0.6ms)  SELECT  "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Reservation Create (0.4ms)  INSERT INTO "reservations" ("name", "recurrence", "day_of_week", "date_of_month", "date_of_year", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id"  [["name", "logs"], ["recurrence", 0], ["day_of_week", ""], ["date_of_month", ""], ["date_of_year", ""], ["user_id", 1], ["created_at", "2019-09-25 14:09:50.926864"], ["updated_at", "2019-09-25 14:09:50.926864"]]
   (1.3ms)  COMMIT
Redirected to http://localhost:3000/admin/reservation
Completed 302 Found in 26ms (ActiveRecord: 3.0ms)

而且,果然参数"recurrence"=>""被转换成["recurrence", 0]

这似乎是一个已知问题,但如果它是一个合法的错误,我仍然需要解决方法的帮助。有人已经解决了这个问题吗?

标签: ruby-on-railsenumsruby-on-rails-5rails-admin

解决方案


这在技术上可行,但我认为这不是理想的解决方案:

如果您将枚举声明为哈希(而不是数组)并且不将任何内容分配给 0,则它可以工作。

在我的情况下enum recurrence: { daily: 0, weekly: 1, monthly: 2, annually: 3 }变成enum recurrence: { daily: 1, weekly: 2, monthly: 3, annually: 4 }

日志显示参数未传递给 SQL:

Started POST "/admin/reservation/new" for ::1 at 2019-09-25 10:21:17 -0400
Processing by RailsAdmin::MainController#new as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"Joyg5VuquwMMKg+ps2zg9t+8r0DZ0iOIkqRlk1cBkemJpkV5Jq84lO8wybL62wIBQIgg1k5gJ25j56i41oVGTQ==", "reservation"=>{"name"=>"test3", "date"=>"", "start_time"=>"", "end_time"=>"", "recurring"=>"0", "recurrence"=>"", "expire_time"=>"", "start_time_of_day"=>"", "end_time_of_day"=>"", "day_of_week"=>"", "date_of_month"=>"", "date_of_year"=>"", "user_id"=>"1"}, "return_to"=>"http://localhost:3000/admin/reservation", "_save"=>"", "model_name"=>"reservation"}
  User Load (1.2ms)  SELECT  "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
   (0.2ms)  BEGIN
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Reservation Create (1.3ms)  INSERT INTO "reservations" ("name", "day_of_week", "date_of_month", "date_of_year", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"  [["name", "test3"], ["day_of_week", ""], ["date_of_month", ""], ["date_of_year", ""], ["user_id", 1], ["created_at", "2019-09-25 14:21:17.091292"], ["updated_at", "2019-09-25 14:21:17.091292"]]
   (5.7ms)  COMMIT

参数包含"recurrence"=>"",但INSERT INTO没有recurrence像以前那样的数组。

我在控制台中确认:

2.4.5 :001 > res = Reservation.first
  Reservation Load (0.4ms)  SELECT  "reservations".* FROM "reservations" ORDER BY "reservations"."id" ASC LIMIT $1  [["LIMIT", 1]]
 => #<Reservation id: 4, name: "test3", date: nil, start_time: nil, end_time: nil, recurring: false, recurrence: nil, expire_time: nil, start_time_of_day: nil, end_time_of_day: nil, day_of_week: "", date_of_month: "", date_of_year: "", user_id: 1, created_at: "2019-09-25 14:21:17", updated_at: "2019-09-25 14:21:17"> 
2.4.5 :002 > res.recurrence
 => nil 

但是,在我看来,我只是传递了一个不允许的值并让 Rails 拒绝它。这似乎仍然是 Rails Admin 的问题,特别是整数枚举。


推荐阅读