lib/data_miner/dictionary.rb in data_miner-2.0.1 vs lib/data_miner/dictionary.rb in data_miner-2.0.2

- old
+ new

@@ -1,60 +1,82 @@ require 'remote_table' class DataMiner + # An easy way to translate data before importing it using an intermediate table. class Dictionary DEFAULT_CASE_SENSITIVE = true + # What field in the dictionary holds the lookup key. + # + # In other words, the column we scan down to find an entry. + # + # @return [String] attr_reader :key_name + + # What field in the dictionary holds the final value. + # + # @return [String] attr_reader :value_name + + # A +sprintf+-style format to be applied. + # @return [String] attr_reader :sprintf + + # The URL of the dictionary. It must be a CSV. + # @return [String] attr_reader :url + + # Whether to be case-sensitive with lookups. Defaults to false. + # @return [TrueClass, FalseClass] attr_reader :case_sensitive + # @private def initialize(options = {}) options = options.symbolize_keys @url = options[:url] - @key_name = options[:input] - @value_name = options[:output] + @key_name = options[:input].to_s + @value_name = options[:output].to_s @sprintf = options[:sprintf] @case_sensitive = options.fetch :case_sensitive, DEFAULT_CASE_SENSITIVE @table_mutex = ::Mutex.new end + # Look up a translation for a value. + # + # @return [nil, String] + def lookup(value) + normalized_value = normalize_for_comparison value + if match = table.detect { |entry| entry[key_name] == normalized_value } + match[value_name].to_s + end + end + + private + def table @table || @table_mutex.synchronize do - @table ||= ::RemoteTable.new(url).to_a # make sure it's fully cached + @table ||= ::RemoteTable.new(url).map do |entry| + entry[key_name] = normalize_for_comparison entry[key_name] + entry + end end end def refresh @table = nil end - - def lookup(key) - find key_name, key, value_name, {:sprintf => sprintf, :case_sensitive => case_sensitive} - end - - def find(key_name, key, value_name, options = {}) - normalized_key = normalize_for_comparison(key, options) - if match = table.detect { |row| normalized_key == normalize_for_comparison(row[key_name.to_s], options) } - match[value_name.to_s].to_s - end - end - - private - def normalize_for_comparison(str, options = {}) + def normalize_for_comparison(str) if sprintf if sprintf.end_with?('f') str = str.to_f elsif sprintf.end_with?('d') str = str.to_i end str = sprintf % str end str = DataMiner.compress_whitespace str - unless options[:case_sensitive] + unless case_sensitive str = DataMiner.downcase str end str end end