处理JSON时如何使用nested_attributes?

How to use nested_attributes when processing JSON?

我正在尝试编写一个处理 JSON 的更新方法。 JSON 看起来像这样:

{
  "organization": {
    "id": 1,
    "nodes": [
      {
        "id": 1,
        "title": "Hello",
        "description": "My description."
      },
      {
        "id": 101,
        "title": "fdhgh",
        "description": "My description."
      }
    ]
  }
}

组织模型:

has_many :nodes
accepts_nested_attributes_for :nodes, reject_if: :new_record?

组织序列化程序:

attributes :id
has_many :nodes

节点序列化器:

attributes :id, :title, :description

组织控制器中的更新方法:

def update
  organization = Organization.find(params[:id])
  if organization.update_attributes(nodes_attributes: node_params.except(:id))
    render json: organization, status: :ok
  else
    render json: organization, status: :failed
  end
end

private
  def node_params
    params.require(:organization).permit(nodes: [:id, :title, :description])
  end

我还尝试将 accepts_nested_attributes_for 添加到组织 serializer,但这似乎不正确,因为它产生了错误 (undefined method 'accepts_nested_attributes_for'),所以我只将 accepts_nested_attributes_for 添加到模型而不是序列化程序。

上面的代码生成下面的错误,参考更新方法中的 update_attributes 行。我做错了什么?

no implicit conversion of String into Integer

在调试器中 node_params returns:

Unpermitted parameters: id
{"nodes"=>[{"id"=>101, "title"=>"gsdgdsfgsdg.", "description"=>"dgdsfgd."}, {"id"=>1, "title"=>"ertret.", "description"=>"etewtete."}]}

更新: 使用以下命令使其工作:

def update
  organization = Organization.find(params[:id])
  if organization.update_attributes(nodes_params)
    render json: organization, status: :ok
  else
    render json: organization, status: :failed
  end
end

private
  def node_params
    params.require(:organization).permit(:id, nodes_attributes: [:id, :title, :description])
  end

我向序列化程序添加了 root: :nodes_attributes

现在一切正常,但是 我担心在 node_params 中包含 ID。这样安全吗? 现在难道不能编辑 organizationnode 的 ID(这是不允许的)吗? 以下是否是不允许它更新 id 的正确解决方案:

if organization.update_attributes(nodes_params.except(:id, nodes_attributes: [:id]))

看起来超级接近。

您的 json 子对象 'nodes' 需要 'nodes_attributes'。

{
  "organization": {
    "id": 1,
    "nodes_attributes": [
      {
        "id": 1,
        "title": "Hello",
        "description": "My description."
      },
      {
        "id": 101,
        "title": "fdhgh",
        "description": "My description."
      }
    ]
  }
}

你可以做这种事。将其放入您的控制器中。

before_action do
  if params[:organization]
    params[:organization][:nodes_attributes] ||= params[:organization].delete :nodes
  end
end

它将在参数中设置正确的属性并且仍然使用所有 accepts_nested_attributes 功能。