Изменить значения во вложенном хэше - PullRequest
2 голосов
/ 04 августа 2009

У меня есть класс конфигурации в Ruby, который имел ключи типа «core.username» и «core.servers», который так же хранился в файле YAML.

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

def [](key)
  namespace, *rest = key.split(".")

  target = @config[namespace]
  rest.each do |k|
    return nil unless target[k]
    target = target[k]
  end

  target
end

Но когда я попробовал то же самое с классом писателя, это работает, но не устанавливается в @config -хэш. @config устанавливается только с помощью вызова YAML.load_file

Мне удалось заставить его работать с eval, но это не то, что я хотел бы сохранить надолго.

def []=(key, value)
  namespace, *rest = key.split(".")

  target = "@config[\"#{namespace}\"]"
  rest.each do |key|
    target += "[\"#{key}\"]"
  end

  eval "#{target} = value"
  self[key]
end

Есть ли какой-нибудь достойный способ добиться этого, желательно без смены плагинов и кода?

Ответы [ 2 ]

1 голос
/ 04 августа 2009
def []=(key, value)
  subkeys = key.split(".")
  lastkey = subkeys.pop
  subhash = subkeys.inject(@config) do |hash, k|
    hash[k]
  end
  subhash[lastkey] = value
end

Редактировать: Исправлено разделение. PS: Вы также можете заменить инъекцию на каждый цикл, как в методе [], если хотите. Важно то, что вы не вызываете [] с последним ключом, а вместо этого [] = для установки значения.

0 голосов
/ 12 декабря 2014

Я использовал рекурсию:

def change(hash)
  if hash.is_an? Hash
    hash.inject({}) do |acc, kv|
      hash[change(kv.first)] = change(kv.last)
      hash 
    end
  else
    hash.to_s.split('.').trim # Do your fancy stuff here
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...