2013-07-15 4 views
6

Esiste un modo per specificare parametri forti arbitrariamente profondi per le strutture ad albero in Rails 4? Ad esempio, come faccio a specificare qualcosa come segue:Ricorsivo/Albero come parametri forti?

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

Per consentire a ciascun nodo di avere un attributo name, e attribuire un nodo?

+1

Hai mai capito questo? – senfo

risposta

0

Questo non è possibile con parametri forti. Dovresti usare un semplice ruby ​​per questo, cioè convertire i parametri in un hash con to_hash e convalidare il formato da solo.

3

Potrebbe esserci una soluzione più pulita per risolvere questo problema, ma questo è il mio attuale lavoro. L'idea generale è di calcolare quanto è profondo il mio nidificazione e quindi generare automaticamente l'hash nidificato corretto basato su quel numero. Quindi, per seguire il vostro esempio:

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 

(L'esempio precedente può essere pulito più dal momento che è basato sulla mia codice in cui il livello superiore non ha avuto gli stessi parametri ho lasciato, come ho avuto da quando è lavorato. il mio sistema.)

+0

Grazie. Questo mi ha salvato molto mal di testa. Stavo attaccando questo problema cercando di estendere i parametri forti. Costruire dinamicamente l'hash dei permessi è un approccio più semplice. – rodamn

2

È possibile risolvere con a seconda del fatto che il numero di livello consentito può essere più che i livelli effettivamente necessarie, in modo da poter contare la presenza della chiave nodes chiave ricorsiva nel vostro uso hash e questo conta come numero di livelli.

Si noti che questo conteggio sarà più che i livelli hai veramente bisogno, ma è più semplice di quanto in modo ricorsivo contare il numero di livelli nella hash

Così nel controller è possibile il seguente:

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

E avere il codice di costruzione dei parametri forti reali può essere il seguente

# 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