stretchy-model 0.1.0 → 0.3.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 +48 -3
- data/lib/rails/instrumentation/publishers.rb +1 -1
- data/lib/rails/instrumentation/railtie.rb +13 -19
- data/lib/stretchy/delegation/gateway_delegation.rb +1 -1
- data/lib/stretchy/open_search_compatibility.rb +86 -0
- data/lib/stretchy/scoping/scope_registry.rb +7 -7
- data/lib/stretchy/scoping.rb +4 -4
- data/lib/stretchy/version.rb +1 -1
- data/lib/stretchy.rb +37 -3
- data/stretchy-model/lib/stretchy-model.rb +1 -0
- metadata +25 -8
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: a85f7bffcc11c54366d4cae7fec47b91341425e06b7f1c8a6269e0b23d4e649b
         | 
| 4 | 
            +
              data.tar.gz: cd0b9314fa734aa7af7179f12ed00626a17bc869186f82088158bfca87c8d915
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: e193c837695100177eac9888841b14243596dfc9694515696ab1a9934174287c821cf52b2ca165e3f3eda04de9ba16c7c7330cb187641d71229d322c06674977
         | 
| 7 | 
            +
              data.tar.gz: 21ace7b64f85d505a05b61b89b5b85d9d2af34941b57672da45f70e6c8736e8b9451c59891fef7d0795f8b54076cffd88bfc141fcd4da1c1f8ffaddcf8276697
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            stretchy
         | 
| 1 | 
            +
            stretchy-model
         | 
| 2 2 | 
             
            ===
         | 
| 3 3 |  | 
| 4 4 | 
             
            <p>
         | 
| @@ -112,11 +112,37 @@ Blanket (6.322ms) curl -X GET 'http://localhost:9200/blankets/_search?size=1' -d | |
| 112 112 |  | 
| 113 113 | 
             
            Install the gem and add to the application's Gemfile by executing:
         | 
| 114 114 |  | 
| 115 | 
            -
                $ bundle add stretchy
         | 
| 115 | 
            +
                $ bundle add stretchy-model
         | 
| 116 116 |  | 
| 117 117 | 
             
            If bundler is not being used to manage dependencies, install the gem by executing:
         | 
| 118 118 |  | 
| 119 | 
            -
                $ gem install stretchy
         | 
| 119 | 
            +
                $ gem install stretchy-model
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            <details>
         | 
| 122 | 
            +
            <summary>Rails Configuration</summary>
         | 
| 123 | 
            +
             | 
| 124 | 
            +
             | 
| 125 | 
            +
             | 
| 126 | 
            +
            ```sh
         | 
| 127 | 
            +
            rails credentials:edit
         | 
| 128 | 
            +
            ```
         | 
| 129 | 
            +
             | 
| 130 | 
            +
            #### Add elasticsearch credentials
         | 
| 131 | 
            +
            ```yaml
         | 
| 132 | 
            +
            elasticsearch:
         | 
| 133 | 
            +
               url: localhost:9200
         | 
| 134 | 
            +
            ```
         | 
| 135 | 
            +
             | 
| 136 | 
            +
            #### Create an initializer 
         | 
| 137 | 
            +
            <p><sub><em>config/initializers/stretchy.rb</em></sub></p>
         | 
| 138 | 
            +
             | 
| 139 | 
            +
            ```ruby {file=config/initializers/stretchy.rb}
         | 
| 140 | 
            +
            Stretchy.configure do |config|
         | 
| 141 | 
            +
                config.client = Elasticsearch::Client.new url: Rails.application.credentials.elasticsearch.url, log: true
         | 
| 142 | 
            +
            end
         | 
| 143 | 
            +
            ```
         | 
| 144 | 
            +
            </details>
         | 
| 145 | 
            +
             | 
| 120 146 |  | 
| 121 147 | 
             
            ## Development
         | 
