web-dev-qa-db-fra.com

Rails4: Comment autoriser un hachage avec des clés dynamiques dans les paramètres?

Je fais une demande http put avec les paramètres suivants:

{"post" => {"fichiers" => {"fichier1" => "fichier_contenu_1", .__ "file2" => "file_content_2"}}, "id" => "4"}

et j'ai besoin de permettre un tableau de hachage dans mon code. basé sur manuels J'ai essayé comme ceci:

> 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

Comment le faire correctement?

UPD1: fichier1, fichier2 - sont des clés dynamiques

35
rdo

de par leur conception, Strong ne permet pas les hachages avec des clés dynamiques, donc .. dans ce cas, vous devez ajouter à la liste blanche files manuellement.

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

Dans Rails 5.1.2, cela fonctionne maintenant:

params.require(:post).permit(:files => {})

Voir https://github.com/Rails/rails/commit/e86524c0c5a26ceec92895c830d1355ae47a7034

27
Derek

Je comprends que c'est un ancien post. Cependant, une recherche sur Google m'a amené à ce résultat et je voulais partager mes découvertes:

Voici une solution alternative que j'ai trouvée qui fonctionne (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"}}

La différence entre cette réponse et la réponse acceptée est que cette solution limite le paramètre à un seul niveau de clés dynamiques. La réponse acceptée autorise plusieurs profondeurs.

[Modifier] Astuce utile du commentaire

"Oh, et vous devez vérifier que params [: post] [. Fichiers] existe sinon les clés échoueraient"

15
wes.hysell

La réponse d'Orlando fonctionne, mais l'ensemble de paramètres résultant renvoie false à partir de la méthode permitted?. En outre, la manière dont vous procéderiez si vous aviez ultérieurement d'autres paramètres dans le hachage post que vous souhaitez inclure dans le résultat n'est pas claire.

Voici une autre façon

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

Voici ce que nous avons dû faire dans Rails 5.0.0, espérons que cela aidera quelqu'un.

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

Vous pouvez utiliser une variable temporaire pour construire votre liste autorisée de la manière suivante:

permitted = params.require(:post).permit(:id)
permitted[:post][:files] = params[:post][:files].permit!
1
Cam

Voici un moyen simple de le faire (fonctionne pour Rails 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
1
Krzysztof Karski

Voici un autre moyen de contourner cela:

  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

Cela devrait fonctionner pour post: { something: {...}, something_else: {...} }

1
Sash

Dans mon cas, il n'y avait qu'un attribut qui avait des clés dynamiques, 

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
1
Mukarram Ali

Je ne pouvais obtenir aucune des nombreuses réponses proposées au travail (Rails 5) sans:

  1. connaître toutes les clés de hachage à l'avance, ou 
  2. pratiquement nier la valeur de paramètres forts en permettant des paramètres arbitraires.

J'utilise cette solution.
Il utilise le rig standard standard de paramètres forts pour nettoyer la plupart des paramètres, Et l’attribut Hash est ajouté explicitement.

# 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
Tom Wilson
    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
0
vikas pal