stretchy-model 0.3.0 → 0.4.0
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/README.md +21 -10
- data/Rakefile +92 -0
- data/lib/stretchy/attributes/transformers/keyword_transformer.rb +85 -0
- data/lib/stretchy/attributes/type/keyword.rb +11 -0
- data/lib/stretchy/attributes.rb +10 -0
- data/lib/stretchy/querying.rb +6 -5
- data/lib/stretchy/relation.rb +3 -3
- data/lib/stretchy/relations/aggregation_methods.rb +758 -0
- data/lib/stretchy/relations/finder_methods.rb +21 -3
- data/lib/stretchy/relations/merger.rb +6 -6
- data/lib/stretchy/relations/query_builder.rb +23 -9
- data/lib/stretchy/relations/query_methods.rb +10 -36
- data/lib/stretchy/utils.rb +21 -0
- data/lib/stretchy/version.rb +1 -3
- data/lib/stretchy.rb +21 -9
- metadata +35 -3
| @@ -9,7 +9,15 @@ module Stretchy | |
| 9 9 | 
             
                    end
         | 
| 10 10 |  | 
| 11 11 | 
             
                    def first!
         | 
| 12 | 
            -
                       | 
| 12 | 
            +
                      spawned = spawn
         | 
| 13 | 
            +
                      if spawned.order_values.length.zero? 
         | 
| 14 | 
            +
                        spawn.sort(Hash[default_sort_key, :asc]).spawn.size(1)
         | 
| 15 | 
            +
                      elsif spawned.order_values.length >= 1
         | 
| 16 | 
            +
                        first_order_value = spawned.order_values.shift
         | 
| 17 | 
            +
                        new_direction = Hash[first_order_value.keys.first, :asc] 
         | 
| 18 | 
            +
                        spawned.order_values.unshift(new_direction)
         | 
| 19 | 
            +
                        spawned.size(1)
         | 
| 20 | 
            +
                      end
         | 
| 13 21 | 
             
                      self
         | 
| 14 22 | 
             
                    end
         | 
| 15 23 |  | 
| @@ -19,7 +27,15 @@ module Stretchy | |
| 19 27 | 
             
                    end
         | 
| 20 28 |  | 
| 21 29 | 
             
                    def last!
         | 
| 22 | 
            -
                       | 
| 30 | 
            +
                      spawned = spawn
         | 
| 31 | 
            +
                      if spawned.order_values.length.zero?
         | 
| 32 | 
            +
                        spawn.sort(Hash[default_sort_key, :desc]).spawn.size(1)
         | 
| 33 | 
            +
                      elsif spawned.order_values.length >= 1
         | 
| 34 | 
            +
                        first_order_value = spawned.order_values.shift
         | 
| 35 | 
            +
                        new_direction = Hash[first_order_value.keys.first, :desc] 
         | 
| 36 | 
            +
                        spawned.order_values.unshift(new_direction)
         | 
| 37 | 
            +
                        spawned.size(1)
         | 
| 38 | 
            +
                      end
         | 
| 23 39 | 
             
                      self
         | 
| 24 40 | 
             
                    end
         | 
| 25 41 |  | 
| @@ -31,7 +47,9 @@ module Stretchy | |
| 31 47 | 
             
                    def count!
         | 
| 32 48 | 
             
                      @values[:count] = true
         | 
| 33 49 | 
             
                      @values.delete(:size)
         | 
| 34 | 
            -
                      spawn | 
| 50 | 
            +
                      spawned = spawn
         | 
| 51 | 
            +
                      spawned.order_values.clear
         | 
| 52 | 
            +
                      spawned.results
         | 
| 35 53 | 
             
                    end
         | 
| 36 54 |  | 
| 37 55 | 
             
                  end
         | 
| @@ -50,7 +50,7 @@ module Stretchy | |
| 50 50 | 
             
                      @other    = other
         | 
| 51 51 | 
             
                    end
         | 
