rails_admin不会让我将枚举字段保留为nil

时间:2019-09-25 14:04:14

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

型号:

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中,当我创建或编辑记录时,它们都分配给了第一个枚举。即使我有意从表单中删除该值,它仍会保存带有第一个枚举值的记录。

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

我尝试过:

  • 不对该字段建立索引(认为Rails Admin希望为索引列提供一个值)
  • 确保在`field:recurrence`上声明`:active_record_enum`。

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

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]

这似乎是known issue,但如果是合法错误,我仍然需要有关解决方法的帮助。有人解决了吗?

2 个答案:

答案 0 :(得分:1)

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

如果您将枚举声明为哈希(而不是数组),并且未将任何赋值为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的问题,尤其是整数枚举。

答案 1 :(得分:0)

由于nil values should work,可能限制了使用哈希。由于要将它们映射到0索引值,因此应该只使用符号数组。 ActiveRecord :: Enum文档(上面链接)指出:

  

请注意,使用数组时,从值到数据库整数的隐式映射是根据值在数组中出现的顺序得出的。在示例中,:active作为第一个元素映射为0,而:archived映射为1。通常,数据库中第i个元素映射为i-1。

因此,您应该能够为此使用符号数组。