2016-01-16 78 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