web-dev-qa-db-ja.com

Rails4:paramsの動的キーでハッシュを許可する方法は?

次のパラメーターを使用してhttp put要求を作成します。

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

そして、コードでハッシュ配列を許可する必要があります。 manuals に基づいて、私はこれらのように試しました:

> 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

正しく作る方法は?

UPD1:file1、file2-動的キー

39
rdo

設計上、強力なパラメーターは、動的キーを値として使用するハッシュを許可しないため、この場合、filesを手動でホワイトリストに登録する必要があります。

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

Rails 5.1.2では、これは現在動作しています:

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

https://github.com/Rails/rails/commit/e86524c0c5a26ceec92895c830d1355ae47a7034 を参照してください

36
Derek

これは古い投稿であることを理解しています。しかし、Google検索でこの結果が得られたので、調査結果を共有したいと思いました。

これが動作することがわかった代替ソリューションを次に示します(レール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"}}

この回答と受け入れられた回答の違いは、このソリューションではパラメーターが動的キーの1レベルのみに制限されることです。受け入れられた答えは、複数の深さを許可します。

[編集]コメントからの役立つヒント

「ああ、そしてparams [:post] [。files]が存在することを確認する必要があります。存在しない場合、キーは失敗します」

15
wes.hysell

オーランドの答えは機能しますが、結果のパラメーターセットはpermitted?メソッドからfalseを返します。また、後でpostハッシュに他のパラメーターを含めて、結果に含めたい場合にどのように進めるかは明確ではありません。

別の方法があります

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

Rails 5.0.0、これが誰かの助けになることを望んでいます。

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

私の場合、動的キーを持つ属性は1つだけでした。

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

次のように、一時変数を使用して許可リストを作成できます。

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

以下に簡単な方法を示します(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

これを回避する別の方法を次に示します。

  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

これはpost: { something: {...}, something_else: {...} }

1
Sash

次のいずれかがなければ、仕事に対する多くの提案された答え(レール5)を得ることができませんでした。

  1. 事前にすべてのハッシュキーを知っている、または
  2. 任意のパラメータを許可することにより、強力なパラメータの値を事実上無効にします。

私はこのソリューションを使用しています。
標準の強力なパラメーターリグを使用してほとんどのパラメーターをクリーンアップし、ハッシュ属性が明示的に追加されます。

# 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

より複雑なデータのサブセットを使用してみましょう。

task: {
  code: "Some Task",
  enabled: '1',
  subtask_attributes: { 
    '1' => { field: 'something', rules: {length_10: true, phone: false, presence: false }} ,
    '2' => { field: 'another', rules: {length_10: true, phone: false, presence: false }} 
  }
}

したがって、処理のためにStrong Parametersに送信します。

params = ActionController::Parameters.new({
  task: {
    code: "Some Task",
    enabled: '1',
    subtask_attributes: { 
     '1' => { field: 'something', rules: {length_10: true, phone: false, presence: false }} ,
     '2' => { field: 'another', rules: {length_10: true, phone: false, presence: false }} 
    }
  }
})

Rails 4のStrong Paramsの:rulesは、データのハッシュであるため、指定できません。

permitted = params.require(:task).permit(:code, :enabled, subtask_attributes: [:field, :rules])
Unpermitted parameter: rules
Unpermitted parameter: rules

特定の属性とデータのハッシュのコレクションをホワイトリストに登録したい場合はどうでしょう。受け入れられた回答は、指定された属性をホワイトリストに登録しません。あなたはこれをしなければなりません:

params.require(:task).permit(
    :code, :enabled,
    subtask_attributes: [:field, :rules],
)

# whitelist the validation rules hash
params.require(:task).tap do |whitelisted|
  params[:task][:subtask_attributes].each do |k,v|
    whitelisted[:subtask_attributes][k] = params[:task][:subtask_attributes][k]
    whitelisted.permit!
  end
end

ここでいくつかのソリューションを試した後、どれも機能しませんでした。任意のハッシュデータを含むhas_manyアソシエーションのネストされた属性に対しては、上記のみが機能しました。

0
Donato