| 122 148 |  | 
| @@ -128,6 +154,10 @@ After checking out the repo, run `bin/setup` to install dependencies. You can al | |
| 128 154 | 
             
            > Full documentation on [Elasticsearch Query DSL and Aggregation options](https://github.com/elastic/elasticsearch-rails/tree/main/elasticsearch-persistence)
         | 
| 129 155 |  | 
| 130 156 | 
             
            ## Testing
         | 
| 157 | 
            +
            <details>
         | 
| 158 | 
            +
            <summary>Elasticsearch</summary>
         | 
| 159 | 
            +
             | 
| 160 | 
            +
             | 
| 131 161 | 
             
            ```
         | 
| 132 162 | 
             
            docker-compose up elasticsearch
         | 
| 133 163 | 
             
            ```
         | 
| @@ -136,6 +166,21 @@ docker-compose up elasticsearch | |
| 136 166 | 
             
            bundle exec rspec
         | 
| 137 167 | 
             
            ```
         | 
| 138 168 |  | 
| 169 | 
            +
            </details>
         | 
| 170 | 
            +
             | 
| 171 | 
            +
            <details>
         | 
| 172 | 
            +
            <summary>Opensearch</summary>
         | 
| 173 | 
            +
             | 
| 174 | 
            +
             | 
| 175 | 
            +
            ```
         | 
| 176 | 
            +
            docker-compose up opensearch
         | 
| 177 | 
            +
            ```
         | 
| 178 | 
            +
             | 
| 179 | 
            +
            ```
         | 
| 180 | 
            +
            ENV['BACKEND']=opensearch bundle rspec 
         | 
| 181 | 
            +
            ```
         | 
| 182 | 
            +
            </details>
         | 
| 183 | 
            +
             | 
| 139 184 | 
             
            ## Contributing
         | 
| 140 185 |  | 
| 141 186 | 
             
            Bug reports and pull requests are welcome on GitHub at https://github.com/theablefew/stretchy. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/theablefew/stretchy/blob/master/CODE_OF_CONDUCT.md).
         | 
| @@ -14,7 +14,7 @@ module Rails | |
| 14 14 | 
             
                            end
         | 
| 15 15 |  | 
| 16 16 | 
             
                            def search_with_instrumentation!(query_or_definition, options={})
         | 
| 17 | 
            -
                                ActiveSupport::Notifications.instrument "search. | 
| 17 | 
            +
                                ActiveSupport::Notifications.instrument "search.stretchy", 
         | 
| 18 18 | 
             
                                  name: "Search", 
         | 
| 19 19 | 
             
                                  klass: self.base_class.to_s,
         | 
| 20 20 | 
             
                                  search: {index: self.index_name, body: query_or_definition }.merge(options) do
         | 
| @@ -2,27 +2,21 @@ module Stretchy | |
| 2 2 | 
             
              module Instrumentation
         | 
| 3 3 |  | 
| 4 4 | 
             
                class Railtie < ::Rails::Railtie
         | 
| 5 | 
            -
                  include ActionView::Helpers::NumberHelper
         | 
| 6 | 
            -
                  def time_diff(start, finish)
         | 
| 7 | 
            -
                    begin
         | 
| 8 | 
            -
                      ((finish.to_time - start.to_time) * 1000).to_s(:rounded, precision: 5, strip_insignificant_zeros: true)
         | 
| 9 | 
            -
                    rescue
         | 
| 10 | 
            -
                      number_with_precision((finish.to_time - start.to_time) * 1000, precision: 5, strip_insignificant_zeros: true)
         | 
| 11 | 
            -
                    end
         | 
| 12 | 
            -
                  end
         | 
| 13 5 |  | 
| 14 | 
            -
                   | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 6 | 
            +
                  require 'rails/instrumentation/publishers'
         | 
| 7 | 
            +
                  ActiveSupport::Notifications.subscribe 'search.stretchy' do |name, start, finish, id, payload|
         | 
| 8 | 
            +
                    message = [
         | 
| 9 | 
            +
                       Rainbow("  #{payload[:klass]}").bright, 
         | 
| 10 | 
            +
                       "(#{(finish.to_time - start.to_time).round(2)}ms)",
         | 
| 11 | 
            +
                       Stretchy::Utils.to_curl(payload[:klass].constantize, payload[:search])
         | 
| 12 | 
            +
                    ].join(" ")
         | 
| 13 | 
            +
                    ::Rails.logger.debug(Rainbow(message).color(:yellow))
         | 
| 14 | 
            +
                 end
         | 
| 17 15 |  | 
| 18 | 
            -
                   | 
| 19 | 
            -
             | 
| 20 | 
            -
                   | 
| 21 | 
            -
             | 
| 22 | 
            -
                  initializer 'stretchy.set_defaults' do
         | 
| 23 | 
            -
                    config.elasticsearch_cache_store = :redis_store
         | 
| 24 | 
            -
                    config.elasticsearch_expire_cache_in = 15.minutes
         | 
| 25 | 
            -
                  end
         | 
| 16 | 
            +
                  # initializer 'stretchy.set_defaults' do
         | 
| 17 | 
            +
                  #   config.elasticsearch_cache_store = :redis_store
         | 
| 18 | 
            +
                  #   config.elasticsearch_expire_cache_in = 15.minutes
         | 
| 19 | 
            +
                  # end
         | 
| 26 20 |  | 
| 27 21 | 
             
                end
         | 
| 28 22 | 
             
              end
         | 
| @@ -33,7 +33,7 @@ module Stretchy | |
| 33 33 | 
             
                  end
         | 
| 34 34 |  | 
| 35 35 | 
             
                  def gateway(&block)
         | 
| 36 | 
            -
                      @gateway ||= Stretchy::Repository.create(index_name: index_name, klass: base_class)
         | 
| 36 | 
            +
                      @gateway ||= Stretchy::Repository.create(client: Stretchy.configuration.client, index_name: index_name, klass: base_class)
         | 
| 37 37 | 
             
                      block.arity < 1 ? @gateway.instance_eval(&block) : block.call(@gateway) if block_given?
         | 
| 38 38 | 
             
                      @gateway
         | 
| 39 39 | 
             
                  end
         | 
| @@ -0,0 +1,86 @@ | |
| 1 | 
            +
            module Stretchy
         | 
| 2 | 
            +
                module OpenSearchCompatibility
         | 
| 3 | 
            +
                extend ActiveSupport::Concern
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                    # Patches the Elasticsearch::Persistence::Repository::Search module to remove the 
         | 
| 6 | 
            +
                    # document type from the request for compatability with OpenSearch
         | 
| 7 | 
            +
                    def self.opensearch_patch!
         | 
| 8 | 
            +
                        patch = Module.new do
         | 
| 9 | 
            +
                            def search(query_or_definition, options={})
         | 
| 10 | 
            +
                                request = { index: index_name }
         | 
| 11 | 
            +
                        
         | 
| 12 | 
            +
                                if query_or_definition.respond_to?(:to_hash)
         | 
| 13 | 
            +
                                    request[:body] = query_or_definition.to_hash
         | 
| 14 | 
            +
                                elsif query_or_definition.is_a?(String)
         | 
| 15 | 
            +
                                    request[:q] = query_or_definition
         | 
| 16 | 
            +
                                else
         | 
| 17 | 
            +
                                    raise ArgumentError, "[!] Pass the search definition as a Hash-like object or pass the query as a String" +
         | 
| 18 | 
            +
                                        " -- #{query_or_definition.class} given."
         | 
| 19 | 
            +
                                end
         | 
| 20 | 
            +
                        
         | 
| 21 | 
            +
                                Elasticsearch::Persistence::Repository::Response::Results.new(self, client.search(request.merge(options)))
         | 
| 22 | 
            +
                            end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                            def count(query_or_definition=nil, options={})
         | 
| 25 | 
            +
                                query_or_definition ||= { query: { match_all: {} } }
         | 
| 26 | 
            +
                                request = { index: index_name}
         | 
| 27 | 
            +
                      
         | 
| 28 | 
            +
                                if query_or_definition.respond_to?(:to_hash)
         | 
| 29 | 
            +
                                  request[:body] = query_or_definition.to_hash
         | 
| 30 | 
            +
                                elsif query_or_definition.is_a?(String)
         | 
| 31 | 
            +
                                  request[:q] = query_or_definition
         | 
| 32 | 
            +
                                else
         | 
| 33 | 
            +
                                  raise ArgumentError, "[!] Pass the search definition as a Hash-like object or pass the query as a String" +
         | 
| 34 | 
            +
                                      " -- #{query_or_definition.class} given."
         | 
| 35 | 
            +
                                end
         | 
| 36 | 
            +
                      
         | 
| 37 | 
            +
                                client.count(request.merge(options))['count']
         | 
| 38 | 
            +
                            end
         | 
| 39 | 
            +
                        end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                        store = Module.new do
         | 
| 42 | 
            +
                            def save(document, options={})
         | 
| 43 | 
            +
                            serialized = serialize(document)
         | 
| 44 | 
            +
                            id = __get_id_from_document(serialized)
         | 
| 45 | 
            +
                            request = { index: index_name,
         | 
| 46 | 
            +
                                        id: id,
         | 
| 47 | 
            +
                                        body: serialized }
         | 
| 48 | 
            +
                            client.index(request.merge(options))
         | 
| 49 | 
            +
                          end
         | 
| 50 | 
            +
                  
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                          def update(document_or_id, options = {})
         | 
| 53 | 
            +
                            if document_or_id.is_a?(String) || document_or_id.is_a?(Integer)
         | 
| 54 | 
            +
                              id = document_or_id
         | 
| 55 | 
            +
                              body = options
         | 
| 56 | 
            +
                            else
         | 
| 57 | 
            +
                              document = serialize(document_or_id)
         | 
| 58 | 
            +
                              id = __extract_id_from_document(document)
         | 
| 59 | 
            +
                              if options[:script]
         | 
| 60 | 
            +
                                body = options
         | 
| 61 | 
            +
                              else
         | 
| 62 | 
            +
                                body = { doc: document }.merge(options)
         | 
| 63 | 
            +
                              end
         | 
| 64 | 
            +
                            end
         | 
| 65 | 
            +
                            client.update(index: index_name, id: id, body: body)
         | 
| 66 | 
            +
                          end
         | 
| 67 | 
            +
                  
         | 
| 68 | 
            +
                          def delete(document_or_id, options = {})
         | 
| 69 | 
            +
                            if document_or_id.is_a?(String) || document_or_id.is_a?(Integer)
         | 
| 70 | 
            +
                              id = document_or_id
         | 
| 71 | 
            +
                            else
         | 
| 72 | 
            +
                              serialized = serialize(document_or_id)
         | 
| 73 | 
            +
                              id = __get_id_from_document(serialized)
         | 
| 74 | 
            +
                            end
         | 
| 75 | 
            +
                            client.delete({ index: index_name, id: id }.merge(options))
         | 
| 76 | 
            +
                          end
         | 
| 77 | 
            +
                        end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
             | 
| 80 | 
            +
                        ::Elasticsearch::Persistence::Repository.send(:include, patch)
         | 
| 81 | 
            +
                        ::Elasticsearch::Persistence::Repository.send(:include, store)
         | 
| 82 | 
            +
                    end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
             | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
            end
         | 
| @@ -6,20 +6,20 @@ module Stretchy | |
| 6 6 |  | 
| 7 7 | 
             
                        VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope]
         | 
| 8 8 |  | 
| 9 | 
            -
                        def initialize
         | 
| 10 | 
            -
                             | 
| 11 | 
            -
                        end
         | 
| 9 | 
            +
                        # def initialize
         | 
| 10 | 
            +
                            self.registry = Hash.new { |hash, key| hash[key] = {} }
         | 
| 11 | 
            +
                        # end
         | 
| 12 12 |  | 
| 13 13 | 
             
                        # Obtains the value for a given +scope_name+ and +variable_name+.
         | 
| 14 | 
            -
                        def value_for(scope_type, variable_name)
         | 
| 14 | 
            +
                        def self.value_for(scope_type, variable_name)
         | 
| 15 15 | 
             
                            raise_invalid_scope_type!(scope_type)
         | 
| 16 | 
            -
                             | 
| 16 | 
            +
                            self.registry[scope_type][variable_name]
         | 
| 17 17 | 
             
                        end
         | 
| 18 18 |  | 
| 19 19 | 
             
                        # Sets the +value+ for a given +scope_type+ and +variable_name+.
         | 
| 20 | 
            -
                        def set_value_for(scope_type, variable_name, value)
         | 
| 20 | 
            +
                        def self.set_value_for(scope_type, variable_name, value)
         | 
| 21 21 | 
             
                            raise_invalid_scope_type!(scope_type)
         | 
| 22 | 
            -
                             | 
| 22 | 
            +
                            self.registry[scope_type][variable_name] = value
         | 
| 23 23 | 
             
                        end
         | 
| 24 24 |  | 
| 25 25 | 
             
                        private
         | 
    
        data/lib/stretchy/scoping.rb
    CHANGED
    
    | @@ -13,13 +13,13 @@ module Stretchy | |
| 13 13 | 
             
                  end
         | 
| 14 14 |  | 
| 15 15 | 
             
                  def current_scope
         | 
| 16 | 
            -
                       | 
| 17 | 
            -
                      ScopeRegistry. | 
| 16 | 
            +
                      ScopeRegistry.new.registry[:current_scope][base_class.to_s]
         | 
| 17 | 
            +
                      # ScopeRegistry.value_for(:current_scope, base_class.to_s)
         | 
| 18 18 | 
             
                  end
         | 
| 19 19 |  | 
| 20 20 | 
             
                  def current_scope=(scope) #:nodoc:
         | 
| 21 | 
            -
                     | 
| 22 | 
            -
                    ScopeRegistry. | 
| 21 | 
            +
                    ScopeRegistry.new.registry[:current_scope][base_class.to_s] = scope
         | 
| 22 | 
            +
                    # ScopeRegistry.set_value_for(:current_scope, base_class.to_s, scope)
         | 
| 23 23 | 
             
                  end
         | 
| 24 24 | 
             
                end
         | 
| 25 25 |  | 
    
        data/lib/stretchy/version.rb
    CHANGED
    
    
    
        data/lib/stretchy.rb
    CHANGED
    
    | @@ -3,10 +3,8 @@ require 'zeitwerk' | |
| 3 3 | 
             
            require 'amazing_print'
         | 
| 4 4 | 
             
            require 'rainbow'
         | 
| 5 5 | 
             
            require 'jbuilder'
         | 
| 6 | 
            -
            # require 'elasticsearch/rails'
         | 
| 7 6 | 
             
            require 'elasticsearch/model'
         | 
| 8 7 | 
             
            require 'elasticsearch/persistence'
         | 
| 9 | 
            -
            # require 'active_support/concern' 
         | 
| 10 8 | 
             
            require 'active_model'
         | 
| 11 9 | 
             
            require 'active_support/all'
         | 
| 12 10 | 
             
            require 'active_model/type/array'
         | 
| @@ -16,21 +14,57 @@ ActiveModel::Type.register(:array, ActiveModel::Type::Array) | |
| 16 14 | 
             
            ActiveModel::Type.register(:hash, ActiveModel::Type::Hash)
         | 
| 17 15 |  | 
| 18 16 | 
             
            require_relative "stretchy/version"
         | 
| 19 | 
            -
            require_relative " | 
| 17 | 
            +
            require_relative "rails/instrumentation/railtie" if defined?(Rails)
         | 
| 20 18 |  | 
| 21 19 | 
             
            module Stretchy
         | 
| 22 20 | 
             
              module Errors
         | 
| 23 21 | 
             
                class QueryOptionMissing < StandardError; end
         | 
| 24 22 | 
             
              end
         | 
| 25 23 |  | 
| 24 | 
            +
              class Configuration
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                attr_accessor :client
         | 
| 27 | 
            +
                attr_accessor :opensearch
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def initialize
         | 
| 30 | 
            +
                    @client = Elasticsearch::Client.new url: 'http://localhost:9200'
         | 
| 31 | 
            +
                    @opensearch = false
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def client=(client)
         | 
| 35 | 
            +
                    @client = client
         | 
| 36 | 
            +
                    self.opensearch = true if @client.class.name =~ /OpenSearch/
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def opensearch=(bool)
         | 
| 40 | 
            +
                    @opensearch = bool
         | 
| 41 | 
            +
                    OpenSearchCompatibility.opensearch_patch! if bool
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def opensearch?
         | 
| 45 | 
            +
                    @opensearch
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 26 50 | 
             
              class << self
         | 
| 27 51 | 
             
                def logger
         | 
| 28 52 | 
             
                  @logger ||= Logger.new(STDOUT)
         | 
| 29 53 | 
             
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def configuration
         | 
| 56 | 
            +
                    @configuration ||= Configuration.new
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                def configure
         | 
| 60 | 
            +
                  yield configuration
         | 
| 61 | 
            +
                end
         | 
| 30 62 | 
             
              end
         | 
| 31 63 |  | 
| 32 64 | 
             
            end
         | 
| 33 65 |  | 
| 66 | 
            +
             | 
| 67 | 
            +
             | 
| 34 68 | 
             
            loader = Zeitwerk::Loader.new
         | 
| 35 69 | 
             
            loader.tag = File.basename(__FILE__, ".rb")
         | 
| 36 70 | 
             
            loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            require_relative "../../lib/stretchy" 
         | 
    
        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.3.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-06 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: zeitwerk
         | 
| @@ -28,42 +28,42 @@ dependencies: | |
| 28 28 | 
             
              name: elasticsearch-rails
         | 
| 29 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 30 | 
             
                requirements:
         | 
| 31 | 
            -
                - - " | 
| 31 | 
            +
                - - "~>"
         | 
| 32 32 | 
             
                  - !ruby/object:Gem::Version
         | 
| 33 33 | 
             
                    version: '7.1'
         | 
| 34 34 | 
             
              type: :runtime
         | 
| 35 35 | 
             
              prerelease: false
         | 
| 36 36 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 37 | 
             
                requirements:
         | 
| 38 | 
            -
                - - " | 
| 38 | 
            +
                - - "~>"
         | 
| 39 39 | 
             
                  - !ruby/object:Gem::Version
         | 
| 40 40 | 
             
                    version: '7.1'
         | 
| 41 41 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 42 42 | 
             
              name: elasticsearch-persistence
         | 
| 43 43 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 44 | 
             
                requirements:
         | 
| 45 | 
            -
                - - " | 
| 45 | 
            +
                - - "~>"
         | 
| 46 46 | 
             
                  - !ruby/object:Gem::Version
         | 
| 47 47 | 
             
                    version: '7.1'
         | 
| 48 48 | 
             
              type: :runtime
         | 
| 49 49 | 
             
              prerelease: false
         | 
| 50 50 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 51 | 
             
                requirements:
         | 
| 52 | 
            -
                - - " | 
| 52 | 
            +
                - - "~>"
         | 
| 53 53 | 
             
                  - !ruby/object:Gem::Version
         | 
| 54 54 | 
             
                    version: '7.1'
         | 
| 55 55 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 56 56 | 
             
              name: elasticsearch-model
         | 
| 57 57 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 58 | 
             
                requirements:
         | 
| 59 | 
            -
                - - " | 
| 59 | 
            +
                - - "~>"
         | 
| 60 60 | 
             
                  - !ruby/object:Gem::Version
         | 
| 61 61 | 
             
                    version: '7.1'
         | 
| 62 62 | 
             
              type: :runtime
         | 
| 63 63 | 
             
              prerelease: false
         | 
| 64 64 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 65 | 
             
                requirements:
         | 
| 66 | 
            -
                - - " | 
| 66 | 
            +
                - - "~>"
         | 
| 67 67 | 
             
                  - !ruby/object:Gem::Version
         | 
| 68 68 | 
             
                    version: '7.1'
         | 
| 69 69 | 
             
            - !ruby/object:Gem::Dependency
         | 
| @@ -164,6 +164,20 @@ dependencies: | |
| 164 164 | 
             
                - - "~>"
         | 
| 165 165 | 
             
                  - !ruby/object:Gem::Version
         | 
| 166 166 | 
             
                    version: 0.9.36
         | 
| 167 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 168 | 
            +
              name: opensearch-ruby
         | 
| 169 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 170 | 
            +
                requirements:
         | 
| 171 | 
            +
                - - "~>"
         | 
| 172 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 173 | 
            +
                    version: '3.0'
         | 
| 174 | 
            +
              type: :development
         | 
| 175 | 
            +
              prerelease: false
         | 
| 176 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 177 | 
            +
                requirements:
         | 
| 178 | 
            +
                - - "~>"
         | 
| 179 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 180 | 
            +
                    version: '3.0'
         | 
| 167 181 | 
             
            description: Provides a familiar ActiveRecord-like interface for working with Elasticsearch
         | 
| 168 182 | 
             
            email:
         | 
| 169 183 | 
             
            - spencer.markowski@theablefew.com
         | 
| @@ -197,6 +211,7 @@ files: | |
| 197 211 | 
             
            - lib/stretchy/model/callbacks.rb
         | 
| 198 212 | 
             
            - lib/stretchy/model/serialization.rb
         | 
| 199 213 | 
             
            - lib/stretchy/null_relation.rb
         | 
| 214 | 
            +
            - lib/stretchy/open_search_compatibility.rb
         | 
| 200 215 | 
             
            - lib/stretchy/persistence.rb
         | 
| 201 216 | 
             
            - lib/stretchy/querying.rb
         | 
| 202 217 | 
             
            - lib/stretchy/record.rb
         | 
| @@ -217,6 +232,7 @@ files: | |
| 217 232 | 
             
            - lib/stretchy/utils.rb
         | 
| 218 233 | 
             
            - lib/stretchy/version.rb
         | 
| 219 234 | 
             
            - sig/stretchy.rbs
         | 
| 235 | 
            +
            - stretchy-model/lib/stretchy-model.rb
         | 
| 220 236 | 
             
            - stretchy.logo.png
         | 
| 221 237 | 
             
            homepage: https://github.com/theablefew/stretchy
         | 
| 222 238 | 
             
            licenses:
         | 
| @@ -229,6 +245,7 @@ post_install_message: | |
| 229 245 | 
             
            rdoc_options: []
         | 
| 230 246 | 
             
            require_paths:
         | 
| 231 247 | 
             
            - lib
         | 
| 248 | 
            +
            - stretchy-model/lib
         | 
| 232 249 | 
             
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 233 250 | 
             
              requirements:
         | 
| 234 251 | 
             
              - - ">="
         |