| 52 52 |  | 
| 53 | 
            -
                    NORMAL_VALUES = [:where, :first, :last, : | 
| 53 | 
            +
                    NORMAL_VALUES = [:where, :first, :last, :filter_query]
         | 
| 54 54 |  | 
| 55 55 | 
             
                    def normal_values
         | 
| 56 56 | 
             
                      NORMAL_VALUES
         | 
| @@ -67,7 +67,7 @@ module Stretchy | |
| 67 67 | 
             
                        unless value.nil? || (value.blank? && false != value)
         | 
| 68 68 | 
             
                          if name == :select
         | 
| 69 69 | 
             
                            relation._select!(*value)
         | 
| 70 | 
            -
                          elsif name == : | 
| 70 | 
            +
                          elsif name == :filter_query
         | 
| 71 71 | 
             
                            values.each do |v|
         | 
| 72 72 | 
             
                              relation.send("#{name}!", v.first, v.last)
         | 
| 73 73 | 
             
                            end
         | 
| @@ -114,19 +114,19 @@ module Stretchy | |
| 114 114 | 
             
                      lhs_wheres = relation.where_values
         | 
| 115 115 | 
             
                      rhs_wheres = values[:where] || []
         | 
| 116 116 |  | 
| 117 | 
            -
                      lhs_filters = relation. | 
| 118 | 
            -
                      rhs_filters = values[: | 
| 117 | 
            +
                      lhs_filters = relation.filter_query_values
         | 
| 118 | 
            +
                      rhs_filters = values[:filter_query] || []
         | 
| 119 119 |  | 
| 120 120 | 
             
                      removed, kept = partition_overwrites(lhs_wheres, rhs_wheres)
         | 
| 121 121 |  | 
| 122 122 | 
             
                      where_values = kept + rhs_wheres
         | 
| 123 123 |  | 
| 124 124 | 
             
                      filters_removed, filters_kept = partition_overwrites(lhs_wheres, rhs_wheres)
         | 
| 125 | 
            -
                       | 
| 125 | 
            +
                      filter_query_values =  rhs_filters
         | 
| 126 126 |  | 
| 127 127 |  | 
| 128 128 | 
             
                      relation.where_values = where_values.empty? ? nil : where_values
         | 
| 129 | 
            -
                      relation. | 
| 129 | 
            +
                      relation.filter_query_values = filter_query_values.empty? ? nil : filter_query_values
         | 
| 130 130 |  | 
| 131 131 | 
             
                      if values[:reordering]
         | 
| 132 132 | 
             
                        # override any order specified in the original relation
         | 
| @@ -2,9 +2,10 @@ module Stretchy | |
| 2 2 | 
             
              module Relations
         | 
| 3 3 | 
             
                class QueryBuilder
         | 
| 4 4 |  | 
| 5 | 
            -
                  attr_reader :structure, :values
         | 
| 5 | 
            +
                  attr_reader :structure, :values, :attribute_types
         | 
| 6 6 |  | 
| 7 | 
            -
                  def initialize(values)
         | 
| 7 | 
            +
                  def initialize(values, attribute_types = nil)
         | 
| 8 | 
            +
                    @attribute_types = attribute_types
         | 
| 8 9 | 
             
                    @structure = Jbuilder.new ignore_nil: true
         | 
| 9 10 | 
             
                    @values = values
         | 
| 10 11 | 
             
                  end
         | 
| @@ -14,7 +15,7 @@ module Stretchy | |
| 14 15 | 
             
                  end
         | 
| 15 16 |  | 
| 16 17 | 
             
                  def filters
         | 
| 17 | 
            -
                    values[: | 
| 18 | 
            +
                    values[:filter_query]
         | 
| 18 19 | 
             
                  end
         | 
| 19 20 |  | 
| 20 21 | 
             
                  def or_filters
         | 
| @@ -58,7 +59,7 @@ module Stretchy | |
| 58 59 | 
             
                  end
         | 
| 59 60 |  | 
| 60 61 | 
             
                  def query_filters
         | 
| 61 | 
            -
                    values[: | 
| 62 | 
            +
                    values[:filter_query]
         | 
| 62 63 | 
             
                  end
         | 
| 63 64 |  | 
| 64 65 | 
             
                  def search_options
         | 
| @@ -149,7 +150,7 @@ module Stretchy | |
| 149 150 | 
             
                  end
         | 
| 150 151 |  | 
| 151 152 | 
             
                  def build_sort
         | 
| 152 | 
            -
                    structure.sort sort. | 
| 153 | 
            +
                    structure.sort sort.map { |arg| keyword_transformer.transform(arg) }.flatten
         | 
| 153 154 | 
             
                  end
         | 
| 154 155 |  | 
| 155 156 | 
             
                  def build_highlights
         | 
| @@ -165,7 +166,7 @@ module Stretchy | |
| 165 166 | 
             
                  def build_aggregations
         | 
| 166 167 | 
             
                    structure.aggregations do
         | 
| 167 168 | 
             
                      aggregations.each do |agg|
         | 
| 168 | 
            -
                        structure.set! agg[:name], aggregation(agg[:name], agg[:args])
         | 
| 169 | 
            +
                        structure.set! agg[:name], aggregation(agg[:name], keyword_transformer.transform(agg[:args], :name))
         | 
| 169 170 | 
             
                      end
         | 
| 170 171 | 
             
                    end
         | 
| 171 172 | 
             
                  end
         | 
| @@ -199,13 +200,23 @@ module Stretchy | |
| 199 200 | 
             
                  def as_must(q)
         | 
| 200 201 | 
             
                    _must = []
         | 
| 201 202 | 
             
                    q.each do |arg|
         | 
| 202 | 
            -
                       | 
| 203 | 
            -
                       | 
| 204 | 
            -
             | 
| 203 | 
            +
                      case arg
         | 
| 204 | 
            +
                      when Hash
         | 
| 205 | 
            +
                        arg = keyword_transformer.transform(arg)
         | 
| 206 | 
            +
                        arg.each_pair do |k,v| 
         | 
| 207 | 
            +
                          # If v is an array, we build a terms query otherwise a term query
         | 
| 208 | 
            +
                          _must << (v.is_a?(Array) ? {terms: Hash[k,v]} : {term: Hash[k,v]}) 
         | 
| 209 | 
            +
                        end
         | 
| 210 | 
            +
                      when String
         | 
| 211 | 
            +
                        _must << {term: Hash[[arg.split(/:/).collect(&:strip)]]}
         | 
| 212 | 
            +
                      when Array
         | 
| 213 | 
            +
                        _must << arg.first
         | 
| 214 | 
            +
                      end
         | 
| 205 215 | 
             
                    end
         | 
| 206 216 | 
             
                    _must.length == 1 ? _must.first : _must
         | 
| 207 217 | 
             
                  end
         | 
| 208 218 |  | 
| 219 | 
            +
             | 
| 209 220 | 
             
                  def as_query_string(q)
         | 
| 210 221 | 
             
                    _and = []
         | 
| 211 222 |  | 
| @@ -260,6 +271,9 @@ module Stretchy | |
| 260 271 | 
             
                    end
         | 
| 261 272 | 
             
                  end
         | 
| 262 273 |  | 
| 274 | 
            +
                  def keyword_transformer
         | 
| 275 | 
            +
                    @keyword_transformer ||= Stretchy::Attributes::Transformers::KeywordTransformer.new(@attribute_types)
         | 
| 276 | 
            +
                  end
         | 
| 263 277 | 
             
                end
         | 
| 264 278 | 
             
              end
         | 
| 265 279 | 
             
            end
         | 
| @@ -15,7 +15,7 @@ module Stretchy | |
| 15 15 | 
             
                    :query_string,
         | 
| 16 16 | 
             
                    :aggregation,
         | 
| 17 17 | 
             
                    :search_option,
         | 
| 18 | 
            -
                    : | 
| 18 | 
            +
                    :filter_query, 
         | 
| 19 19 | 
             
                    :or_filter,
         | 
| 20 20 | 
             
                    :extending,
         | 
| 21 21 | 
             
                    :skip_callbacks
         | 
| @@ -308,7 +308,7 @@ module Stretchy | |
| 308 308 |  | 
| 309 309 |  | 
| 310 310 |  | 
| 311 | 
            -
                  # @deprecated in elasticsearch 7.x+ use {# | 
| 311 | 
            +
                  # @deprecated in elasticsearch 7.x+ use {#filter_query} instead
         | 
| 312 312 | 
             
                  def or_filter(name, options = {}, &block)
         | 
| 313 313 | 
             
                    spawn.or_filter!(name, options, &block)
         | 
| 314 314 | 
             
                  end
         | 
| @@ -322,53 +322,27 @@ module Stretchy | |
| 322 322 | 
             
                  #
         | 
| 323 323 | 
             
                  # This method supports all filters supported by Elasticsearch.
         | 
| 324 324 | 
             
                  #
         | 
| 325 | 
            -
                  # @overload  | 
| 325 | 
            +
                  # @overload filter_query(type, opts)
         | 
| 326 326 | 
             
                  #   @param type [Symbol] the type of filter to add (:range, :term, etc.)
         | 
| 327 327 | 
             
                  #   @param opts [Hash] a hash containing the attribute and value to filter by
         | 
| 328 328 | 
             
                  #
         | 
| 329 329 | 
             
                  # @example
         | 
| 330 | 
            -
                  #   Model. | 
| 331 | 
            -
                  #   Model. | 
| 330 | 
            +
                  #   Model.filter_query(:range, age: {gte: 30})
         | 
| 331 | 
            +
                  #   Model.filter_query(:term, color: :blue)
         | 
| 332 332 | 
             
                  #
         | 
| 333 333 | 
             
                  # @return [Stretchy::Relation] a new relation, which reflects the filter
         | 
| 334 | 
            -
                  def  | 
| 335 | 
            -
                    spawn. | 
| 334 | 
            +
                  def filter_query(name, options = {}, &block)
         | 
| 335 | 
            +
                    spawn.filter_query!(name, options, &block)
         | 
| 336 336 | 
             
                  end
         | 
| 337 337 |  | 
| 338 | 
            -
                  def  | 
| 339 | 
            -
                    self. | 
| 338 | 
            +
                  def filter_query!(name, options = {}, &block) # :nodoc:
         | 
| 339 | 
            +
                    self.filter_query_values += [{name: name, args: options}]
         | 
| 340 340 | 
             
                    self
         | 
| 341 341 | 
             
                  end
         | 
| 342 342 |  | 
| 343 343 |  | 
| 344 344 |  | 
| 345 | 
            -
                  # Adds an aggregation to the query.
         | 
| 346 | 
            -
                  #
         | 
| 347 | 
            -
                  # @param name [Symbol, String] the name of the aggregation
         | 
| 348 | 
            -
                  # @param options [Hash] a hash of options for the aggregation
         | 
| 349 | 
            -
                  # @param block [Proc] an optional block to further configure the aggregation
         | 
| 350 | 
            -
                  #
         | 
| 351 | 
            -
                  # @example
         | 
| 352 | 
            -
                  #   Model.aggregation(:avg_price, field: :price)
         | 
| 353 | 
            -
                  #   Model.aggregation(:price_ranges) do
         | 
| 354 | 
            -
                  #     range field: :price, ranges: [{to: 100}, {from: 100, to: 200}, {from: 200}]
         | 
| 355 | 
            -
                  #   end
         | 
| 356 | 
            -
                  #
         | 
| 357 | 
            -
                  # Aggregation results are available in the `aggregations` method of the results under name provided in the aggregation.
         | 
| 358 | 
            -
                  #
         | 
| 359 | 
            -
                  # @example
         | 
| 360 | 
            -
                  #  results = Model.where(color: :blue).aggregation(:avg_price, field: :price)
         | 
| 361 | 
            -
                  #  results.aggregations.avg_price
         | 
| 362 | 
            -
                  #
         | 
| 363 | 
            -
                  # @return [Stretchy::Relation] a new relation
         | 
| 364 | 
            -
                  def aggregation(name, options = {}, &block)
         | 
| 365 | 
            -
                    spawn.aggregation!(name, options, &block)
         | 
| 366 | 
            -
                  end
         | 
| 367 345 |  | 
| 368 | 
            -
                  def aggregation!(name, options = {}, &block) # :nodoc:
         | 
| 369 | 
            -
                    self.aggregation_values += [{name: name, args: assume_keyword_field(options)}]
         | 
| 370 | 
            -
                    self
         | 
| 371 | 
            -
                  end
         | 
| 372 346 |  | 
| 373 347 |  | 
| 374 348 |  | 
| @@ -430,7 +404,7 @@ module Stretchy | |
| 430 404 | 
             
                  #
         | 
| 431 405 | 
             
                  # @return [ActiveRecord::Relation] a new relation, which reflects the exists filter
         | 
| 432 406 | 
             
                  def has_field(field)
         | 
| 433 | 
            -
                    spawn. | 
| 407 | 
            +
                    spawn.filter_query(:exists, {field: field})
         | 
| 434 408 | 
             
                  end
         | 
| 435 409 |  | 
| 436 410 |  | 
    
        data/lib/stretchy/utils.rb
    CHANGED
    
    | @@ -2,6 +2,27 @@ module Stretchy | |
| 2 2 | 
             
                module Utils
         | 
| 3 3 | 
             
                    extend ActiveSupport::Concern
         | 
| 4 4 |  | 
| 5 | 
            +
                        concerning :ConsoleMethods do
         | 
| 6 | 
            +
                            def reload!
         | 
| 7 | 
            +
                                Stretchy.loader.reload
         | 
| 8 | 
            +
                            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                            def banner
         | 
| 11 | 
            +
                                banner = <<~BANNER
         | 
| 12 | 
            +
                                                
         | 
| 13 | 
            +
                                                                                d8b                
         | 
| 14 | 
            +
                                           d8P                     d8P          ?88                
         | 
| 15 | 
            +
                                        d888888P                d888888P         88b               
         | 
| 16 | 
            +
                                 .d888b,  ?88'    88bd88b d8888b  ?88'   d8888b  888888b ?88   d8P 
         | 
| 17 | 
            +
                                 ?8b,     88P     88P'  `d8b_,dP  88P   d8P' `P  88P `?8bd88   88  
         | 
| 18 | 
            +
                                   `?8b   88b    d88     88b      88b   88b     d88   88P?8(  d88  
         | 
| 19 | 
            +
                                `?888P'   `?8b  d88'     `?888P'  `?8b  `?888P'd88'   88b`?88P'?8b 
         | 
| 20 | 
            +
                                                                                                )88
         | 
| 21 | 
            +
                                                                                               ,d8P
         | 
| 22 | 
            +
                                                                                            `?888P'
         | 
| 23 | 
            +
                                BANNER
         | 
| 24 | 
            +
                            end
         | 
| 25 | 
            +
                        end
         | 
| 5 26 |  | 
| 6 27 | 
             
                        def self.to_curl(klass, arguments = {}, end_point = "_search")
         | 
| 7 28 | 
             
                            host = klass.gateway.client.transport.transport.hosts&.first || klass.gateway.client.transport.transport.options[:url]
         | 
    
        data/lib/stretchy/version.rb
    CHANGED
    
    
    
        data/lib/stretchy.rb
    CHANGED
    
    | @@ -10,13 +10,28 @@ require 'active_support/all' | |
| 10 10 | 
             
            require 'active_model/type/array'
         | 
| 11 11 | 
             
            require 'active_model/type/hash'
         | 
| 12 12 |  | 
| 13 | 
            -
            ActiveModel::Type.register(:array, ActiveModel::Type::Array)
         | 
| 14 | 
            -
            ActiveModel::Type.register(:hash, ActiveModel::Type::Hash)
         | 
| 15 | 
            -
             | 
| 16 13 | 
             
            require_relative "stretchy/version"
         | 
| 17 14 | 
             
            require_relative "rails/instrumentation/railtie" if defined?(Rails)
         | 
| 18 15 |  | 
| 16 | 
            +
             | 
| 17 | 
            +
             | 
| 19 18 | 
             
            module Stretchy
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def self.loader
         | 
| 21 | 
            +
                @loader ||= begin
         | 
| 22 | 
            +
                  loader = Zeitwerk::Loader.new
         | 
| 23 | 
            +
                  loader.tag = File.basename(__FILE__, ".rb")
         | 
| 24 | 
            +
                  loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
         | 
| 25 | 
            +
                  loader.push_dir(__dir__)
         | 
| 26 | 
            +
                  loader
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              def self.boot!
         | 
| 31 | 
            +
                loader.setup
         | 
| 32 | 
            +
                Stretchy::Attributes.register!
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 20 35 | 
             
              module Errors
         | 
| 21 36 | 
             
                class QueryOptionMissing < StandardError; end
         | 
| 22 37 | 
             
              end
         | 
| @@ -61,12 +76,9 @@ module Stretchy | |
| 61 76 | 
             
                end
         | 
| 62 77 | 
             
              end
         | 
| 63 78 |  | 
| 64 | 
            -
            end
         | 
| 65 79 |  | 
| 80 | 
            +
            end
         | 
| 66 81 |  | 
| 82 | 
            +
            Stretchy.loader.enable_reloading if defined?(Rails) && Rails.env.development? || ENV['RACK_ENV'] == 'development'
         | 
| 83 | 
            +
            Stretchy.boot!
         | 
| 67 84 |  | 
| 68 | 
            -
            loader = Zeitwerk::Loader.new
         | 
| 69 | 
            -
            loader.tag = File.basename(__FILE__, ".rb")
         | 
| 70 | 
            -
            loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
         | 
| 71 | 
            -
            loader.push_dir(__dir__)
         | 
| 72 | 
            -
            loader.setup
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: stretchy-model
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.4.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Spencer Markowski
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2024-03- | 
| 11 | 
            +
            date: 2024-03-10 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: zeitwerk
         | 
| @@ -178,6 +178,34 @@ dependencies: | |
| 178 178 | 
             
                - - "~>"
         | 
| 179 179 | 
             
                  - !ruby/object:Gem::Version
         | 
| 180 180 | 
             
                    version: '3.0'
         | 
| 181 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 182 | 
            +
              name: octokit
         | 
| 183 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 184 | 
            +
                requirements:
         | 
| 185 | 
            +
                - - "~>"
         | 
| 186 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 187 | 
            +
                    version: '4.20'
         | 
| 188 | 
            +
              type: :development
         | 
| 189 | 
            +
              prerelease: false
         | 
| 190 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 191 | 
            +
                requirements:
         | 
| 192 | 
            +
                - - "~>"
         | 
| 193 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 194 | 
            +
                    version: '4.20'
         | 
| 195 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 196 | 
            +
              name: versionomy
         | 
| 197 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 198 | 
            +
                requirements:
         | 
| 199 | 
            +
                - - "~>"
         | 
| 200 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 201 | 
            +
                    version: 0.5.0
         | 
| 202 | 
            +
              type: :development
         | 
| 203 | 
            +
              prerelease: false
         | 
| 204 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 205 | 
            +
                requirements:
         | 
| 206 | 
            +
                - - "~>"
         | 
| 207 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 208 | 
            +
                    version: 0.5.0
         | 
| 181 209 | 
             
            description: Provides a familiar ActiveRecord-like interface for working with Elasticsearch
         | 
| 182 210 | 
             
            email:
         | 
| 183 211 | 
             
            - spencer.markowski@theablefew.com
         | 
| @@ -204,6 +232,9 @@ files: | |
| 204 232 | 
             
            - lib/stretchy/associations.rb
         | 
| 205 233 | 
             
            - lib/stretchy/associations/associated_validator.rb
         | 
| 206 234 | 
             
            - lib/stretchy/associations/elastic_relation.rb
         | 
| 235 | 
            +
            - lib/stretchy/attributes.rb
         | 
| 236 | 
            +
            - lib/stretchy/attributes/transformers/keyword_transformer.rb
         | 
| 237 | 
            +
            - lib/stretchy/attributes/type/keyword.rb
         | 
| 207 238 | 
             
            - lib/stretchy/common.rb
         | 
| 208 239 | 
             
            - lib/stretchy/delegation/delegate_cache.rb
         | 
| 209 240 | 
             
            - lib/stretchy/delegation/gateway_delegation.rb
         | 
| @@ -217,6 +248,7 @@ files: | |
| 217 248 | 
             
            - lib/stretchy/record.rb
         | 
| 218 249 | 
             
            - lib/stretchy/refreshable.rb
         | 
| 219 250 | 
             
            - lib/stretchy/relation.rb
         | 
| 251 | 
            +
            - lib/stretchy/relations/aggregation_methods.rb
         | 
| 220 252 | 
             
            - lib/stretchy/relations/finder_methods.rb
         | 
| 221 253 | 
             
            - lib/stretchy/relations/merger.rb
         | 
| 222 254 | 
             
            - lib/stretchy/relations/query_builder.rb
         | 
| @@ -257,7 +289,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 257 289 | 
             
                - !ruby/object:Gem::Version
         | 
| 258 290 | 
             
                  version: '0'
         | 
| 259 291 | 
             
            requirements: []
         | 
| 260 | 
            -
            rubygems_version: 3.3 | 
| 292 | 
            +
            rubygems_version: 3.5.3
         | 
| 261 293 | 
             
            signing_key:
         | 
| 262 294 | 
             
            specification_version: 4
         | 
| 263 295 | 
             
            summary: Rails ORM for Elasticsearch
         |