2015-08-11 18 views
7

Przesyłam formularz zawierający od 2 do 4 obiektów naraz, w zależności od liczby rodziców. Zdaję sobie sprawę, że jest to prawdopodobnie niekonwencjonalne, ale naprawdę chciałem, aby użytkownik mógł edytować wszystkie obiekty naraz w jednym formularzu. Na moim formularzu, robię:Szyny 4 Silne parametry z wieloma obiektami i kluczami całkowitymi

<%= simple_fields_for "derps[]", derp do |f| %> 

<% end %> 

Potem robię to w kontrolerze:

def update 
    @derps = [] 
    @rejects = [] 
    derps_params.each do |key, hash| 
    derp = Derp.find(key) 
    derp.assign_attributes(hash) 
    @rejects << derp unless derp.save 
    end 
    if @rejects.empty? 
    redirect_to @parent, flash: {success: 'Derps were successfully updated.'} 
    else 
    @derps = @rejects 
    render :edit 
    end 
end 

powiedzmy, że istnieją dwa obiekty - params idą przez jak:

"derps"=>{"1"=>{"attribute"=>"39", "another_attribute"=>"serp", "a_third_attribute"=>"yerp"}, "2"=>{"attribute"=>"30", "another_attribute"=>"49", }} 

Miałem to działa w Rails 3 bez silnych params. Ja uaktualnieniu do szyn 4 i jestem zmaga się z jak dostać tej pracy - ciśgle „niedozwolonej parametry: 1, 2”

Jestem zakładając muszę zrobić coś takiego:

def mashes_params 
    params.require(:derps).permit(
    id: [] 

lub

def mashes_params 
    params.require(:derps).permit(
    :id, 

Coś wzdłuż tych linii, ale próbowałem to każdy sposób mogę myśleć bez powodzenia.

Wszelkie pomysły tutaj?

+0

co są 'mashes' w mashes_params? Czy to powinno być 'derps'? –

+0

Tak, dziękuję! Poprawiono tę literówkę. To był mój prawdziwy kod.Użyłem derps jako ogólnego przykładu. – gregblass

Odpowiedz

1

Finał Edit (mam nadzieję):

Musiałem przemyśleć to od podstaw. Doszedłem do wniosku: Ponieważ: id działa jako symbol wieloznaczny, ale nie jest dozwolony jako klucz hasha, może nie zawsze tworzy klucze 1-4, więc mogę je jawnie dodać do białej listy, a następnie pobrać identyfikator z klucza. wartość w haszowaniu, podobnie jak w tradycyjnym zagnieżdżaniu formularzy? Tak to właśnie rozwiązałem. Oto ostateczna realizacja że ja pracuje:

<% i = @parent.derps.index(derp) + 1 %> 
<%= simple_fields_for "derps[#{i}]", derp do |f| %> 
    <%= f.hidden_field :id, value: derp.id %> 
    <%= render "rest_of_the_fields" %> 
<% end %> 

Następnie w sterowniku:

def update 
    @derps = [] 
    @rejects = [] 
    derp_params.each do |key, hash| 
    derp = Derp.find(hash.delete("id")) 
    derp.assign_attributes(hash) 
    @rejects << derp unless derp.save 
    end 
    if @rejects.empty? 
    redirect_to @parent, flash: {success: "Derps updated successfully."} 
    else 
    @derps = @rejects 
    render :edit 
    end 
end 

Następnie są tu silne params:

def derp_params 
    p = [:id, :attribute_1, :another_attribute, ...] 
    params.require(:derps).permit(
    "1" => p, "2" => p, "3" => p, "4" => p 
) 
end 

Uff. Mam nadzieję, że to pomaga komuś.

+1

Działa to tylko wtedy, gdy możesz zagwarantować, że masz nie więcej niż 4 zagnieżdżone rekordy, prawda? Więc nie wydaje się być rozwiązaniem ogólnego celu dla podstawowego problemu. –

4

znalazłem, że linia poleceń jest ogromnie pomocne dla debugowania Silne Parametry w Rails 4. Oto jak testowałem swój problem w konsoli:

rails C# From within your project directory, short for 'rails console' 

params = ActionController::Parameters.new({ derps: { 1 => { attribute: 39, another_attribute: "serp" }, 2 => { attribute: 30, another_attribute: 49 } } }) 

params # To make sure that the object looks the same 

permitted = params.require(:derps).permit(1 => [ :attribute, :another_attribute ], 2 => [ :attribute, :another_attribute ]) 

permitted # To see what you'd get back in your controller 

Mam nadzieję, że z tego narzędzia będzie można do debugowania wszystkiego, czego moja odpowiedź nie zapewniała łatwiej niż próba i błąd.

+0

Świetna wskazówka na temat konsoli! Dzięki. – RichardAE

+0

Naprawdę świetny napiwek. Dziękuję Ci! – gregblass

0

Bezwzględna najlepszym rozwiązaniem Widziałem to here:

def product_params 
    properties_keys = params[:product].try(:fetch, :properties, {}).keys 
    params.require(:product).permit(:title, :description, properties: properties_keys) 
end 

Zrobiłem jeszcze jedną zmianę do iterację nienazwanych klucze od mojego property_keys mieć więcej zagnieżdżone klucze i wartości:

response_keys = params[:survey][:responses].try(:fetch, :properties, {}).keys 
params.require(:survey).permit(responses: response_keys.map {|rk| [rk => [:question_id, :answer_id, :value]]})