2016-01-16 37 views
0

我想写一个处理JSON的更新方法。该JSON看起来是这样的:如何在处理JSON时使用nested_attributes?

{ 
    "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')是正确的,所以我只加accepts_nested_attributes_for到模型中并没有给串行器。

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

no implicit conversion of String into Integer

在调试器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])) 
+0

我认为你需要从params中删除节点。您无法使用update_attributes以这种方式设置节点。 – Swards

回答

1

看起来超近。

你的json子对象'nodes'需要是'nodes_attributes'。

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

我不知道我可以改变这个......不是我写更新模型来适应JSON代码吗?序列化器(除了属性之外)只有:'has_many:nodes'并生成显示的JSON。我似乎只能在组织模型中包括'accep_nested_attributes_for:nodes',而不是在组织化串行化程序中(然后它会产生一个错误:'未定义的方法'recep_nested_attributes_for'')。 – Nick

+0

我可以在序列化程序中使用'root'将其更改为'nodes_attributes'。现在它可以工作(请参阅OP中的更新)。但是我担心在'node_params'中包含id。那安全吗?现在不可能编辑“组织”和“节点”(不应该被允许)的ID吗? – Nick

+0

嘿嘿。你将不得不增加安全性。最好的做法是添加一个reject_if子句来强制传入组织的节点的所有权。如果该标识为空,则会创建一个新标识。如果它存在,它会更新那个ID。真理的破坏破坏了它。建议通过api码头阅读以获取完整的详细信息。 http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html – Austio

1

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

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

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

+0

谢谢,我不应该再对'updates_attributes'行和/或'def node_params'进行更改吗? – Nick

+0

是的 - 只是update_attributes(node_params)正常 – Swards

+0

谢谢,我用新代码将结果添加到原始文章中,以确保我按照您的要求进行操作。我收到错误消息:'节点(#70152224207320)预计,得到ActionController :: Parameters(#27264600)'。 – Nick