【问题标题】:Better way to return validation errors for nested models as json in Rails?在 Rails 中将嵌套模型的验证错误作为 json 返回的更好方法?
【发布时间】:2016-03-31 06:15:39
【问题描述】:

我有上课顺序,可以内容条目。并且每个条目可以是复杂类型,并且由另一个条目组成。

class Order < ActiveRecord::Base
  accepts_nested_attributes_for :entries
end

class Entry < ActiveRecord::Base
  accepts_nested_attributes_for :members, allow_destroy: true
end

在表单中,我使用 fields_for 在表单中生成了 rails 字段

<input autocomplete="off" class="string required form-control" id="order_entries_attributes_1459329286687_members_attributes_1459329286739_title" name="order[entries_attributes][1459329286687][members_attributes][1459329286739][title]" placeholder="Наименование" type="text">

所以,我提交了一份订单表格,例如有 2 个条目,5 个成员有一些验证错误(2 个成员没有标题),然后它传递给控制器​​

class OrdersController
  def update
    if @order.update(order_params)
      render json: @order
    else
      render json: @order.errors, status: :unprocessable_entity
    end
  end
end

它还给我这个

{"entries.members.title":["cant be blank"]}

问题是我找不到其中的哪个条目和哪个成员,存在验证错误,这就是为什么我不能突出显示该字段的原因。此外,它合并了类似的错误。这就是问题。

在提交时,我传递了唯一索引(在名称属性中),rails 正确地使用它来创建嵌套模型,如果错误响应包含这个索引会很好。

有没有其他方法可以从服务器返回漂亮的索引错误,并使用 rails 作为 json 的 api 而不会痛苦?

【问题讨论】:

标签: ruby-on-rails json ruby-on-rails-4 rubygems


【解决方案1】:

更新为与 Rails 嵌套参数的格式相同

render json: {
  order: {
    entries: @order.entries.enum_for(:each_with_index).collect{|entry, index|
      {
        index => {
          id: entry.id,
          errors: entry.errors.to_hash,
          members: entry.members.enum_for(:each_with_index).collect{|member, index|
            { 
              index => {
                id: member.id,
                errors: member.errors.to_hash
              }
            } unless member.valid?
          }.compact
        }
      } unless entry.valid?
    }.compact
  }
}

您应该得到如下 JSON 响应:

{
  order: {
    entries: [
      0: {
        id: 1, # nil, if new record
        errors: {},
        members: [
          0: {
            id: 7, # nil, if new record
            errors: {
              title: ["cant be blank"]
            }
          },
          1: {
            id: 13, # nil, if new record
            errors: {
              title: ["cant be blank"]
            }
          }
        ]
      }
    ]
  }
}

附:也许其他人知道这样做的 Rails 集成方式。否则,我会说这可能是 git 中 Rails 的一个很好的功能请求。

【讨论】:

  • 感谢回复 但是在提交成功之前我没有ID,所有模型(订单,条目,成员)都是新记录,并且使用fields_for生成html示例中的大数字是提交的生成索引,例如fields_for 为每个嵌套模型自动创建
  • 你是对的。在使用 nested_attributes 时在没有 ID 的新资源上使用 fields_for 时,Rails 会自动分配随机 ID。我想知道如何在这里复制它。
  • 我的错,Rails 4 不会使用 fields_for 和 nested_attributes 为新记录自动分配 ID(我现在刚刚测试过)。也许它曾经在 Rails 3.2 中使用过,因为我记得以前发生过这种情况。我更新了我的答案以不处理任何 ID。
  • 更新解决方案解决了更新现有嵌套模型的问题。但是,如果我提交包含 20 个新条目的新订单,其中 3 个有验证问题,则响应将类似于“嘿,您的一些嵌套记录有问题”。我需要一种服务器响应的方法,例如:“3,5,8 的新嵌套模型没有标题属性”。我想知道为什么以前没有人遇到过这个问题。
  • 我更新了我的答案,使其具有与创建具有嵌套属性的记录时相同的 Rails 格式。现在您可以将索引 0 识别为第一条记录,将 1 识别为提交的第二条记录,2,依此类推。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
相关资源
最近更新 更多