needle_in_a_haystack 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/needle_in_a_haystack/concerns/base_tag.rb +24 -4
- data/lib/needle_in_a_haystack/factories/base_factory.rb +13 -0
- data/lib/needle_in_a_haystack/factories/haystack_factory.rb +38 -0
- data/lib/needle_in_a_haystack/models/haystack_ontology.rb +9 -18
- data/lib/needle_in_a_haystack/models/haystack_tag.rb +15 -17
- data/lib/needle_in_a_haystack/strategies/default_tag_strategy.rb +9 -0
- data/lib/needle_in_a_haystack/strategies/find_by_tag_strategy.rb +11 -0
- data/lib/needle_in_a_haystack/strategies/find_point_by_tag_strategy.rb +11 -0
- data/lib/needle_in_a_haystack/strategies/find_points_with_multiple_tags_strategy.rb +14 -0
- data/lib/needle_in_a_haystack/strategies/ontology_tag_strategy.rb +11 -0
- data/lib/needle_in_a_haystack/strategies/query_context.rb +9 -0
- data/lib/needle_in_a_haystack/strategies/query_strategy.rb +5 -0
- data/lib/needle_in_a_haystack/strategies/tag_strategy.rb +9 -0
- data/lib/needle_in_a_haystack/version.rb +1 -1
- data/lib/needle_in_a_haystack.rb +10 -0
- metadata +12 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d0d636da24994074ca2e0d360e34eb2cbb71b18fd5a7af9b5940357069c2c99c
         | 
| 4 | 
            +
              data.tar.gz: 04c8d8ef066aede9ef052a1aa5a619959a3b40927d89699912e462a919ce91e5
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: e46870a3a6ffa25cdd61dec219bbfcd520e27a991ad8e38ba63deb69082394226e50060dae345151cbc264590a9d88cf5337509d94694e942759fe9f96ec1a89
         | 
| 7 | 
            +
              data.tar.gz: f6ec23b578c01343a147493622f9f4e32d16dee03f92359b9fba0815dda00b04f2084b8391a96d0cc673380f452603d8811120d4652a69c1c7ad5a6c6b6b53bf
         | 
| @@ -1,11 +1,31 @@ | |
| 1 1 | 
             
            class BaseTag < ApplicationRecord
         | 
| 2 2 | 
             
              self.abstract_class = true
         | 
| 3 3 |  | 
| 4 | 
            -
              def  | 
| 5 | 
            -
                raise NotImplementedError, "Subclasses must implement a  | 
| 4 | 
            +
              def full_path
         | 
| 5 | 
            +
                raise NotImplementedError, "Subclasses must implement a full_path-method"
         | 
| 6 6 | 
             
              end
         | 
| 7 7 |  | 
| 8 | 
            -
              def  | 
| 9 | 
            -
                raise NotImplementedError, "Subclasses must implement a  | 
| 8 | 
            +
              def prevent_circular_reference
         | 
| 9 | 
            +
                raise NotImplementedError, "Subclasses must implement a prevent_circular_reference-method"
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def ancestors
         | 
| 13 | 
            +
                raise NotImplementedError, "Subclasses must implement an ancestors-method"
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              def descendants
         | 
| 17 | 
            +
                raise NotImplementedError, "Subclasses must implement a descendants-method"
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def siblings
         | 
| 21 | 
            +
                raise NotImplementedError, "Subclasses must implement a siblings-method"
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def root?
         | 
| 25 | 
            +
                raise NotImplementedError, "Subclasses must implement a root?-method"
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def leaf?
         | 
| 29 | 
            +
                raise NotImplementedError, "Subclasses must implement a leaf?-method"
         | 
| 10 30 | 
             
              end
         | 
| 11 31 | 
             
            end
         | 
| @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            class BaseFactory
         | 
| 2 | 
            +
              def create_tag(name, description)
         | 
| 3 | 
            +
                raise NotImplementedError, "Subclasses must implement a create_tag-method"
         | 
| 4 | 
            +
              end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def create_tagging(tag, taggable)
         | 
| 7 | 
            +
                raise NotImplementedError, "Subclasses must implement a create_tagging-method"
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def find_or_create_tag(name, attributes = {})
         | 
| 11 | 
            +
                raise NotImplementedError, "Subclasses must implement a find_or_create_tag-method"
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
            end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            class HaystackFactory < BaseFactory
         | 
| 2 | 
            +
              attr_accessor :tag_strategy
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              def initialize(tag_strategy = DefaultTagStrategy.new)
         | 
