2015-12-12 2 views
0

Предположим, у нас есть хэш-рельсы с полными вложенными хэшами и массивами. Есть ли способ изменить каждое строковое значение (будь то во вложенных хэшах или массивах), которое соответствует определенным критериям (например, регулярное выражение), и все равно сохранить вывод в качестве хэша params (все еще содержащий вложенные хэш-массивы?Редактирование параметров вложенных хеш

Я хочу сделать какой-то строки манипуляции на некоторые атрибуты перед тем даже назначая их к модели. есть ли лучший способ для достижения этой цели?

[UPDATE] Допустим, мы хотим, чтобы выбрать строки, которые имеют час в начните и замените его на «b». поэтому у нас есть: до: { a: "h343", b: { c: ["h2", "s21"] } }

после: { a: "b343", b: { c: ["b2", "s21"] } }

По некоторым причинам я не могу сделать это с моделью обратных вызовов и прочее, так что это должно быть сделано до присвоения соответствующих атрибутов.

+1

Можете привести пример? –

+0

@SunnyK Просто добавил пример. – Arvinje

+0

Я понятия не имею, почему кто-то изменил бы параметры, которые соответствуют регулярному выражению, вместо того, чтобы переместить эту логику обратно в модель (обратный вызов ведьмы или только пользовательский метод) –

ответ

1

еще сохранить вывод в виде Params хэш (все еще содержащий вложенные хэши массивы

Sure.

Вы должны манипулировать params хэш, который делается в контроллере.

Хотя у меня нет большого опыта с этим Я только что провел кучу времени тестирования - вы можете использовать смесь класса ActionController::Parameters, а затем использовать gsub! - как это:

#app/controllers/your_controller.rb 
class YourController < ApplicationController 
    before_action :set_params, only: :create 

    def create 
     # Params are passed from the browser request 
     @model = Model.new params_hash 
    end 

    private 

    def params_hash 
     params.require(:x).permit(:y).each do |k,v| 
     v.gsub!(/[regex]/, 'string') 
     end 
    end 
end 

Я испытал это на одном из наших тестовых приложений, и она работала отлично:

enter image description here

enter image description here

enter image description here

-

Есть несколько важных моментов.

Во-первых, при вызове strong_params хэш, params.permitсоздает новый хэш из пройденных Params. Это означает, что вы не можете просто изменить переданные параметры с помощью params[:description] = и т. Д. Вы должны сделать это с разрешенными параметрами.

Во-вторых, я мог получить только блок .each, работающий с bang-operator (gsub!), так как это напрямую меняет значение. Мне нужно потратить больше времени, чтобы выяснить, как сделать более сложные изменения.

-

Update

Если вы хотите, чтобы включить вложенные хэши, вы должны были бы назвать еще один цикл:

def params_hash 
    params.require(:x).permit(:y).each do |k,v| 
     if /_attributes/ ~= k 
     k.each do |deep_k, deep_v| 
      deep_v.gsub!(/[regex]/, 'string' 
     end 
     else 
     v.gsub!(/[regex]/, 'string') 
     end 
    end 
end 
+0

Я не думаю, что это решение будет работать, если разрешенные параметры включают вложенные массивы или хеши (например, если вы используете accepts_nested_attributes_for). – Arvinje

+0

Вы протестировали его? –

+0

да, если у нас есть это как разрешенные параметры: "{" name "=>" hello "," ch "=> {" a "=>" 12 "," b "=>" 13 "}}", затем каждый метод выбирает только «hello» и {"a" => "12", "b" => "13"} в качестве значений. Но я хочу также изменить значения внутри вложенного хэша. – Arvinje

0

В общем, вы не должны изменять оригинальный хеш params. Когда вы используете сильные параметры для белого списка параметров, вы фактически создаете копию параметров, которые могут быть изменены, если вам нужно действительно.

def whitelist_params 
    params.require(:foo).permit(:bar, :baz) 
end 

Но если отображение входных данных для модели является слишком сложным или вы не хотите, чтобы сделать это на уровне модели вы должны рассмотреть возможность использования service object.

+0

Я тоже в порядке с копией параметров. Хотя я не хочу использовать белый список или удалять любые ключи или значения из файла has. Я просто хочу изменить некоторые строковые значения. – Arvinje

+0

Я проигнорировал, потому что это не отвечает на вопрос, извините:/ –

0

Если у вас есть хэш, как это:

hash = { "hello" => { "hello" => "hello", "world" => { "hello" => "world", "world" => { "hello" => "world" } } }, "world" => "hello" } 

Затем добавьте функцию tha т превращает «ELLO» часть всех ключей и значений в «я» (это означает, что «привет» и «желтый» станет «привет» и «yiw»)

def transform_hash(hash, &block) 
    hash.inject({}){ |result, (key,value)| 
    value = value.is_a?(Hash) ? transform_hash(value, &block) : value.gsub(/ello/, 'i') 
    block.call(result, key.gsub(/ello/, 'i'), value) 
    result 
    } 
end 

Используйте функцию как:

new_hash = transform_hash(hash) {|hash, key, value| hash[key] = value } 

Это преобразует ваш хэш и его значения независимо от уровня гнездования. Однако значения должны быть строками (или другим Hash), иначе вы получите сообщение об ошибке. для решения этой проблемы просто измените значение value.is_a?(Hash) условно.

ПРИМЕЧАНИЕ, что я настоятельно рекомендую вам НЕ изменить ключи хеша!

Смежные вопросы