2013-08-21 1 views
27

Ich mache eine HTTP PUT-Anforderung mit folgenden Parametern:Rails4: Wie erlaubt man einen Hash mit dynamischen Schlüsseln in Params?

{ "post" => { "files" => { "file1" => "file_content_1", "file2" => "file_content_2"} }, "id" => "4"}

und ich muss Hash-Array in meinem Code zulassen. basierend auf manuals Ich habe wie diese versucht:

> 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 

Wie es richtig zu machen?

UPD1: file1, file2 - sind dynamische Schlüssel

+0

Try params.require (Post) .permit (: files => [: file1,: file2]) – user2801

+2

Es ist keine Option: Datei1, Datei2 sind dynamische Schlüssel. – rdo

+0

Für Rails 5.1 siehe https://stackoverflow.com/a/44891190/1414100 –

Antwort

39

nach Design stark params nicht Hashes mit dynamischen Tasten als Werte erlauben, so .. in diesem Fall müssen Sie files manuell weiße Liste.

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

Vielen Dank! Es klappt. – rdo

+3

So funktioniert 'tap': http://ruby-doc.org/core-2.1.1/Object.html#method-i-tap – amoebe

5

Orlando Antwort funktioniert, aber der resultierende Parametersatz liefert false von permitted? Methode. Es ist auch nicht klar, wie Sie vorgehen würden, wenn Sie später andere Parameter im post Hash haben, die Sie in das Ergebnis aufnehmen möchten.

Hier ist eine andere Art und Weise

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

Dies ist ein weiterer Weg, dies zu umgehen:

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 

Diese für post: { something: {...}, something_else: {...} }

14

arbeiten sollte ich verstehe, dass dies eine alte Post ist. Allerdings brachte eine Google-Suche mich zu diesem Ergebnis, und ich wollte meine Erkenntnisse teilen:

Hier ist eine alternative Lösung, die ich gefunden habe, das funktioniert (Rails 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"}} 

Der Unterschied Antwort und die akzeptierte Antwort ist, dass diese Lösung den Parameter auf nur 1 Ebene der dynamischen Schlüssel beschränkt. Die akzeptierte Antwort erlaubt mehrere Tiefen.

[Bearbeiten] Nützlicher Tipp von Kommentar

"Oh, und Sie überprüfen müssen, dass params [: post] [. Dateien] existiert sonst Schlüssel fail"

+0

Ja, das funktioniert auch für mich –

+4

Oh, und Sie müssen das überprüfen params [: post] [. files] existiert sonst Schlüssel werden scheitern –

+0

Eine nette Idee eigentlich (mit Vorbehalte) – prusswan

0

Sie eine temporäre verwenden können Variable Ihre zulässigen Liste zu erstellen, wie so:

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

Hier ist, was wir in Rails 5.0.0, hoffe, das hilft jemand zu tun hatte.

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

Netter Ansatz. Hat mir wirklich geholfen. Danke @Garry! – mikej

0

Hier ist eine einfache Art und Weise, es zu tun (funktioniert für Schienen 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

Ich konnte keine der vielen vorgeschlagenen Antworten zur Arbeit bekommen (Rails 5) ohne:

  1. alle Hash-Schlüssel im Voraus zu wissen, oder
  2. Negieren praktisch den Wert von starken Parameter durch willkürliche params ermöglicht.

Ich verwende diese Lösung.
Es verwendet die Standard-starke Parameter-Rig, um die meisten Parameter zu bereinigen, und das Hash-Attribut wird explizit wieder hinzugefügt.

# 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

In meinem Fall war es nur ein Attribut, das dynamische Schlüssel hatte,

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 
Verwandte Themen