处理JSON时如何使用nested_attributes?

时间:2016-01-16 15:23:25

标签: ruby-on-rails ruby json serialization nested-attributes

我试图编写一个处理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添加到组织序列化程序,但这似乎不正确,因为它产生了错误(undefined method 'accepts_nested_attributes_for'),所以我' ve仅将accepts_nested_attributes_for添加到模型而不是序列化程序。

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

  

没有将String隐式转换为整数

在调试器中node_params返回:

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]))

2 个答案:

答案 0 :(得分:1)

看起来非常接近。

您的json子对象'节点'需要是'nodes_attributes'。

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

答案 1 :(得分:1)

你可以做这种事情。把它放在你的控制器里。

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

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