lib/locabulary.rb in locabulary-0.3.1 vs lib/locabulary.rb in locabulary-0.5.0

- old
+ new

@@ -1,125 +1,117 @@ require 'date' require 'json' require 'locabulary/exceptions' -require 'locabulary/items' +require 'locabulary/item' +require 'locabulary/commands/build_ordered_hierarchical_tree_command' +require 'locabulary/commands/active_items_for_command' +require 'locabulary/commands/active_hierarchical_roots_command' # @since 0.1.0 module Locabulary - DATA_DIRECTORY = File.expand_path("../../data/", __FILE__).freeze + # @api private + # @since 0.5.0 + # + # Responsible for building a hierarchical tree from faceted items, and ordering the nodes as per the presentation sequence for the + # associated predicate_name. + # + # @param [Hash] options + # @option options [String] :predicate_name + # @option options [Array<#hits, #value>] :faceted_items + # @option options [String] :faceted_item_hierarchy_delimiter + # @return Array[<FacetWrapperForItem>] + # + # @see Locabulary::Commands::BuildOrderedHierarchicalTree + def self.build_ordered_hierarchical_tree(options = {}) + Commands::BuildOrderedHierarchicalTreeCommand.call(options) + end - module_function - # @api public # @since 0.1.0 # - # @note A concession about the as_of; This is not a live query. The data has a - # low churn rate. And while the date is important, I'm not as concerned - # about the local controlled vocabulary exposing a date that has expired. - # When we next deploy the server changes, the deactivated will go away. - def active_items_for(options = {}) - predicate_name = options.fetch(:predicate_name) - as_of = options.fetch(:as_of) { Date.today } - builder = Items.builder_for(predicate_name: predicate_name) - active_cache[predicate_name] ||= begin - collector = [] - with_active_extraction_for(predicate_name, as_of) do |data| - collector << builder.call(data.merge('predicate_name' => predicate_name)) - end - collector.sort - end + # Responsible for extracting a non-hierarchical sorted array of Locabulary::Items::Base objects for the given predicate_name. + # + # @param [Hash] options + # @option options [String] :predicate_name + # @option options [Date] :as_of (Date.today) + # @return Array[<Locabulary::Items::Base>] + # + # @see Locabulary::Commands::ActiveItemsForCommand + def self.active_items_for(options = {}) + Commands::ActiveItemsForCommand.call(options) end # @api public - # @since 0.2.0 - def active_hierarchical_root(options = {}) + # @since 0.4.0 + # + # Responsible for transforming the flat data for the given :predicate_name + # into a hierarchy. + # + # @param [Hash] options + # @option options [String] :predicate_name + # @option options [Date] :as_of (Date.today) + # @return [Array<Locabulary::Items::Base>] - the root nodes + def self.active_hierarchical_roots(options = {}) + Commands::ActiveHierarchicalRootsCommand.call(options) + end + + # @api public + # @since 0.5.0 + # @param options [Hash] + # @option options [String] :predicate_name + # @option options [String] :term_label + # @option options [Date] :as_of (Date.today) + # @raise [Locabulary::Exceptions::ItemNotFoundError] if unable to find label for predicate_name + # @return [Locabulary::Items::Base] + def self.item_for(options = {}) predicate_name = options.fetch(:predicate_name) + term_label = options.fetch(:term_label) as_of = options.fetch(:as_of) { Date.today } - builder = Items.builder_for(predicate_name: predicate_name) - active_hierarchical_root_cache[predicate_name] ||= begin - items = [] - hierarchy_graph_keys = {} - top_level_slugs = Set.new - with_active_extraction_for(predicate_name, as_of) do |data| - item = builder.call(data.merge('predicate_name' => predicate_name)) - items << item - top_level_slugs << item.root_slug - hierarchy_graph_keys[item.term_label] = item - end - associate_parents_and_childrens_for(hierarchy_graph_keys, items, predicate_name) - raise Exceptions::TooManyHierarchicalRootsError.new(predicate_name, top_level_slugs.to_a) if top_level_slugs.size > 1 - hierarchy_graph_keys.fetch(top_level_slugs.first) + item = nil + Utility.with_extraction_for(predicate_name) do |data| + next unless data.fetch('term_label') == term_label + item = Item.build(data.merge('predicate_name' => predicate_name)) + break if Utility.data_is_active?(data, as_of) end + return item unless item.nil? + raise Locabulary::Exceptions::ItemNotFoundError.new(predicate_name, term_label) end - def associate_parents_and_childrens_for(hierarchy_graph_keys, items, predicate_name) - items.each do |item| - begin - hierarchy_graph_keys.fetch(item.parent_term_label).add_child(item) unless item.parent_slugs.empty? - rescue KeyError => error - raise Exceptions::MissingHierarchicalParentError.new(predicate_name, error) - end - end - end - private :associate_parents_and_childrens_for - - def with_active_extraction_for(predicate_name, as_of) - filename = filename_for_predicate_name(predicate_name: predicate_name) - json = JSON.parse(File.read(filename)) - json.fetch('values').each do |data| - yield(data) if data_is_active?(data, as_of) - end - end - private :with_active_extraction_for - - def data_is_active?(data, as_of) - activated_on = Date.parse(data.fetch('activated_on')) - return false unless activated_on < as_of - deactivated_on_value = data.fetch('deactivated_on', nil) - return true if deactivated_on_value.nil? - deactivated_on = Date.parse(deactivated_on_value) - return false unless deactivated_on >= as_of - true - end - private :data_is_active? - # @api public # @since 0.1.0 - def active_label_for_uri(options = {}) - predicate_name = options.fetch(:predicate_name) + # + # @param [Hash] options + # @option options [String] :predicate_name + # @option options [String] :term_uri + # @option options [String] :as_of (Date.today) + # + # @return [String] a label or URI + # + # @see Locabulary.active_items_for + def self.active_label_for_uri(options = {}) term_uri = options.fetch(:term_uri) - object = active_items_for(predicate_name: predicate_name).detect { |obj| obj.term_uri == term_uri } + object = active_items_for(options).detect { |obj| obj.term_uri == term_uri } return object.term_label if object term_uri end # @api public # @since 0.1.0 - def active_labels_for(options = {}) - predicate_name = options.fetch(:predicate_name) - active_items_for(predicate_name: predicate_name).map(&:term_label) + # + # Return an Array of term labels for the given :predicate_name + # + # @param [Hash] options + # @option options [String] :predicate_name + # @option options [String] :as_of (Date.today) + # @return [Array<String>] an array of Locabuarly::Items::Base#term_label + # + # @see Locabulary.active_items_for + def self.active_labels_for(options = {}) + active_items_for(options).map(&:term_label) end # @api private - def filename_for_predicate_name(options = {}) - predicate_name = options.fetch(:predicate_name) - filename = File.join(DATA_DIRECTORY, "#{File.basename(predicate_name)}.json") - return filename if File.exist?(filename) - raise Locabulary::Exceptions::RuntimeError, "Unable to find predicate_name: #{predicate_name}" - end - - # @api private - def active_cache - @active_cache ||= {} - end - - # @api private - def active_hierarchical_root_cache - @active_hierarchical_root_cache ||= {} - end - - # @api private - def reset_active_cache! - @active_cache = nil - @active_hierarchical_root_cache = nil + def self.reset_active_cache! + Commands::ActiveItemsForCommand.reset_cache! + Commands::ActiveHierarchicalRootsCommand.reset_cache! end end