| 5 | 
            +
                super()
         | 
| 6 | 
            +
                @tag_strategy = tag_strategy
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def create_tag(name, description)
         | 
| 10 | 
            +
                @tag_strategy.create_tag(name, description)
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              def create_tagging(tag, taggable)
         | 
| 14 | 
            +
                HaystackTagging.create(haystack_tag: tag, taggable: taggable)
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def find_or_create_tag(name, attributes = {})
         | 
| 18 | 
            +
                tag = HaystackTag.find_or_create_by(name: name)
         | 
| 19 | 
            +
                @tag_strategy.update_tag(tag, attributes)
         | 
| 20 | 
            +
                tag
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              def create_tags(tag_hash, parent_tag = nil)
         | 
| 24 | 
            +
                tag_hash.each do |name, data|
         | 
| 25 | 
            +
                  next if %w[description children].include?(name)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  tag = find_or_create_tag(name, description: data["description"], haystack_marker: data["marker"])
         | 
| 28 | 
            +
                  tag.update(parent_tag_id: parent_tag&.id)
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  Rails.logger.info("Created tag: #{tag.name}, Parent: #{parent_tag&.name}, Parent ID: #{parent_tag&.id}")
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  if data["children"]
         | 
| 33 | 
            +
                    Rails.logger.info("Processing children for tag: #{tag.name}")
         | 
| 34 | 
            +
                    create_tags(data["children"], tag)
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
| @@ -38,29 +38,20 @@ class HaystackOntology < ApplicationRecord | |
| 38 38 | 
             
              end
         | 
| 39 39 |  | 
| 40 40 | 
             
              def self.create_tags
         | 
| 41 | 
            -
                 | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
              def self.create_tag_hierarchy(tag_hash, parent_tag = nil)
         | 
| 45 | 
            -
                tag_hash.each do |name, data|
         | 
| 46 | 
            -
                  next if %w[description children].include?(name)
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                  tag = HaystackTag.find_or_create_by(name: name.to_s)
         | 
| 49 | 
            -
                  tag.update(description: data["description"], parent_tag_id: parent_tag&.id, haystack_marker: data["marker"])
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                  Rails.logger.info("Created tag: #{tag.name}, Parent: #{parent_tag&.name}")
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                  create_tag_hierarchy(data["children"], tag) if data["children"]
         | 
| 54 | 
            -
                end
         | 
| 41 | 
            +
                factory = HaystackFactory.new(OntologyTagStrategy.new)
         | 
| 42 | 
            +
                factory.create_tags(tags)
         | 
| 55 43 | 
             
              end
         | 
| 56 44 |  | 
| 57 45 | 
             
              def self.find_or_create_tag(name)
         | 
| 46 | 
            +
                factory = HaystackFactory.new(OntologyTagStrategy.new)
         | 
| 58 47 | 
             
                tag_data = find_tag(name)
         | 
| 59 48 | 
             
                return nil if tag_data.nil?
         | 
| 60 49 |  | 
| 61 | 
            -
                 | 
| 62 | 
            -
                 | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 50 | 
            +
                attributes = { description: tag_data["description"], haystack_marker: tag_data["marker"] }
         | 
| 51 | 
            +
                factory.find_or_create_tag(name, attributes)
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              def self.import_full_ontology
         | 
| 55 | 
            +
                create_tags
         | 
| 65 56 | 
             
              end
         | 
| 66 57 | 
             
            end
         | 
| @@ -2,47 +2,43 @@ class HaystackTag < BaseTag | |
| 2 2 | 
             
              belongs_to :parent_tag, class_name: "HaystackTag", optional: true
         | 
| 3 3 | 
             
              has_many :children, class_name: "HaystackTag", foreign_key: "parent_tag_id", dependent: :destroy, inverse_of: :parent_tag
         | 
| 4 4 | 
             
              has_many :haystack_taggings, dependent: :destroy
         | 
| 5 | 
            -
              has_many :taggables, through: :haystack_taggings
         | 
| 5 | 
            +
              has_many :taggables, through: :haystack_taggings, source: :taggable
         | 
| 6 6 |  | 
| 7 7 | 
             
              validates :name, presence: true, uniqueness: true
         | 
| 8 8 | 
             
              validates :description, presence: true
         | 
| 9 9 | 
             
              validate :prevent_circular_reference
         | 
| 10 10 |  | 
| 11 | 
            -
              def name
         | 
| 12 | 
            -
                self[:name]
         | 
