Rails4: Как разрешить хэш с динамическими клавишами в параметрах?
Я делаю запрос http put со следующими параметрами:
{ "пост" = > { "файлы" = > { "file1" = > "file_content_1", "file2" = > "file_content_2" }}, "id" = > "4" }
и мне нужно разрешить хэш-массив в моем коде.
на основе руководства Я пробовал вот так:
> 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 - динамические клавиши
Ответы
Ответ 1
Сконструированные строгие параметры не допускают использование в качестве значений хэшей с динамическими ключами, в этом случае вам нужно добавить белый список files
, вызвав permit!
params.require(:post).tap do |whitelisted|
whitelisted[:files] = params[:post][:files].permit!
end
Для Rails 4 и ниже вы делаете это без вызова permit!
params.require(:post).tap do |whitelisted|
whitelisted[:files] = params[:post][:files]
end
Ответ 2
В рельсах 5.1.2 это работает сейчас:
params.require(:post).permit(:files => {})
См. https://github.com/rails/rails/commit/e86524c0c5a26ceec92895c830d1355ae47a7034
Ответ 3
Я понимаю, что это старый пост. Однако поиск Google привел меня к этому результату, и я хотел поделиться своими выводами:
Вот альтернативное решение, которое я нашел, что работает (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"}}
Разница между этим ответом и принятым ответом заключается в том, что это решение ограничивает параметр только одним уровнем динамических клавиш. Принятый ответ допускает несколько глубин.
[Изменить] Полезный отзыв от комментария
"О, и вам нужно проверить, что params [: post] [. files] существует, иначе клавиши будут терпеть неудачу"
Ответ 4
Работа в Orlando работает, но результирующий набор параметров возвращает false
из метода permitted?
. Также неясно, как вы будете продолжать, если позже у вас будут другие параметры в хеше post
, которые вы хотите включить в результат.
Здесь другой путь
permitted_params = params.require(:post).permit(:other, :parameters)
permitted_params.merge(params[:post][:files])
Ответ 5
Вот что нам нужно было сделать в 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
Ответ 6
В моем случае был только один атрибут с динамическими ключами,
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
Ответ 7
Вот еще один способ обойти это:
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: {...} }
Ответ 8
Вы можете использовать временную переменную для создания разрешенного списка следующим образом:
permitted = params.require(:post).permit(:id)
permitted[:post][:files] = params[:post][:files].permit!
Ответ 9
Вот простой способ сделать это (работает для рельсов 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
Ответ 10
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
Ответ 11
Я не мог получить ни один из многих предлагаемых ответов на работу (Rails 5) без:
- заранее знать все хэш-ключи или
- фактически отрицает значение сильных параметров, разрешая произвольные параметры.
Я использую это решение.
Он использует стандартную установку сильных параметров для очистки большинства параметров,
и атрибут Hash добавляется обратно явно.
# 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
Ответ 12
Позвольте использовать более сложное подмножество данных:
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 }}
}
}
})
Мы не сможем указать: правила в Strong Params в Rails 4, потому что это хеш данных:
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, которая содержит произвольные хеш-данные.