2016-10-27 3 views
1

Как я могу реорганизовать следующее? У меня есть некоторые значения, хранящиеся в моем файле YAML в виде вложенных массивов, но я хочу, чтобы все мои транзакции были переведены в два метода get и set. Это работает, но явно ограничено и громоздко. Он чувствует себя не так.Есть ли способ передать «адреса массива» методу?

module Persistance 
    @store = YAML::Store.new('store.yml') 

    def self.get_transaction(key) 
    @store.transaction { @store[key] } 
    end 

    def self.get_nested_transaction(key, sub) 
    @store.transaction { @store[key][sub] } 
    end 
end 

Bonus credit: У меня также есть дополнительный метод для увеличения значений в моем файле YAML. Есть ли еще один способ реорганизации этого кода? Имеет ли смысл просто передавать блоки одному методу доступа к базе данных?

ответ

1

Эй, я помню, думал об этом, когда я практиковал PStore некоторое время назад. Тогда я не понял рабочего подхода, но мне удалось получить его сейчас. Кстати, yaml/store довольно круто, и вы можете взять кредит, чтобы познакомить меня с ним.

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

  • @store похож на хэш в том, что вы можете использовать [] и []=, но это на самом деле не хэш, это YAML::Store.
  • Ruby 2.3 имеет способ Hash#dig, который является видом недостающей части головоломки здесь. Вы предоставляете список ключей, и каждый из них рассматривает их как последовательные ключи. Вы можете использовать это для обоих get и set, так как мой код показывает
  • Если @store были истинным хэша, что будет конец его, но это не так, так что для этого ответа я добавил YAML::Store#dig метод, который имеет такой же использование в качестве исходного ,

require 'yaml/store' 

class YAML::Store 
    def dig(*keys) 
    first_val = self[keys.shift] 
    if keys.empty? 
     first_val 
    else 
     keys.reduce(first_val) do |result, key| 
     first_val[key] 
     end 
    end 
    end 
end 

class YamlStore 
    attr_reader :store 
    def initialize filename 
    @store = YAML::Store.new filename 
    end 
    def get *keys 
    @store.transaction do 
     @store.dig *keys 
    end 
    end 
    def set *keys, val 
    @store.transaction do 
     final_key = keys.pop 
     hash_to_set = keys.empty? ? @store : @store.dig(*keys) 
     hash_to_set.send :[]=, final_key, val 
    end 
    end 
end 

filename = 'store.yml' 
db = YamlStore.new filename 

db.set :a, {} 
puts db.get :a 
# => {} 

db.set :a, :b, 1 
puts db.get :a, :b 
# => 1 
+0

УДИВИТЕЛЬНЫЙ. Dig - это именно то, что я знал, что мне нужно, но не знал. Я возьму на себя некоторую работу, чтобы переварить приведенный вами пример кода, но я уже вижу, куда мы направляемся, и это выглядит идеально. Спасибо! –

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