2013-08-21 14 views
27

robię żądanie HTTP PUT z następującymi parametrami:Rails4: Jak zezwolić na mieszanie z dynamicznymi kluczami w parametrach?

{ "post" => { "pliki" => { "plik1" => "file_content_1" "plik2" => "file_content_2"} }, "id" => "4"}

i muszę zezwolić na tablicę haszującą w moim kodzie. podstawie manuals Próbowałem takie jak:

> params.require(:post).permit(:files) # does not work 
> params.require(:post).permit(:files => {}) # does not work, empty hash as result 
> params.require(:post).permit! # works, but all params are enabled 

jak zrobić to prawidłowo?

UPD1: plik1, plik2 - są dynamiczne klucze

+0

Spróbuj params.require (: post) .permit (: Pliki => [: plik1,: plik2]) – user2801

+2

To nie jest opcja: plik1, plik2 to klucze dynamiczne. – rdo

+0

Dla Rails 5.1 proszę zobaczyć https://stackoverflow.com/a/44891190/1414100 –

Odpowiedz

39

przez Design silnych params nie pozwala mieszań z dynamicznych kluczy jako wartości, tak .. w tym przypadku trzeba do białej files ręcznie.

params.require(:post).tap do |whitelisted| 
    whitelisted[:files] = params[:post][:files] 
end 
+0

Dzięki! To działa. – rdo

+3

Oto jak działa 'tap': http://ruby-doc.org/core-2.1.1/Object.html#method-i-tap – amoebe

5

odpowiedź Orlanda działa, ale uzyskany zestaw parametrów zwraca false od sposobu permitted?. Również nie jest jasne, jak postępować, gdyby później miały inne parametry w haszu post, które chcesz uwzględnić w wyniku.

Oto kolejny sposób

permitted_params = params.require(:post).permit(:other, :parameters) 
permitted_params.merge(params[:post][:files]) 
1

Oto kolejny sposób, aby obejść ten problem:

def post_params 
    permit_key_params(params[:post]) do 
     params.require(:post) 
    end 
    end 

    def permit_key_params(hash) 
    permitted_params = yield 
    dynamic_keys = hash.keys 
    dynamic_keys.each do |key| 
     values = hash.delete(key) 
     permitted_params[key] = values if values 
    end 
    permitted_params 
    end 

ten powinien pracować dla post: { something: {...}, something_else: {...} }

14

Rozumiem, że to jest stary słup. Jednak Wyszukiwarka Google wprowadził mnie do tego wyniku, i chciałem podzielić się moje wyniki:

Oto alternatywne rozwiązanie, które znalazłem, że działa (Szyny 4):

params = ActionController::Parameters.new({"post"=>{"files"=>{"file1"=>"file_content_1", "file2"=>"file_content_2"}}, "id"=>"4"}) 
params.require(:post).permit(files: params[:post][:files].keys) 
# Returns: {"files"=>{"file1"=>"file_content_1", "file2"=>"file_content_2"}} 

Różnica między tym odpowiedź i zaakceptowana odpowiedź jest taka, że ​​to rozwiązanie ogranicza parametr tylko do 1 poziomu kluczy dynamicznych. Przyjęta odpowiedź pozwala na wiele głębokości.

[Edytuj] Przydatna wskazówka z komentarzem

"Och, i trzeba sprawdzić, params [: post] [. Plików] Istnieje inaczej klucze zawiedzie"

+0

Tak, to działa również dla mnie –

+4

Aha, i musisz to sprawdzić params [: post] [. files] istnieje inaczej klucze się nie powiedzie –

+0

Zgrabny pomysł (z zastrzeżeniami) – prusswan

0

Można użyć tymczasowy zmienna zbudować dozwolone listy tak:

permitted = params.require(:post).permit(:id) 
permitted[:post][:files] = params[:post][:files].permit! 
0
Send params as array type like name=date[]**strong text** 
     def user_post 
     dates = params[:date] 
     #render json: { 'response' => params } 
     i = 0 
     dates.each do |date| 
      locations = params['location_'+"#{i}"] 
      user_names = params['user_'+"#{i}"] 
      currency_rates = params['currency_'+"#{i}"] 
      flags = params['flag_'+"#{i}"] 
      j = 0 
      locations.each do |location| 
      User.new(user_name: user_names[j], currency_name: flags[j], 
      currency_rate: currency_rates[j], currency_flag: flags[j], location: location).save 
      j =+ 1 
      end 
      i =+ 1 
     end 
    def 
3

Oto, co mieliśmy do zrobienia w Rails 5.0.0, mam nadzieję, że ktoś pomaga.

files = params[:post].delete(:files) if params[:post][:files] 
params.require(:post).permit(:id).tap do |whitelisted| 
    whitelisted[:files] = files.permit! 
end 
+0

Przyjemne podejście. Naprawdę mi pomógł. Dzięki @Garry! – mikej

0

Oto prosty sposób to zrobić (działa na szynach 5):

def my_params 
    data_params = preset_data_params 

    params.require(:my_stuff).permit(
     :some, 
     :stuff, 
     data: data_params 
    ) 
    end 

    def preset_data_params 
    return {} unless params[:my_stuff] 
    return {} unless params[:my_stuff][:data] 

    params[:my_stuff][:data].keys 
    end 
0

Nie mogłem uzyskać żadnej z wielu proponowanych odpowiedzi (Rails 5) bez:

  1. znając wszystkie klawisze skrótu z góry, lub
  2. praktycznie negując wartości mocnych parametrów, umożliwiając dowolne params.

Używam tego rozwiązania.
Wykorzystuje standardowe silne parametry rig do czyszczenia większości parametrów, , a atrybut Hash jest dodawany z powrotem jawnie.

# Assuming: 
class MyObject < ApplicationRecord 
    serialize :hash_attr as: Hash 
    #... 
end 

# MyObjectsController method to filter params: 
def my_object_params 
    # capture the hashed attribute value, as a Hash 
    hash_attr = params[:my_object] && params[:my_object][:hash_attr] ? 
     params[my_object][:hash_attr].to_unsafe_h : {} 
    # clean up the params 
    safe_params = params.require(:my_object).permit(:attr1, :attr2) # ... etc 
    # and add the hashed value back in 
    safe_params.to_unsafe_h.merge hash_attr: hash_attr 
end 
0

W moim przypadku, nie było tylko jeden atrybut, który miał klucze dynamiczne,

def post_params 
    marking_keys = Set.new 
    params[:post][:marking].keys.collect {|ii| marking_keys.add(ii)} 
    params.require(:post).permit(:name, marking: marking_keys.to_a) 
end