| 13 | 
            -
              end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
              def description
         | 
| 16 | 
            -
                self[:description]
         | 
| 17 | 
            -
              end
         | 
| 18 | 
            -
             | 
| 19 11 | 
             
              def ancestors
         | 
| 20 12 | 
             
                ancestors = []
         | 
| 21 13 | 
             
                current = self
         | 
| 22 14 | 
             
                while current.parent_tag
         | 
| 15 | 
            +
                  break if ancestors.include?(current.parent_tag) # Voorkom oneindige lus
         | 
| 23 16 | 
             
                  ancestors << current.parent_tag
         | 
| 24 17 | 
             
                  current = current.parent_tag
         | 
| 25 18 | 
             
                end
         | 
| 26 19 | 
             
                ancestors
         | 
| 27 20 | 
             
              end
         | 
| 28 21 |  | 
| 22 | 
            +
              def full_path
         | 
| 23 | 
            +
                ancestors.reverse.map(&:name).join(" > ") + " > " + name
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 29 26 | 
             
              def self.find_by_path(path)
         | 
| 30 27 | 
             
                keys = path.split(".")
         | 
| 31 28 | 
             
                current = nil
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                  current = current ? current. | 
| 29 | 
            +
                  keys.each do |key|
         | 
| 30 | 
            +
                  current = current ? current.children.find_by(name: key) : find_by(name: key)
         | 
| 34 31 | 
             
                  return nil unless current
         | 
| 35 32 | 
             
                end
         | 
| 36 33 | 
             
                current
         | 
| 37 34 | 
             
              end
         | 
| 38 35 |  | 
| 39 36 | 
             
              def descendants
         | 
| 40 | 
            -
                children = child_tags
         | 
| 41 37 | 
             
                children + children.flat_map(&:descendants)
         | 
| 42 38 | 
             
              end
         | 
| 43 39 |  | 
| 44 40 | 
             
              def siblings
         | 
| 45 | 
            -
                parent_tag ? parent_tag. | 
| 41 | 
            +
                parent_tag ? parent_tag.children.where.not(id: id) : self.class.where(parent_tag_id: nil).where.not(id: id)
         | 
| 46 42 | 
             
              end
         | 
| 47 43 |  | 
| 48 44 | 
             
              def root?
         | 
| @@ -50,16 +46,18 @@ class HaystackTag < BaseTag | |
| 50 46 | 
             
              end
         | 
| 51 47 |  | 
| 52 48 | 
             
              def leaf?
         | 
| 53 | 
            -
                 | 
| 49 | 
            +
                children.empty?
         | 
| 54 50 | 
             
              end
         | 
| 55 51 |  | 
| 56 52 | 
             
              def depth
         | 
| 57 53 | 
             
                ancestors.size
         | 
| 58 54 | 
             
              end
         | 
| 59 55 |  | 
| 60 | 
            -
               | 
| 61 | 
            -
                return unless parent_tag == self || ancestors.include?(self)
         | 
| 56 | 
            +
              private
         | 
| 62 57 |  | 
| 63 | 
            -
             | 
| 58 | 
            +
              def prevent_circular_reference
         | 
| 59 | 
            +
                if parent_tag == self || ancestors.include?(self)
         | 
| 60 | 
            +
                  errors.add(:parent_tag, "kan geen circulaire referentie bevatten")
         | 
| 61 | 
            +
                end
         | 
| 64 62 | 
             
              end
         | 
| 65 63 | 
             
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            class FindPointsWithMultipleTagsStrategy < QueryStrategy
         | 
| 2 | 
            +
              def initialize(model, tags)
         | 
| 3 | 
            +
                super()
         | 
| 4 | 
            +
                @model = model
         | 
| 5 | 
            +
                @tags = tags
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              def execute
         | 
| 9 | 
            +
                @model.joins(:haystack_tags)
         | 
| 10 | 
            +
                      .where(haystack_tags: { id: @tags.map(&:id) })
         | 
| 11 | 
            +
                      .group("#{@model.table_name}.id")
         | 
| 12 | 
            +
                      .having("COUNT(haystack_tags.id) = ?", @tags.size)
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,9 @@ | |
| 1 | 
            +
            class TagStrategy
         | 
| 2 | 
            +
              def create_tag(name, description)
         | 
| 3 | 
            +
                raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
         | 
| 4 | 
            +
              end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def update_tag(tag, attributes)
         | 
| 7 | 
            +
                raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
            end
         | 
