2013-07-15 29 views
6

有沒有在Rails 4中爲樹結構指定任意深度強參數的方法?例如,我將如何指定如下內容:遞歸/樹像強參數?

{ 
    "node": { 
    "name": "parent", 
    "nodes": [ 
     { "name": "child1", "nodes": []}, 
     { "name": "child2", "nodes": [ 
     {"name": "grandchild", "nodes": []} 
     ]} 
    ] 
    } 
} 

要允許每個節點具有名稱屬性和節點屬性?

+1

你有沒有想過這個? – senfo

回答

0

這是不可能具有較強的參數。您應該使用普通紅寶石,例如將您的參數轉換爲散列,並自行驗證格式。

3

有可能是解決這個簡潔的解決方案,但是這是在我目前的工作。總體思路是統計嵌套的深度,然後根據該編號自動生成正確的嵌套散列。因此,要按照你的例子:

def count_levels(node_params) 
    if !node_params[:nodes].nil? 
    max = 0 
    node_params[:node_parameters].each do |child_params| 
     count = count_levels(child_params[1]) 
     max = count if count > max 
    end 
    return max + 1 
    else 
    return 0 
    end 
end 

def node_params 
    node_attributes_base = [:id, :name] 
    nodes = [] 
    (1..count_levels(params[:node])).each do |val| 
    nodes = node_attributes_base + [node_attributes: nodes] 
    end 
    params.require(:node).permit(:id, :name, node_attributes: nodes) 
end 

(上面的例子可以清理更因爲它是基於我的代碼,其中頂層沒有具有相同的參數,我離開它,因爲我有它,因爲它的工作的。我的系統。)

+0

謝謝。這節省了我很多頭痛。我試圖擴展Strong Parameters來攻擊這個問題。動態構造許可證散列是一種更簡單的方法。 – rodamn

2

您可以根據的事實,允許水平的數量可能比你實際需要的水平以上,所以你可以在哈希和使用統計遞歸關鍵nodes鍵的出現解決這個計數爲級別的數量。

注意這數會比你實際需要的水平以上,但比遞歸哈希在你的控制器計算層數

所以,你可以在下面的它更簡單:

# your_controller.rb 
# include RecursiveParametersBuilder 
recursive_nodes_attr = build_recursive_params(
    recursive_key: 'nodes', 
    parameters: params, 
    permitted_attributes: [:name] 
) 
params.require(:model_name).permit(:name, nodes: recursive_nodes_attr) 

並有實際的強參數建築代碼可以像下面這樣

# helper module 
module RecursiveParametersBuilder 
    # recursive_path = [:post] 
    # recursive_key = :comment_attributes 
    # recursive_node_permitted_params = [:id, :_destroy, :parameterized_type, :parameterized_id, :name, :value, :is_encrypted, :base_param_id, :parent_param_id] 
    # 
    def build_recursive_params(recursive_key:, parameters:, permitted_attributes:) 
    template = { recursive_key => permitted_attributes } 

    nested_permit_list = template.deep_dup 
    current_node = nested_permit_list[recursive_key] 

    nested_count = parameters.to_s.scan(/#{recursive_key}/).count 
    (1..nested_count).each do |i| 
     new_element = template.deep_dup 
     current_node << new_element 
     current_node = new_element[recursive_key] 
    end 
    nested_permit_list 
    end 
end