lib/fusuma/config/searcher.rb in fusuma-2.0.0.pre vs lib/fusuma/config/searcher.rb in fusuma-2.0.0.pre2
- old
+ new
@@ -4,11 +4,11 @@
module Fusuma
class Config
# Search config.yml
class Searcher
def initialize
- @cache
+ @cache = nil
end
# @param index [Index]
# @param location [Hash]
# @return [NilClass]
@@ -29,13 +29,27 @@
value = search(next_index, location: next_location)
end
value
end
+ def search_with_context(index, location:, context:)
+ return search(index, location: location[0]) if context == {}
+
+ new_location = location.find do |conf|
+ search(index, location: conf) if conf[:context] == context
+ end
+ search(index, location: new_location)
+ end
+
+ # @param index [Index]
+ # @param location [Hash]
+ # @return [NilClass]
+ # @return [Hash]
+ # @return [Object]
def search_with_cache(index, location:)
- cache([index.cache_key, Searcher.skip?, Searcher.fallback?]) do
- search(index, location: location)
+ cache([index.cache_key, Searcher.context, Searcher.skip?, Searcher.fallback?]) do
+ search_with_context(index, location: location, context: Searcher.context)
end
end
def cache(key)
@cache ||= {}
@@ -54,15 +68,75 @@
# 2. fallback to other key
# 3. skip the key and go to child location
def next_location_cadidates(location, key)
[
location[key.symbol],
- Searcher.fallback? && key.fallback && location[key.fallback],
Searcher.skip? && key.skippable && location
].compact
end
class << self
+ # @return [Hash]
+ def conditions(&block)
+ {
+ nothing: -> { block.call },
+ skip: -> { Config::Searcher.skip { block.call } }
+ }
+ end
+
+ # Execute block with specified conditions
+ # @param conidtion [Symbol]
+ # @return [Object]
+ def with_condition(condition, &block)
+ conditions(&block)[condition].call
+ end
+
+ # Execute block with all conditions
+ # @return [Array<Symbol, Object>]
+ def find_condition(&block)
+ conditions(&block).find do |c, l|
+ result = l.call
+ return [c, result] if result
+
+ nil
+ end
+ end
+
+ # Search with context from load_streamed Config
+ # @param context [Hash]
+ # @return [Object]
+ def with_context(context, &block)
+ @context = context || {}
+ result = block.call
+ @context = {}
+ result
+ end
+
+ # Return a matching context from config
+ # @params request_context [Hash]
+ # @return [Hash]
+ def find_context(request_context, &block)
+ # Search in blocks in the following order.
+ # 1. complete match config[:context] == request_context
+ # 2. partial match config[:context] =~ request_context
+ # 3. no context
+ Config.instance.keymap.each do |config|
+ next unless config[:context] == request_context
+ return config[:context] if with_context(config[:context]) { block.call }
+ end
+ if request_context.keys.size > 1
+ Config.instance.keymap.each do |config|
+ next if config[:context].nil?
+
+ next unless config[:context].all? { |k, v| request_context[k] == v }
+ return config[:context] if with_context(config[:context]) { block.call }
+ end
+ end
+ return {} if with_context({}) { block.call }
+ end
+
+ attr_reader :context
+
def fallback?
@fallback
end
def skip?