| @@ -1 +1 @@ | |
| 1 | 
            -
            VERSION = "1.0. | 
| 1 | 
            +
            VERSION = "1.0.5".freeze
         | 
    
        data/lib/needle_in_a_haystack.rb
    CHANGED
    
    | @@ -4,10 +4,20 @@ require "needle_in_a_haystack/application_record" | |
| 4 4 | 
             
            require "needle_in_a_haystack/configuration"
         | 
| 5 5 | 
             
            require "needle_in_a_haystack/concerns/base_tagging"
         | 
| 6 6 | 
             
            require "needle_in_a_haystack/concerns/base_tag"
         | 
| 7 | 
            +
            require "needle_in_a_haystack/factories/base_factory"
         | 
| 7 8 |  | 
| 8 9 | 
             
            require "needle_in_a_haystack/models/haystack_ontology"
         | 
| 9 10 | 
             
            require "needle_in_a_haystack/models/haystack_tag"
         | 
| 10 11 | 
             
            require "needle_in_a_haystack/models/haystack_tagging"
         | 
| 12 | 
            +
            require "needle_in_a_haystack/factories/haystack_factory"
         | 
| 13 | 
            +
            require "needle_in_a_haystack/strategies/query_context"
         | 
| 14 | 
            +
            require "needle_in_a_haystack/strategies/query_strategy"
         | 
| 15 | 
            +
            require "needle_in_a_haystack/strategies/find_by_tag_strategy"
         | 
| 16 | 
            +
            require "needle_in_a_haystack/strategies/find_point_by_tag_strategy"
         | 
| 17 | 
            +
            require "needle_in_a_haystack/strategies/find_points_with_multiple_tags_strategy"
         | 
| 18 | 
            +
            require "needle_in_a_haystack/strategies/tag_strategy"
         | 
| 19 | 
            +
            require "needle_in_a_haystack/strategies/default_tag_strategy"
         | 
| 20 | 
            +
            require "needle_in_a_haystack/strategies/ontology_tag_strategy"
         | 
| 11 21 |  | 
| 12 22 | 
             
            module NeedleInAHaystack
         | 
| 13 23 | 
             
              class << self
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: needle_in_a_haystack
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.0. | 
| 4 | 
            +
              version: 1.0.5
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Frans Verberne
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2024- | 
| 11 | 
            +
            date: 2024-12-05 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bcrypt_pbkdf
         | 
| @@ -282,9 +282,19 @@ files: | |
| 282 282 | 
             
            - lib/needle_in_a_haystack/concerns/taggable.rb
         | 
| 283 283 | 
             
            - lib/needle_in_a_haystack/configuration.rb
         | 
| 284 284 | 
             
            - lib/needle_in_a_haystack/engine.rb
         | 
| 285 | 
            +
            - lib/needle_in_a_haystack/factories/base_factory.rb
         | 
| 286 | 
            +
            - lib/needle_in_a_haystack/factories/haystack_factory.rb
         | 
| 285 287 | 
             
            - lib/needle_in_a_haystack/models/haystack_ontology.rb
         | 
| 286 288 | 
             
            - lib/needle_in_a_haystack/models/haystack_tag.rb
         | 
| 287 289 | 
             
            - lib/needle_in_a_haystack/models/haystack_tagging.rb
         | 
| 290 | 
            +
            - lib/needle_in_a_haystack/strategies/default_tag_strategy.rb
         | 
| 291 | 
            +
            - lib/needle_in_a_haystack/strategies/find_by_tag_strategy.rb
         | 
| 292 | 
            +
            - lib/needle_in_a_haystack/strategies/find_point_by_tag_strategy.rb
         | 
| 293 | 
            +
            - lib/needle_in_a_haystack/strategies/find_points_with_multiple_tags_strategy.rb
         | 
| 294 | 
            +
            - lib/needle_in_a_haystack/strategies/ontology_tag_strategy.rb
         | 
| 295 | 
            +
            - lib/needle_in_a_haystack/strategies/query_context.rb
         | 
| 296 | 
            +
            - lib/needle_in_a_haystack/strategies/query_strategy.rb
         | 
| 297 | 
            +
            - lib/needle_in_a_haystack/strategies/tag_strategy.rb
         | 
| 288 298 | 
             
            - lib/needle_in_a_haystack/version.rb
         | 
| 289 299 | 
             
            - lib/tasks/location_create.rake
         | 
| 290 300 | 
             
            - spec/factories/haystack_tags.rb
         |