diff --git a/.github/workflows/2.7.yml b/.github/workflows/2.7.yml deleted file mode 100644 index 8bfd9b66f..000000000 --- a/.github/workflows/2.7.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Ruby 2.7 -on: - push: - branches: - - main - pull_request: - branches: - - main - workflow_dispatch: - branches: - - '*' -jobs: - tests: - env: - TEST_ES_SERVER: http://localhost:9200 - RAILS_VERSIONS: '5.0,6.0' - strategy: - fail-fast: false - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Increase system limits - run: | - sudo swapoff -a - sudo sysctl -w vm.swappiness=1 - sudo sysctl -w fs.file-max=262144 - sudo sysctl -w vm.max_map_count=262144 - - uses: elastic/elastic-github-actions/elasticsearch@master - with: - stack-version: 7.x-SNAPSHOT - - uses: ruby/setup-ruby@v1 - with: - ruby-version: 2.7 - - name: Bundle - run: | - sudo apt-get install libsqlite3-dev - gem install bundler - bundle install - bundle exec rake bundle:clean - bundle exec rake bundle:install - - name: Test elasticsearch-rails - run: cd elasticsearch-rails && bundle exec rake test:all - - name: Test elasticsearch-persistence - run: cd elasticsearch-persistence && bundle exec rake test:all - - name: Test elasticsearch-model - run: cd elasticsearch-model && bundle exec rake test:all diff --git a/.github/workflows/jruby.yml b/.github/workflows/jruby.yml index 7a3ec1be7..91dc5ff48 100644 --- a/.github/workflows/jruby.yml +++ b/.github/workflows/jruby.yml @@ -1,4 +1,4 @@ -name: JRuby +name: JRuby tests on: push: branches: @@ -13,12 +13,15 @@ jobs: tests: env: TEST_ES_SERVER: http://localhost:9200 - RAILS_VERSIONS: '5.0,6.0' + RAILS_VERSIONS: ${{ matrix.rails }} strategy: fail-fast: false + matrix: + rails: [ '6.1', '7.0', '7.1' ] + ruby: ['jruby-9.4'] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Increase system limits run: | sudo swapoff -a @@ -27,13 +30,14 @@ jobs: sudo sysctl -w vm.max_map_count=262144 - uses: elastic/elastic-github-actions/elasticsearch@master with: - stack-version: 7.x-SNAPSHOT + stack-version: 8.15.0-SNAPSHOT + security-enabled: false - uses: ruby/setup-ruby@v1 with: - ruby-version: jruby-9.3 + ruby-version: ${{ matrix.ruby }} - name: Bundle run: | - sudo apt-get install libsqlite3-dev + sudo apt-get install libsqlite3-dev libcurl4-openssl-dev gem install bundler bundle install bundle exec rake bundle:clean diff --git a/.github/workflows/2.6.yml b/.github/workflows/tests.yml similarity index 75% rename from .github/workflows/2.6.yml rename to .github/workflows/tests.yml index c003a58e5..e2ae0ca8b 100644 --- a/.github/workflows/2.6.yml +++ b/.github/workflows/tests.yml @@ -1,4 +1,4 @@ -name: Ruby 2.6 +name: Ruby tests on: push: branches: @@ -6,19 +6,19 @@ on: pull_request: branches: - main - workflow_dispatch: - branches: - - '*' jobs: tests: env: - TEST_ES_SERVER: http://localhost:9200 - RAILS_VERSIONS: '5.0,6.0' + ELASTICSEARCH_URL: http://localhost:9200 + RAILS_VERSIONS: ${{ matrix.rails }} strategy: fail-fast: false + matrix: + rails: [ '6.1', '7.0', '7.1' ] + ruby: ['3.1', '3.2', '3.3'] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Increase system limits run: | sudo swapoff -a @@ -27,10 +27,11 @@ jobs: sudo sysctl -w vm.max_map_count=262144 - uses: elastic/elastic-github-actions/elasticsearch@master with: - stack-version: 7.x-SNAPSHOT + stack-version: 8.15.0-SNAPSHOT + security-enabled: false - uses: ruby/setup-ruby@v1 with: - ruby-version: 2.6 + ruby-version: ${{ matrix.ruby }} - name: Bundle run: | sudo apt-get install libsqlite3-dev diff --git a/.gitignore b/.gitignore index 43ddc2e30..e3359ace9 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ coverage/ rdoc/ doc/ Gemfile.lock +.byebug_history \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c3405dea7..ce1eed141 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +## 8.0.0 + +First general availability release for `8.0.0`. Major versions of `8.x` will support Elasticsearch version `8.x` changing the `elasticsearch` dependency's major version: `gem 'elasticsearch', '~> 8'`. +All references to `type` should have been removed. Document types were deprecated and do not exist in `8.x`. + +The dependency from `elasticsearch` on `elasticsearch-transport` was updated to `elastic-transport`. All `8.x` Elasticsearch APIs supported by `elasticsearch` should now be supported on the Rails library. See [Release notes for the Elasticsearch client 8.0](https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/current/release_notes_80.html) and the [8.x release notes](https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/current/release_notes.html#_8_x) for more information. + +### Compatibility + +The gem is currently testing with Ruby 3.1, 3.2 and 3.3 and JRuby 9.4. Testing for Ruby `2.x` versions has been dropped as they're no longer updated or supported. Currently testing with Rails 6.1, 7.0 and 7.1. + +### Changes since 8.0.0.pre + +- Address Rails 7.1 deprecation warning in elasticsearch-rails [PR](https://github.com/elastic/elasticsearch-rails/pull/1067) +- Ensure subclasses are added to the registry [PR](https://github.com/elastic/elasticsearch-rails/pull/1073) + +### Development changes + +- Using `debug` for debugging in `development` and `testing` Gemfile groups. +- Minor general code cleanups and styling changes. +- Updated code for `elasticsearch` 8.x. + ## 7.2.1 * The default git branch `master` has been renamed to `main` diff --git a/Gemfile b/Gemfile index 0edd2dd95..ddb9b7bbd 100644 --- a/Gemfile +++ b/Gemfile @@ -19,11 +19,12 @@ source 'https://rubygems.org/' gem 'ansi' gem 'cane' -gem 'elasticsearch', '~> 7' +gem 'elasticsearch', '~> 8' gem 'pry' gem 'rake', '~> 12' group :development do + gem 'debug' unless defined?(JRUBY_VERSION) gem 'rspec' gem 'yard' end diff --git a/README.md b/README.md index 26ee3860e..0e27afb21 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,7 @@ # Elasticsearch Rails -[![Ruby 2.7](https://github.com/elastic/elasticsearch-rails/workflows/Ruby%202.7/badge.svg)](https://github.com/elastic/elasticsearch-rails/actions) -[![Ruby 2.6](https://github.com/elastic/elasticsearch-rails/workflows/Ruby%202.6/badge.svg)](https://github.com/elastic/elasticsearch-rails/actions) -[![Ruby 2.5](https://github.com/elastic/elasticsearch-rails/workflows/Ruby%202.5/badge.svg)](https://github.com/elastic/elasticsearch-rails/actions) -[![Ruby 2.4](https://github.com/elastic/elasticsearch-rails/workflows/Ruby%202.4/badge.svg)](https://github.com/elastic/elasticsearch-rails/actions) -[![JRuby](https://github.com/elastic/elasticsearch-rails/workflows/JRuby/badge.svg)](https://github.com/elastic/elasticsearch-rails/actions) -[![Code Climate](https://codeclimate.com/github/elastic/elasticsearch-rails/badges/gpa.svg)](https://codeclimate.com/github/elastic/elasticsearch-rails) +[![Ruby tests](https://github.com/elastic/elasticsearch-rails/actions/workflows/tests.yml/badge.svg)](https://github.com/elastic/elasticsearch-rails/actions/workflows/tests.yml) +[![JRuby tests](https://github.com/elastic/elasticsearch-rails/actions/workflows/jruby.yml/badge.svg)](https://github.com/elastic/elasticsearch-rails/actions/workflows/jruby.yml) This repository contains various Ruby and Rails integrations for [Elasticsearch](http://elasticsearch.org): @@ -29,20 +25,13 @@ Install each library from [Rubygems](https://rubygems.org/gems/elasticsearch): gem install elasticsearch-model gem install elasticsearch-rails -To use an unreleased version, add it to your `Gemfile` for [Bundler](http://bundler.io): - -```ruby -gem 'elasticsearch-model', github: 'elastic/elasticsearch-rails', branch: '5.x' -gem 'elasticsearch-rails', github: 'elastic/elasticsearch-rails', branch: '5.x' -``` - ## Compatibility -The libraries are compatible with Ruby 2.4 and higher. +The libraries are compatible with Ruby 3.0 and higher. We follow Ruby’s own maintenance policy and officially support all currently maintained versions per [Ruby Maintenance Branches](https://www.ruby-lang.org/en/downloads/branches/). -The version numbers follow the Elasticsearch major versions. Currently the `main` branch is compatible with version `7.x` of the Elasticsearch stack. **We haven't tested and updated the code for Elasticsearch `8.0` yet**. +The version numbers follow the Elasticsearch major versions. Currently the `main` branch is compatible with version `8.x` of the Elasticsearch stack. | Rubygem | | Elasticsearch | |:-------------:|:-:| :-----------: | @@ -50,7 +39,9 @@ The version numbers follow the Elasticsearch major versions. Currently the `main | 2.x | → | 2.x | | 5.x | → | 5.x | | 6.x | → | 6.x | -| main | → | 7.x | +| 7.x | → | 7.x | +| 8.x | → | 8.x | +| main | → | 8.x | Check out [Elastic product end of life dates](https://www.elastic.co/support/eol) to learn which releases are still actively supported and tested. @@ -118,7 +109,7 @@ repository = Elasticsearch::Persistence::Repository.new repository.save Article.new(title: 'Test') # POST http://localhost:9200/repository/article -# => {"_index"=>"repository", "_type"=>"article", "_id"=>"Ak75E0U9Q96T5Y999_39NA", ...} +# => {"_index"=>"repository", "_id"=>"Ak75E0U9Q96T5Y999_39NA", ...} ``` **Please refer to each library documentation for detailed information and examples.** @@ -173,9 +164,9 @@ This software is licensed under the Apache 2 license, quoted below. the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/Rakefile b/Rakefile index 9b3347f86..55c294486 100644 --- a/Rakefile +++ b/Rakefile @@ -38,14 +38,16 @@ def admin_client if test_suite == 'security' transport_options.merge!(:ssl => { verify: false, - ca_path: CERT_DIR }) + ca_path: defined?(CERT_DIR) ? CERT_DIR : nil + }.compact) password = ENV['ELASTIC_PASSWORD'] user = ENV['ELASTIC_USER'] || 'elastic' - url = "https://#{user}:#{password}@#{host}:#{port}" + url = "https://#{user}:#{password}@#{host || 'localhost'}:#{port || 9200}" else url = "http://#{host || 'localhost'}:#{port || 9200}" end + ENV['ELASTICSEARCH_URL'] ||= url Elasticsearch::Client.new(host: url, transport_options: transport_options) end end @@ -140,7 +142,7 @@ namespace :test do end desc "Run all tests in all subprojects" - task all: :wait_for_green do + task all: :wait_for_green_or_yellow do subprojects.each do |project| puts '-'*80 sh "cd #{project} && " + @@ -151,20 +153,20 @@ namespace :test do end end -desc "Wait for elasticsearch cluster to be in green state" -task :wait_for_green do +desc "Wait for elasticsearch cluster to be in green or yellow state" +task :wait_for_green_or_yellow do require 'elasticsearch' ready = nil 5.times do |i| begin - puts "Attempting to wait for green status: #{i + 1}" - if admin_client.cluster.health(wait_for_status: 'green', timeout: '50s') + puts "Attempting to wait for green or yellow status: #{i + 1}" + if admin_client.cluster.health(wait_for_status: 'yellow', timeout: '50s') ready = true break end - rescue Elasticsearch::Transport::Transport::Errors::RequestTimeout => ex - puts "Couldn't confirm green status.\n#{ex.inspect}." + rescue Elastic::Transport::Transport::Errors::RequestTimeout => ex + puts "Couldn't confirm green or yellow status.\n#{ex.inspect}." rescue Faraday::ConnectionFailed => ex puts "Couldn't connect to Elasticsearch.\n#{ex.inspect}." sleep(30) diff --git a/elasticsearch-model/Gemfile b/elasticsearch-model/Gemfile index 5a31c3095..58f5b6b92 100644 --- a/elasticsearch-model/Gemfile +++ b/elasticsearch-model/Gemfile @@ -21,6 +21,7 @@ source 'https://rubygems.org/' gemspec group :development, :testing do + gem 'debug' unless defined?(JRUBY_VERSION) gem 'pry-nav' gem 'rspec' end diff --git a/elasticsearch-model/README.md b/elasticsearch-model/README.md index 0e120c349..4103ffa8b 100644 --- a/elasticsearch-model/README.md +++ b/elasticsearch-model/README.md @@ -6,18 +6,19 @@ It aims to simplify integration of Ruby classes ("models"), commonly found e.g. ## Compatibility -This library is compatible with Ruby 2.4 and higher. +This library is compatible with Ruby 3 and higher. -The version numbers follow the Elasticsearch major versions. Currently the `main` branch is compatible with version `7.x` of the Elasticsearch stack. **We haven't tested and updated the code for Elasticsearch `8.0` yet**. +The version numbers follow the Elasticsearch major versions. Currently the `main` branch is compatible with version `8.x` of the Elasticsearch stack. -| Rubygem | | Elasticsearch | -|:-------------:|:-:| :-----------: | -| 0.1 | → | 1.x | -| 2.x | → | 2.x | -| 5.x | → | 5.x | -| 6.x | → | 6.x | -| 7.x | → | 7.x | -| main | → | 7.x | +| Rubygem | | Elasticsearch | +|:-------:|:-:|:-------------:| +| 0.1 | → | 1.x | +| 2.x | → | 2.x | +| 5.x | → | 5.x | +| 6.x | → | 6.x | +| 7.x | → | 7.x | +| 8.x | → | 8.x | +| main | → | 8.x | ## Installation @@ -140,7 +141,7 @@ Elasticsearch::Model.client = Elasticsearch::Client.new log: true You might want to do this during your application bootstrap process, e.g. in a Rails initializer. Please refer to the -[`elasticsearch-transport`](https://github.com/elastic/elasticsearch-ruby/tree/main/elasticsearch-transport) +[`elastic-transport`](https://github.com/elastic/elastic-transport-ruby/) library documentation for all the configuration options, and to the [`elasticsearch-api`](http://rubydoc.info/gems/elasticsearch-api) library documentation for information about the Ruby client API. @@ -268,8 +269,8 @@ It is possible to search across multiple models with the module method: ```ruby Elasticsearch::Model.search('fox', [Article, Comment]).results.to_a.map(&:to_hash) # => [ -# {"_index"=>"articles", "_type"=>"article", "_id"=>"1", "_score"=>0.35136628, "_source"=>...}, -# {"_index"=>"comments", "_type"=>"comment", "_id"=>"1", "_score"=>0.35136628, "_source"=>...} +# {"_index"=>"articles", "_id"=>"1", "_score"=>0.35136628, "_source"=>...}, +# {"_index"=>"comments", "_id"=>"1", "_score"=>0.35136628, "_source"=>...} # ] Elasticsearch::Model.search('fox', [Article, Comment]).records.to_a @@ -414,13 +415,11 @@ Article.__elasticsearch__.create_index! force: true Article.__elasticsearch__.refresh_index! ``` -By default, index name and document type will be inferred from your class name, -you can set it explicitly, however: +By default, index name will be inferred from your class name, you can set it explicitly, however: ```ruby class Article index_name "articles-#{Rails.env}" - document_type "post" end ``` @@ -528,11 +527,11 @@ class Indexer case operation.to_s when /index/ record = Article.find(record_id) - Client.index index: 'articles', type: 'article', id: record.id, body: record.__elasticsearch__.as_indexed_json + Client.index index: 'articles', id: record.id, body: record.__elasticsearch__.as_indexed_json when /delete/ begin - Client.delete index: 'articles', type: 'article', id: record_id - rescue Elasticsearch::Transport::Transport::Errors::NotFound + Client.delete index: 'articles', id: record_id + rescue Elastic::Transport::Transport::Errors::NotFound logger.debug "Article not found, ID: #{record_id}" end else raise ArgumentError, "Unknown operation '#{operation}'" @@ -554,7 +553,7 @@ You'll see the job being processed in the console where you started the _Sidekiq Indexer JID-eb7e2daf389a1e5e83697128 DEBUG: ["index", "ID: 7"] Indexer JID-eb7e2daf389a1e5e83697128 INFO: PUT http://localhost:9200/articles/article/1 [status:200, request:0.004s, query:n/a] Indexer JID-eb7e2daf389a1e5e83697128 DEBUG: > {"id":1,"title":"Updated", ...} -Indexer JID-eb7e2daf389a1e5e83697128 DEBUG: < {"ok":true,"_index":"articles","_type":"article","_id":"1","_version":6} +Indexer JID-eb7e2daf389a1e5e83697128 DEBUG: < {"ok":true,"_index":"articles","_id":"1","_version":6} Indexer JID-eb7e2daf389a1e5e83697128 INFO: done: 0.006 sec ``` diff --git a/elasticsearch-model/Rakefile b/elasticsearch-model/Rakefile index 6e03532b0..9efdda0af 100644 --- a/elasticsearch-model/Rakefile +++ b/elasticsearch-model/Rakefile @@ -21,8 +21,7 @@ desc 'Run unit tests' task default: 'test:all' task test: 'test:all' -gemfiles = ['5.0.gemfile', '6.0.gemfile'] -gemfiles << '4.0.gemfile' if RUBY_VERSION < '2.7' +gemfiles = ['6.1.gemfile', '7.0.gemfile'] GEMFILES = gemfiles.freeze namespace :bundle do @@ -47,7 +46,7 @@ end require 'rake/testtask' namespace :test do desc 'Run all tests. Optionally define env variable RAILS_VERSIONS. E.g. RAILS_VERSIONS=3.0,5.0' - task :all, [:rails_versions] do |task, args| + task :all do |task, args| gemfiles = ENV['RAILS_VERSIONS'] ? ENV['RAILS_VERSIONS'].split(',').map { |v| "#{v}.gemfile" } : GEMFILES puts '-' * 80 gemfiles.each do |gemfile| @@ -57,6 +56,8 @@ namespace :test do puts '-' * 80 end end + + task unit: :all end # ----- Documentation tasks --------------------------------------------------- diff --git a/elasticsearch-model/elasticsearch-model.gemspec b/elasticsearch-model/elasticsearch-model.gemspec index 0dc71775c..57f95b6ae 100644 --- a/elasticsearch-model/elasticsearch-model.gemspec +++ b/elasticsearch-model/elasticsearch-model.gemspec @@ -39,10 +39,10 @@ Gem::Specification.new do |s| s.extra_rdoc_files = ['README.md', 'LICENSE.txt'] s.rdoc_options = ['--charset=UTF-8'] - s.required_ruby_version = '>= 2.4' + s.required_ruby_version = '>= 3' s.add_dependency 'activesupport', '> 3' - s.add_dependency 'elasticsearch', '~> 7' + s.add_dependency 'elasticsearch', '~> 8' s.add_dependency 'hashie' s.add_development_dependency 'activemodel', '> 3' @@ -63,6 +63,6 @@ Gem::Specification.new do |s| unless defined?(JRUBY_VERSION) s.add_development_dependency 'oj' s.add_development_dependency 'ruby-prof' - s.add_development_dependency 'sqlite3' + s.add_development_dependency 'sqlite3', '~> 1.4' end end diff --git a/elasticsearch-model/examples/activerecord_associations.rb b/elasticsearch-model/examples/activerecord_associations.rb index 17d521cbf..b8100b33b 100644 --- a/elasticsearch-model/examples/activerecord_associations.rb +++ b/elasticsearch-model/examples/activerecord_associations.rb @@ -81,7 +81,7 @@ # ----- Elasticsearch client setup ---------------------------------------------------------------- Elasticsearch::Model.client = Elasticsearch::Client.new log: true -Elasticsearch::Model.client.transport.transport.logger.formatter = proc { |s, d, p, m| "\e[2m#{m}\n\e[0m" } +Elasticsearch::Model.client.transport.logger.formatter = proc { |s, d, p, m| "\e[2m#{m}\n\e[0m" } # ----- Search integration ------------------------------------------------------------------------ diff --git a/elasticsearch-model/examples/activerecord_custom_analyzer.rb b/elasticsearch-model/examples/activerecord_custom_analyzer.rb index d16ddbd11..886eaab91 100644 --- a/elasticsearch-model/examples/activerecord_custom_analyzer.rb +++ b/elasticsearch-model/examples/activerecord_custom_analyzer.rb @@ -37,8 +37,8 @@ end end -Elasticsearch::Model.client.transport.transport.logger = ActiveSupport::Logger.new(STDOUT) -Elasticsearch::Model.client.transport.transport.logger.formatter = lambda { |s, d, p, m| "#{m.ansi(:faint)}\n" } +Elasticsearch::Model.client.transport.logger = ActiveSupport::Logger.new(STDOUT) +Elasticsearch::Model.client.transport.logger.formatter = lambda { |s, d, p, m| "#{m.ansi(:faint)}\n" } class Article < ActiveRecord::Base include Elasticsearch::Model diff --git a/elasticsearch-model/gemfiles/4.0.gemfile b/elasticsearch-model/gemfiles/4.0.gemfile deleted file mode 100644 index 944568fce..000000000 --- a/elasticsearch-model/gemfiles/4.0.gemfile +++ /dev/null @@ -1,36 +0,0 @@ -# Licensed to Elasticsearch B.V. under one or more contributor -# license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright -# ownership. Elasticsearch B.V. licenses this file to you under -# the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# Usage: -# -# $ BUNDLE_GEMFILE=./gemfiles/4.0.gemfile bundle install -# $ BUNDLE_GEMFILE=./gemfiles/4.0.gemfile bundle exec rake test:integration - -source 'https://rubygems.org/' - -gemspec path: '../' - -gem 'activemodel', '~> 4' -gem 'activerecord', '~> 4' -gem 'mongoid', '~> 5' -gem 'sqlite3', '> 1.3', '< 1.4' unless defined?(JRUBY_VERSION) - -group :development, :testing do - gem 'bigdecimal', '~> 1' - gem 'pry-nav' - gem 'rspec' -end diff --git a/elasticsearch-model/gemfiles/6.0.gemfile b/elasticsearch-model/gemfiles/6.1.gemfile similarity index 89% rename from elasticsearch-model/gemfiles/6.0.gemfile rename to elasticsearch-model/gemfiles/6.1.gemfile index 2461d66f0..79a13d5c4 100644 --- a/elasticsearch-model/gemfiles/6.0.gemfile +++ b/elasticsearch-model/gemfiles/6.1.gemfile @@ -24,12 +24,13 @@ source 'https://rubygems.org/' gemspec path: '../' -gem 'activemodel', '6.0.0' -gem 'activerecord', '6.0.0' -gem 'sqlite3' unless defined?(JRUBY_VERSION) +gem 'activemodel', '6.1' +gem 'activerecord', '6.1' +gem 'sqlite3', '~> 1.4' unless defined?(JRUBY_VERSION) # gem 'mongoid', '~> 6' group :development, :testing do + gem 'debug' gem 'pry-nav' gem 'rspec' end diff --git a/elasticsearch-model/gemfiles/5.0.gemfile b/elasticsearch-model/gemfiles/7.0.gemfile similarity index 77% rename from elasticsearch-model/gemfiles/5.0.gemfile rename to elasticsearch-model/gemfiles/7.0.gemfile index 8b1930961..f1b5e3ba0 100644 --- a/elasticsearch-model/gemfiles/5.0.gemfile +++ b/elasticsearch-model/gemfiles/7.0.gemfile @@ -17,19 +17,20 @@ # Usage: # -# $ BUNDLE_GEMFILE=./gemfiles/5.0.gemfile bundle install -# $ BUNDLE_GEMFILE=./gemfiles/5.0.gemfile bundle exec rake test:integration +# $ BUNDLE_GEMFILE=./gemfiles/7.0.gemfile bundle install +# $ BUNDLE_GEMFILE=./gemfiles/7.0.gemfile bundle exec rake test:integration source 'https://rubygems.org/' gemspec path: '../' -gem 'activemodel', '~> 5' -gem 'activerecord', '~> 5' -gem 'sqlite3' unless defined?(JRUBY_VERSION) -gem 'mongoid', '~> 6' +gem 'activemodel', '~> 7' +gem 'activerecord', '~> 7' +gem 'sqlite3', '~> 1.4' unless defined?(JRUBY_VERSION) +# gem 'mongoid', '~> 6' group :development, :testing do - gem 'rspec' + gem 'debug' gem 'pry-nav' + gem 'rspec' end diff --git a/elasticsearch-model/gemfiles/3.0.gemfile b/elasticsearch-model/gemfiles/7.1.gemfile similarity index 76% rename from elasticsearch-model/gemfiles/3.0.gemfile rename to elasticsearch-model/gemfiles/7.1.gemfile index 1641023d7..6a8e59da9 100644 --- a/elasticsearch-model/gemfiles/3.0.gemfile +++ b/elasticsearch-model/gemfiles/7.1.gemfile @@ -17,19 +17,20 @@ # Usage: # -# $ BUNDLE_GEMFILE=./gemfiles/3.0.gemfile bundle install -# $ BUNDLE_GEMFILE=./gemfiles/3.0.gemfile bundle exec rake test:integration +# $ BUNDLE_GEMFILE=./gemfiles/7.0.gemfile bundle install +# $ BUNDLE_GEMFILE=./gemfiles/7.0.gemfile bundle exec rake test:integration source 'https://rubygems.org/' gemspec path: '../' -gem 'activemodel', '>= 3.0' -gem 'activerecord', '~> 3.2' -gem 'mongoid', '>= 3.0' -gem 'sqlite3', '> 1.3', '< 1.4' unless defined?(JRUBY_VERSION) +gem 'activemodel', '~> 7.1' +gem 'activerecord', '~> 7.1' +gem 'sqlite3', '~> 1.4' unless defined?(JRUBY_VERSION) +# gem 'mongoid', '~> 6' group :development, :testing do - gem 'rspec' + gem 'debug' gem 'pry-nav' -end \ No newline at end of file + gem 'rspec' +end diff --git a/elasticsearch-model/lib/elasticsearch/model.rb b/elasticsearch-model/lib/elasticsearch/model.rb index af2f34cb6..6cc595050 100644 --- a/elasticsearch-model/lib/elasticsearch/model.rb +++ b/elasticsearch-model/lib/elasticsearch/model.rb @@ -62,7 +62,6 @@ end module Elasticsearch - # Elasticsearch integration for Ruby models # ========================================= # @@ -85,7 +84,7 @@ module Elasticsearch # # ... # module Model - METHODS = [:search, :mapping, :mappings, :settings, :index_name, :document_type, :import] + METHODS = [:search, :mapping, :mappings, :settings, :index_name, :import] # Adds the `Elasticsearch::Model` functionality to the including class. # @@ -108,12 +107,16 @@ module Model def self.included(base) base.class_eval do include Elasticsearch::Model::Proxy - # Delegate common methods to the `__elasticsearch__` ClassMethodsProxy, unless they are defined already class << self METHODS.each do |method| delegate method, to: :__elasticsearch__ unless self.public_instance_methods.include?(method) end + + def inherited(subclass) + super + Registry.add(subclass) if subclass.is_a?(Class) + end end end diff --git a/elasticsearch-model/lib/elasticsearch/model/adapter.rb b/elasticsearch-model/lib/elasticsearch/model/adapter.rb index cdb0c7d0e..3283112e9 100644 --- a/elasticsearch-model/lib/elasticsearch/model/adapter.rb +++ b/elasticsearch-model/lib/elasticsearch/model/adapter.rb @@ -17,7 +17,6 @@ module Elasticsearch module Model - # Contains an adapter which provides OxM-specific implementations for common behaviour: # # * {Adapter::Adapter#records_mixin Fetching records from the database} @@ -29,7 +28,6 @@ module Model # @see Elasticsearch::Model::Adapter::Mongoid # module Adapter - # Returns an adapter based on the Ruby class passed # # @example Create an adapter for an ActiveRecord-based model diff --git a/elasticsearch-model/lib/elasticsearch/model/adapters/active_record.rb b/elasticsearch-model/lib/elasticsearch/model/adapters/active_record.rb index 64e0277d8..20dee0505 100644 --- a/elasticsearch-model/lib/elasticsearch/model/adapters/active_record.rb +++ b/elasticsearch-model/lib/elasticsearch/model/adapters/active_record.rb @@ -18,11 +18,9 @@ module Elasticsearch module Model module Adapter - # An adapter for ActiveRecord-based models # module ActiveRecord - Adapter.register self, lambda { |klass| !!defined?(::ActiveRecord::Base) && klass.respond_to?(:ancestors) && klass.ancestors.include?(::ActiveRecord::Base) } @@ -71,7 +69,6 @@ def load end module Callbacks - # Handle index updates (creating, updating or deleting documents) # when the model changes, by hooking into the lifecycle # @@ -87,7 +84,6 @@ def self.included(base) end module Importing - # Fetch batches of records from the database (used by the import method) # # diff --git a/elasticsearch-model/lib/elasticsearch/model/adapters/default.rb b/elasticsearch-model/lib/elasticsearch/model/adapters/default.rb index 9891b5d64..914514136 100644 --- a/elasticsearch-model/lib/elasticsearch/model/adapters/default.rb +++ b/elasticsearch-model/lib/elasticsearch/model/adapters/default.rb @@ -18,15 +18,12 @@ module Elasticsearch module Model module Adapter - # The default adapter for models which haven't one registered # module Default - # Module for implementing methods and logic related to fetching records from the database # module Records - # Return the collection of records fetched from the database # # By default uses `MyModel#find[1, 2, 3]` @@ -60,7 +57,6 @@ def __transform raise NotImplemented, "Method not implemented for default adapter" end end - end end end diff --git a/elasticsearch-model/lib/elasticsearch/model/adapters/multiple.rb b/elasticsearch-model/lib/elasticsearch/model/adapters/multiple.rb index 30d851043..9a8657f1d 100644 --- a/elasticsearch-model/lib/elasticsearch/model/adapters/multiple.rb +++ b/elasticsearch-model/lib/elasticsearch/model/adapters/multiple.rb @@ -18,7 +18,6 @@ module Elasticsearch module Model module Adapter - # An adapter to be used for deserializing results from multiple models, # retrieved through `Elasticsearch::Model.search` # diff --git a/elasticsearch-model/lib/elasticsearch/model/importing.rb b/elasticsearch-model/lib/elasticsearch/model/importing.rb index 927dd16ee..26e05458c 100644 --- a/elasticsearch-model/lib/elasticsearch/model/importing.rb +++ b/elasticsearch-model/lib/elasticsearch/model/importing.rb @@ -17,14 +17,12 @@ module Elasticsearch module Model - # Provides support for easily and efficiently importing large amounts of # records from the including class into the index. # # @see ClassMethods#import # module Importing - # When included in a model, adds the importing methods. # # @example Import all records from the `Article` model @@ -42,13 +40,12 @@ def self.included(base) end module ClassMethods - # Import all model records into the index # # The method will pick up correct strategy based on the `Importing` module # defined in the corresponding adapter. # - # @param options [Hash] Options passed to the underlying `__find_in_batches`method + # @param options [Hash] Options passed to the underlying `__find_in_batches` method # @param block [Proc] Optional block to evaluate for each batch # # @yield [Hash] Gives the Hash with the Elasticsearch response to the block @@ -62,7 +59,6 @@ module ClassMethods # "index" => { # "error" => 'FAILED', # "_index" => "test", - # "_type" => "_doc", # "_id" => '1', # "_version" => 1, # "result" => "foo", @@ -141,7 +137,6 @@ def import(options={}, &block) errors = [] refresh = options.delete(:refresh) || false target_index = options.delete(:index) || index_name - target_type = options.delete(:type) || document_type transform = options.delete(:transform) || __transform pipeline = options.delete(:pipeline) return_value = options.delete(:return) || 'count' @@ -161,14 +156,10 @@ def import(options={}, &block) __find_in_batches(options) do |batch| params = { index: target_index, - type: target_type, body: __batch_to_bulk(batch, transform) } - params[:pipeline] = pipeline if pipeline - response = client.bulk params - yield response if block_given? errors += response['items'].select { |k, v| k.values.first['error'] } @@ -188,8 +179,6 @@ def __batch_to_bulk(batch, transform) batch.map { |model| transform.call(model) } end end - end - end end diff --git a/elasticsearch-model/lib/elasticsearch/model/indexing.rb b/elasticsearch-model/lib/elasticsearch/model/indexing.rb index 3ebd8cfb4..0e9c68b30 100644 --- a/elasticsearch-model/lib/elasticsearch/model/indexing.rb +++ b/elasticsearch-model/lib/elasticsearch/model/indexing.rb @@ -17,7 +17,6 @@ module Elasticsearch module Model - # Provides the necessary support to set up index options (mappings, settings) # as well as instance methods to create, update or delete documents in the index. # @@ -29,7 +28,6 @@ module Model # @see InstanceMethods#delete_document # module Indexing - # Wraps the [index settings](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) # class Settings @@ -51,13 +49,11 @@ def as_json(options={}) # Wraps the [index mappings](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html) # class Mappings - attr_accessor :options, :type + attr_accessor :options - # @private TYPES_WITH_EMBEDDED_PROPERTIES = %w(object nested) - def initialize(type = nil, options={}) - @type = type + def initialize(options={}) @options = options @mapping = {} end @@ -87,11 +83,7 @@ def indexes(name, options={}, &block) end def to_hash - if @type - { @type.to_sym => @options.merge( properties: @mapping ) } - else - @options.merge( properties: @mapping ) - end + @options.merge( properties: @mapping ) end def as_json(options={}) @@ -100,7 +92,6 @@ def as_json(options={}) end module ClassMethods - # Defines mappings for the index # # @example Define mapping for model @@ -152,7 +143,7 @@ module ClassMethods # when it doesn't already define them. Use the `__elasticsearch__` proxy otherwise. # def mapping(options={}, &block) - @mapping ||= Mappings.new(document_type, options) + @mapping ||= Mappings.new(options) @mapping.options.update(options) unless options.empty? @@ -290,7 +281,7 @@ def delete_index!(options={}) self.client.indices.delete index: target_index rescue Exception => e if e.class.to_s =~ /NotFound/ && options[:force] - client.transport.transport.logger.debug("[!!!] Index does not exist (#{e.class})") if client.transport.transport.logger + client.transport.logger.debug("[!!!] Index does not exist (#{e.class})") if client.transport.logger nil else raise e @@ -317,7 +308,7 @@ def refresh_index!(options={}) self.client.indices.refresh index: target_index rescue Exception => e if e.class.to_s =~ /NotFound/ && options[:force] - client.transport.transport.logger.debug("[!!!] Index does not exist (#{e.class})") if client.transport.transport.logger + client.transport.logger.debug("[!!!] Index does not exist (#{e.class})") if client.transport.logger nil else raise e @@ -372,7 +363,6 @@ def index_document(options={}) request = { index: index_name, id: id, body: document } - request.merge!(type: document_type) if document_type client.index(request.merge!(options)) end @@ -393,7 +383,6 @@ def index_document(options={}) def delete_document(options={}) request = { index: index_name, id: self.id } - request.merge!(type: document_type) if document_type client.delete(request.merge!(options)) end @@ -434,7 +423,6 @@ def update_document(options={}) request = { index: index_name, id: self.id, body: { doc: attributes } } - request.merge!(type: document_type) if document_type client.update(request.merge!(options)) end @@ -461,7 +449,6 @@ def update_document_attributes(attributes, options={}) request = { index: index_name, id: self.id, body: { doc: attributes } } - request.merge!(type: document_type) if document_type client.update(request.merge!(options)) end diff --git a/elasticsearch-model/lib/elasticsearch/model/multimodel.rb b/elasticsearch-model/lib/elasticsearch/model/multimodel.rb index 6b5fc2a81..c519ea968 100644 --- a/elasticsearch-model/lib/elasticsearch/model/multimodel.rb +++ b/elasticsearch-model/lib/elasticsearch/model/multimodel.rb @@ -17,7 +17,6 @@ module Elasticsearch module Model - # Keeps a global registry of classes that include `Elasticsearch::Model` # class Registry @@ -80,17 +79,9 @@ def index_name models.map { |m| m.index_name } end - # Get an Array of document types used for retrieving documents when doing a search across multiple models - # - # @return [Array] the list of document types used for retrieving documents - # - def document_type - models.map { |m| m.document_type }.compact.presence - end - # Get the client common for all models # - # @return Elasticsearch::Transport::Client + # @return Elastic::Transport::Client # def client Elasticsearch::Model.client diff --git a/elasticsearch-model/lib/elasticsearch/model/naming.rb b/elasticsearch-model/lib/elasticsearch/model/naming.rb index c4c796ab2..643f3559b 100644 --- a/elasticsearch-model/lib/elasticsearch/model/naming.rb +++ b/elasticsearch-model/lib/elasticsearch/model/naming.rb @@ -17,15 +17,10 @@ module Elasticsearch module Model - - # Provides methods for getting and setting index name and document type for the model + # Provides methods for getting and setting index and name for the model # module Naming - - DEFAULT_DOC_TYPE = '_doc'.freeze - module ClassMethods - # Get or set the name of the index # # @example Set the index name for the `Article` model @@ -64,46 +59,18 @@ def index_name=(name) @index_name = name end - # Get or set the document type - # - # @example Set the document type for the `Article` model - # - # class Article - # document_type "my-article" - # end - # - # @example Directly set the document type for the `Article` model - # - # Article.document_type "my-article" - # - def document_type name=nil - @document_type = name || @document_type || implicit(:document_type) - end - - - # Set the document type - # - # @see document_type - # - def document_type=(name) - @document_type = name - end - private - def implicit(prop) - self.send("default_#{prop}") - end - - def default_index_name - self.model_name.collection.gsub(/\//, '-') - end + def implicit(prop) + self.send("default_#{prop}") + end - def default_document_type; end + def default_index_name + self.model_name.collection.gsub(/\//, '-') + end end module InstanceMethods - # Get or set the index name for the model instance # # @example Set the index name for an instance of the `Article` model @@ -129,25 +96,7 @@ def index_name name=nil, &block def index_name=(name) @index_name = name end - - # @example Set the document type for an instance of the `Article` model - # - # @article.document_type "my-article" - # @article.__elasticsearch__.update_document - # - def document_type name=nil - @document_type = name || @document_type || self.class.document_type - end - - # Set the document type - # - # @see document_type - # - def document_type=(name) - @document_type = name - end end - end end end diff --git a/elasticsearch-model/lib/elasticsearch/model/proxy.rb b/elasticsearch-model/lib/elasticsearch/model/proxy.rb index 69a6059d2..8a93bc359 100644 --- a/elasticsearch-model/lib/elasticsearch/model/proxy.rb +++ b/elasticsearch-model/lib/elasticsearch/model/proxy.rb @@ -17,7 +17,6 @@ module Elasticsearch module Model - # This module provides a proxy interfacing between the including class and # `Elasticsearch::Model`, preventing the pollution of the including class namespace. # @@ -45,7 +44,6 @@ module Model # # => true # module Proxy - # Define the `__elasticsearch__` class and instance methods in the including class # and register a callback for intercepting changes in the model. # @@ -53,9 +51,7 @@ module Proxy # module and the functionality is accessible via the proxy. # def self.included(base) - base.class_eval do - # `ClassMethodsProxy` instance, accessed as `MyModel.__elasticsearch__` def self.__elasticsearch__ &block @__elasticsearch__ ||= ClassMethodsProxy.new(self) diff --git a/elasticsearch-model/lib/elasticsearch/model/response/result.rb b/elasticsearch-model/lib/elasticsearch/model/response/result.rb index 5e102c2b3..d293e6efa 100644 --- a/elasticsearch-model/lib/elasticsearch/model/response/result.rb +++ b/elasticsearch-model/lib/elasticsearch/model/response/result.rb @@ -40,12 +40,6 @@ def id @result['_id'] end - # Return document `_type` as `_type` - # - def type - @result['_type'] - end - # Delegate methods to `@result` or `@result._source` # def method_missing(name, *arguments) diff --git a/elasticsearch-model/lib/elasticsearch/model/searching.rb b/elasticsearch-model/lib/elasticsearch/model/searching.rb index 714f98a22..e913444dd 100644 --- a/elasticsearch-model/lib/elasticsearch/model/searching.rb +++ b/elasticsearch-model/lib/elasticsearch/model/searching.rb @@ -37,7 +37,6 @@ def initialize(klass, query_or_payload, options={}) @options = options __index_name = options[:index] || klass.index_name - __document_type = options[:type] || klass.document_type case # search query: ... @@ -54,9 +53,9 @@ def initialize(klass, query_or_payload, options={}) end if body - @definition = { index: __index_name, type: __document_type, body: body }.update options + @definition = { index: __index_name, body: body }.update options else - @definition = { index: __index_name, type: __document_type, q: q }.update options + @definition = { index: __index_name, q: q }.update options end end diff --git a/elasticsearch-model/lib/elasticsearch/model/version.rb b/elasticsearch-model/lib/elasticsearch/model/version.rb index cdd631896..eb3aebc12 100644 --- a/elasticsearch-model/lib/elasticsearch/model/version.rb +++ b/elasticsearch-model/lib/elasticsearch/model/version.rb @@ -17,6 +17,6 @@ module Elasticsearch module Model - VERSION = "7.2.1" + VERSION = '8.0.0'.freeze end end diff --git a/elasticsearch-model/spec/elasticsearch/model/adapter_spec.rb b/elasticsearch-model/spec/elasticsearch/model/adapter_spec.rb index 33dd62590..a2f2f850a 100644 --- a/elasticsearch-model/spec/elasticsearch/model/adapter_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/adapter_spec.rb @@ -18,7 +18,6 @@ require 'spec_helper' describe Elasticsearch::Model::Adapter do - before(:all) do class ::DummyAdapterClass; end class ::DummyAdapterClassWithAdapter; end @@ -37,14 +36,12 @@ class ::DummyAdapter end describe '#from_class' do - it 'should return an Adapter instance' do expect(Elasticsearch::Model::Adapter.from_class(DummyAdapterClass)).to be_a(Elasticsearch::Model::Adapter::Adapter) end end describe 'register' do - before do expect(Elasticsearch::Model::Adapter::Adapter).to receive(:register).and_call_original Elasticsearch::Model::Adapter.register(:foo, lambda { |c| false }) @@ -55,7 +52,6 @@ class ::DummyAdapter end context 'when a specific adapter class is set' do - before do expect(Elasticsearch::Model::Adapter::Adapter).to receive(:register).and_call_original Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter, @@ -73,7 +69,6 @@ class ::DummyAdapter end describe 'default adapter' do - let(:adapter) do Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClass) end @@ -84,11 +79,9 @@ class ::DummyAdapter end describe '#records_mixin' do - before do Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter, lambda { |c| c == DummyAdapterClassWithAdapter }) - end let(:adapter) do @@ -101,11 +94,9 @@ class ::DummyAdapter end describe '#callbacks_mixin' do - before do Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter, lambda { |c| c == DummyAdapterClassWithAdapter }) - end let(:adapter) do @@ -118,11 +109,9 @@ class ::DummyAdapter end describe '#importing_mixin' do - before do Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter, lambda { |c| c == DummyAdapterClassWithAdapter }) - end let(:adapter) do diff --git a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/associations_spec.rb b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/associations_spec.rb index c3e460ffb..14000b693 100644 --- a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/associations_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/associations_spec.rb @@ -18,7 +18,6 @@ require 'spec_helper' describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do - before(:all) do ActiveRecord::Schema.define(version: 1) do create_table :categories do |t| @@ -76,7 +75,6 @@ end context 'when a document is created' do - before do Post.create!(title: 'Test') Post.create!(title: 'Testing Coding') @@ -97,9 +95,7 @@ end describe 'has_many_and_belongs_to association' do - - context 'when an association is updated' do - + context 'when an association is updated' do before do post.categories = [category_a, category_b] Post.__elasticsearch__.refresh_index! @@ -119,20 +115,20 @@ let(:search_result) do Post.search(query: { - bool: { - must: { - multi_match: { - fields: ['title'], - query: 'first' - } - }, - filter: { - terms: { - categories: ['One'] - } - } - } - } ) + bool: { + must: { + multi_match: { + fields: ['title'], + query: 'first' + } + }, + filter: { + terms: { + categories: ['One'] + } + } + } + } ) end it 'applies the update with' do @@ -144,7 +140,6 @@ end context 'when an association is deleted' do - before do post.categories = [category_a, category_b] post.categories = [category_b] @@ -165,20 +160,20 @@ let(:search_result) do Post.search(query: { - bool: { - must: { - multi_match: { - fields: ['title'], - query: 'first' - } - }, - filter: { - terms: { - categories: ['One'] - } - } - } - } ) + bool: { + must: { + multi_match: { + fields: ['title'], + query: 'first' + } + }, + filter: { + terms: { + categories: ['One'] + } + } + } + } ) end it 'applies the update with a reindex' do @@ -189,9 +184,7 @@ end describe 'has_many through association' do - context 'when the association is updated' do - before do author_a = Author.where(first_name: "John", last_name: "Smith").first_or_create! author_b = Author.where(first_name: "Mary", last_name: "Smith").first_or_create! @@ -210,33 +203,17 @@ Post.__elasticsearch__.refresh_index! end - context 'if active record is at least 4' do - - let(:search_result) do - Post.search('authors.full_name:john') - end - - it 'applies the update', if: active_record_at_least_4? do - expect(search_result.results.size).to eq(2) - expect(search_result.records.size).to eq(2) - end + let(:search_result) do + Post.search('authors.full_name:john') end - context 'if active record is less than 4' do - - let(:search_result) do - Post.search('authors.author.full_name:john') - end - - it 'applies the update', if: !active_record_at_least_4? do - expect(search_result.results.size).to eq(2) - expect(search_result.records.size).to eq(2) - end + it 'applies the update' do + expect(search_result.results.size).to eq(2) + expect(search_result.records.size).to eq(2) end end - context 'when an association is added', if: active_record_at_least_4? do - + context 'when an association is added' do before do author_a = Author.where(first_name: "John", last_name: "Smith").first_or_create! author_b = Author.where(first_name: "Mary", last_name: "Smith").first_or_create! @@ -262,9 +239,7 @@ end describe 'has_many association' do - - context 'when an association is added', if: active_record_at_least_4? do - + context 'when an association is added' do before do # Create posts post_1 = Post.create!(title: "First Post", text: "This is the first post...") @@ -282,18 +257,18 @@ let(:search_result) do Post.search(query: { - nested: { - path: 'comments', - query: { - bool: { - must: [ - { match: { 'comments.author' => 'john' } }, - { match: { 'comments.text' => 'good' } } - ] - } - } - } - }) + nested: { + path: 'comments', + query: { + bool: { + must: [ + { match: { 'comments.author' => 'john' } }, + { match: { 'comments.text' => 'good' } } + ] + } + } + } + }) end it 'adds the association' do @@ -303,9 +278,7 @@ end describe '#touch' do - context 'when a touch callback is defined on the model' do - before do # Create categories category_a = Category.where(title: "One").first_or_create! @@ -329,7 +302,6 @@ end describe '#includes' do - before do post_1 = Post.create(title: 'One') post_2 = Post.create(title: 'Two') diff --git a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/basic_spec.rb b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/basic_spec.rb index a769b38f6..d334685b2 100644 --- a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/basic_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/basic_spec.rb @@ -18,44 +18,7 @@ require 'spec_helper' describe Elasticsearch::Model::Adapter::ActiveRecord do - - context 'when a document_type is not defined for the Model' do - - before do - ActiveRecord::Schema.define(:version => 1) do - create_table :article_no_types do |t| - t.string :title - t.string :body - t.integer :clicks, :default => 0 - t.datetime :created_at, :default => 'NOW()' - end - end - - ArticleNoType.delete_all - ArticleNoType.__elasticsearch__.create_index!(force: true) - - ArticleNoType.create!(title: 'Test', body: '', clicks: 1) - ArticleNoType.create!(title: 'Testing Coding', body: '', clicks: 2) - ArticleNoType.create!(title: 'Coding', body: '', clicks: 3) - - ArticleNoType.__elasticsearch__.refresh_index! - end - - describe 'indexing a document' do - - let(:search_result) do - ArticleNoType.search('title:test') - end - - it 'allows searching for documents' do - expect(search_result.results.size).to be(2) - expect(search_result.records.size).to be(2) - end - end - end - - context 'when a document_type is defined for the Model' do - + context 'for the Model' do before(:all) do ActiveRecord::Schema.define(:version => 1) do create_table :articles do |t| @@ -67,7 +30,7 @@ end Article.delete_all - Article.__elasticsearch__.create_index!(force: true, include_type_name: true) + Article.__elasticsearch__.create_index!(force: true) Article.create!(title: 'Test', body: '', clicks: 1) Article.create!(title: 'Testing Coding', body: '', clicks: 2) @@ -77,7 +40,6 @@ end describe 'indexing a document' do - let(:search_result) do Article.search('title:test') end @@ -89,7 +51,6 @@ end describe '#results' do - let(:search_result) do Article.search('title:test') end @@ -98,12 +59,11 @@ expect(search_result.results.first).to be_a(Elasticsearch::Model::Response::Result) end - it 'prooperly loads the document' do + it 'properly loads the document' do expect(search_result.results.first.title).to eq('Test') end context 'when the result contains other data' do - let(:search_result) do Article.search(query: { match: { title: 'test' } }, highlight: { fields: { title: {} } }) end @@ -120,7 +80,6 @@ end describe '#records' do - let(:search_result) do Article.search('title:test') end @@ -135,7 +94,6 @@ end describe 'Enumerable' do - let(:search_result) do Article.search('title:test') end @@ -150,7 +108,6 @@ end describe '#id' do - let(:search_result) do Article.search('title:test') end @@ -160,19 +117,7 @@ end end - describe '#id' do - - let(:search_result) do - Article.search('title:test') - end - - it 'returns the type' do - expect(search_result.results.first.type).to eq('article') - end - end - describe '#each_with_hit' do - let(:search_result) do Article.search('title:test') end @@ -186,7 +131,6 @@ end describe 'search results order' do - let(:search_result) do Article.search(query: { match: { title: 'code' }}, sort: { clicks: :desc }) end @@ -209,7 +153,6 @@ end describe 'a paged collection' do - let(:search_result) do Article.search(query: { match: { title: { query: 'test' } } }, size: 2, @@ -225,7 +168,6 @@ end describe '#destroy' do - before do Article.create!(title: 'destroy', body: '', clicks: 1) Article.__elasticsearch__.refresh_index! @@ -246,7 +188,6 @@ end describe 'full document updates' do - before do article = Article.create!(title: 'update', body: '', clicks: 1) Article.__elasticsearch__.refresh_index! @@ -267,7 +208,6 @@ end describe 'attribute updates' do - before do article = Article.create!(title: 'update', body: '', clicks: 1) Article.__elasticsearch__.refresh_index! @@ -288,7 +228,6 @@ end describe '#save' do - before do article = Article.create!(title: 'save', body: '', clicks: 1) @@ -315,7 +254,6 @@ end describe 'a DSL search' do - let(:search_result) do Article.search(query: { match: { title: { query: 'test' } } }) end @@ -327,7 +265,6 @@ end describe 'chaining SQL queries on response.records' do - let(:search_result) do Article.search(query: { match: { title: { query: 'test' } } }) end @@ -340,31 +277,23 @@ end describe 'ordering of SQL queries' do - context 'when order is called on the ActiveRecord query' do - let(:search_result) do Article.search query: { match: { title: { query: 'test' } } } end - it 'allows the SQL query to be ordered independent of the Elasticsearch results order', unless: active_record_at_least_4? do - expect(search_result.records.order('title DESC').first.title).to eq('Testing Coding') - expect(search_result.records.order('title DESC')[0].title).to eq('Testing Coding') - end - - it 'allows the SQL query to be ordered independent of the Elasticsearch results order', if: active_record_at_least_4? do + it 'allows the SQL query to be ordered independent of the Elasticsearch results order' do expect(search_result.records.order(title: :desc).first.title).to eq('Testing Coding') expect(search_result.records.order(title: :desc)[0].title).to eq('Testing Coding') end end context 'when more methods are chained on the ActiveRecord query' do - let(:search_result) do Article.search query: {match: {title: {query: 'test'}}} end - it 'allows the SQL query to be ordered independent of the Elasticsearch results order', if: active_record_at_least_4? do + it 'allows the SQL query to be ordered independent of the Elasticsearch results order' do expect(search_result.records.distinct.order(title: :desc).first.title).to eq('Testing Coding') expect(search_result.records.distinct.order(title: :desc)[0].title).to eq('Testing Coding') end @@ -372,11 +301,10 @@ end describe 'access to the response via methods' do - let(:search_result) do Article.search(query: { match: { title: { query: 'test' } } }, aggregations: { - dates: { date_histogram: { field: 'created_at', interval: 'hour' } }, + dates: { date_histogram: { field: 'created_at', calendar_interval: 'hour' } }, clicks: { global: {}, aggregations: { min: { min: { field: 'clicks' } } } } }, suggest: { text: 'tezt', title: { term: { field: 'title', suggest_mode: 'always' } } }) diff --git a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/import_spec.rb b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/import_spec.rb index 1f5fe0847..73be18c59 100644 --- a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/import_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/import_spec.rb @@ -19,12 +19,12 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Importing' do before(:all) do - ActiveRecord::Schema.define(:version => 1) do + ActiveRecord::Schema.define(version: 1) do create_table :import_articles do |t| t.string :title t.integer :views t.string :numeric # For the sake of invalid data sent to Elasticsearch - t.datetime :created_at, :default => 'NOW()' + t.datetime :created_at, default: 'NOW()' end end @@ -52,6 +52,10 @@ it 'imports all documents' do expect(ImportArticle.search('*').results.total).to eq(10) end + + it "does not pollute the model's namespace" do + expect(ImportArticle.methods).not_to include(:__transform) + end end context 'when batch size is specified' do diff --git a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb index 730dad0e0..09f4670a6 100644 --- a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb @@ -27,7 +27,7 @@ end MyNamespace::Book.delete_all - MyNamespace::Book.__elasticsearch__.create_index!(force: true, include_type_name: true) + MyNamespace::Book.__elasticsearch__.create_index!(force: true) MyNamespace::Book.create!(title: 'Test') MyNamespace::Book.__elasticsearch__.refresh_index! end @@ -43,10 +43,6 @@ expect(MyNamespace::Book.index_name).to eq('my_namespace-books') end - it 'has the proper document type' do - expect(MyNamespace::Book.document_type).to eq('book') - end - it 'saves the document into the index' do expect(MyNamespace::Book.search('title:test').results.size).to eq(1) expect(MyNamespace::Book.search('title:test').results.first.title).to eq('Test') diff --git a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb index c4a503ed7..3cbd30b7f 100644 --- a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb @@ -18,7 +18,6 @@ require 'spec_helper' describe 'Elasticsearch::Model::Adapter::ActiveRecord Pagination' do - before(:all) do ActiveRecord::Schema.define(:version => 1) do create_table ArticleForPagination.table_name do |t| @@ -41,48 +40,41 @@ end context 'when no other page is specified' do - let(:records) do ArticleForPagination.search('title:test').page(1).records end describe '#size' do - it 'returns the correct size' do expect(records.size).to eq(25) end end describe '#current_page' do - it 'returns the correct current page' do expect(records.current_page).to eq(1) end end describe '#prev_page' do - it 'returns the correct previous page' do expect(records.prev_page).to be_nil end end describe '#next_page' do - it 'returns the correct next page' do expect(records.next_page).to eq(2) end end describe '#total_pages' do - it 'returns the correct total pages' do expect(records.total_pages).to eq(3) end end describe '#first_page?' do - it 'returns the correct first page' do expect(records.first_page?).to be(true) end diff --git a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb index 5147943ee..a9feb9b58 100644 --- a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb @@ -38,7 +38,7 @@ add_index(:answers, :question_id) unless index_exists?(:answers, :question_id) clear_tables(Question) - ParentChildSearchable.create_index!(force: true, include_type_name: true) + ParentChildSearchable.create_index!(force: true) q_1 = Question.create!(title: 'First Question', author: 'John') q_2 = Question.create!(title: 'Second Question', author: 'Jody') @@ -53,7 +53,6 @@ end describe 'has_child search' do - let(:search_result) do Question.search(query: { has_child: { type: 'answer', query: { match: { author: 'john' } } } }) end @@ -64,7 +63,6 @@ end describe 'hash_parent search' do - let(:search_result) do Answer.search(query: { has_parent: { parent_type: 'question', query: { match: { author: 'john' } } } }) end @@ -75,7 +73,6 @@ end context 'when a parent is deleted' do - before do Question.where(title: 'First Question').each(&:destroy) Question.__elasticsearch__.refresh_index! diff --git a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb index 3f01c348b..3837169a9 100644 --- a/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb @@ -18,7 +18,6 @@ require 'spec_helper' describe 'Elasticsearch::Model::Adapter::ActiveRecord Serialization' do - before(:all) do ActiveRecord::Schema.define(:version => 1) do create_table ArticleWithCustomSerialization.table_name do |t| @@ -32,18 +31,17 @@ end context 'when the model has a custom serialization defined' do - before do ArticleWithCustomSerialization.create!(title: 'Test', status: 'green') ArticleWithCustomSerialization.__elasticsearch__.refresh_index! end context 'when a document is indexed' do - let(:search_result) do - ArticleWithCustomSerialization.__elasticsearch__.client.get(index: 'article_with_custom_serializations', - type: '_doc', - id: '1') + ArticleWithCustomSerialization.__elasticsearch__.client.get( + index: 'article_with_custom_serializations', + id: '1' + ) end it 'applies the serialization when indexing' do @@ -52,9 +50,8 @@ end context 'when a document is updated' do - before do - article.update_attributes(title: 'UPDATED', status: 'yellow') + article.update(title: 'UPDATED', status: 'yellow') ArticleWithCustomSerialization.__elasticsearch__.refresh_index! end @@ -65,9 +62,10 @@ end let(:search_result) do - ArticleWithCustomSerialization.__elasticsearch__.client.get(index: 'article_with_custom_serializations', - type: '_doc', - id: article.id) + ArticleWithCustomSerialization.__elasticsearch__.client.get( + index: 'article_with_custom_serializations', + id: article.id + ) end it 'applies the serialization when updating' do diff --git a/elasticsearch-model/spec/elasticsearch/model/adapters/mongoid_spec.rb b/elasticsearch-model/spec/elasticsearch/model/adapters/mongoid_spec.rb index 81a286c0d..88ffbd2a6 100644 --- a/elasticsearch-model/spec/elasticsearch/model/adapters/mongoid_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/adapters/mongoid_spec.rb @@ -174,7 +174,7 @@ class DummyClassForMongoid; end context 'query criteria specified as a hash' do before do - expect(relation).to receive(:where).with(color: 'red').and_return(relation) + expect(relation).to receive(:where).with({ color: 'red' }).and_return(relation) end let(:query) do diff --git a/elasticsearch-model/spec/elasticsearch/model/adapters/multiple_spec.rb b/elasticsearch-model/spec/elasticsearch/model/adapters/multiple_spec.rb index eb5a983b0..86c001db8 100644 --- a/elasticsearch-model/spec/elasticsearch/model/adapters/multiple_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/adapters/multiple_spec.rb @@ -18,13 +18,11 @@ require 'spec_helper' describe Elasticsearch::Model::Adapter::Multiple do - before(:all) do class DummyOne include Elasticsearch::Model index_name 'dummy' - document_type 'dummy_one' def self.find(ids) ids.map { |id| new(id) } @@ -42,7 +40,6 @@ class DummyTwo include Elasticsearch::Model index_name 'dummy' - document_type 'dummy_two' def self.find(ids) ids.map { |id| new(id) } @@ -60,7 +57,6 @@ class DummyTwo include Elasticsearch::Model index_name 'other_index' - document_type 'dummy_two' def self.find(ids) ids.map { |id| new(id) } @@ -86,27 +82,22 @@ def initialize(id) [ { _index: 'dummy', - _type: 'dummy_two', _id: '2' }, { _index: 'dummy', - _type: 'dummy_one', _id: '2' }, { _index: 'other_index', - _type: 'dummy_two', _id: '1' }, { _index: 'dummy', - _type: 'dummy_two', _id: '1' }, { _index: 'dummy', - _type: 'dummy_one', _id: '3' } ] @@ -121,13 +112,12 @@ def initialize(id) end describe '#records' do - before do multimodel.class.send :include, Elasticsearch::Model::Adapter::Multiple::Records expect(multimodel).to receive(:response).at_least(:once).and_return(response) end - it 'instantiates the correct types of instances' do + xit 'instantiates the correct types of instances' do expect(multimodel.records[0]).to be_a(Namespace::DummyTwo) expect(multimodel.records[1]).to be_a(DummyOne) expect(multimodel.records[2]).to be_a(DummyTwo) diff --git a/elasticsearch-model/spec/elasticsearch/model/importing_spec.rb b/elasticsearch-model/spec/elasticsearch/model/importing_spec.rb index 02cde6d6c..b905fa4eb 100644 --- a/elasticsearch-model/spec/elasticsearch/model/importing_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/importing_spec.rb @@ -18,18 +18,17 @@ require 'spec_helper' describe Elasticsearch::Model::Importing do - before(:all) do class DummyImportingModel end module DummyImportingAdapter module ImportingMixin - def __find_in_batches(options={}, &block) + def __find_in_batches(options = {}, &block) yield if block_given? end def __transform - lambda {|a|} + lambda { |a| } end end @@ -49,7 +48,6 @@ def importing_mixin end context 'when a model includes the Importing module' do - it 'provides importing methods' do expect(DummyImportingModel.respond_to?(:import)).to be(true) expect(DummyImportingModel.respond_to?(:__find_in_batches)).to be(true) @@ -57,10 +55,8 @@ def importing_mixin end describe '#import' do - before do allow(DummyImportingModel).to receive(:index_name).and_return('foo') - allow(DummyImportingModel).to receive(:document_type).and_return('foo') allow(DummyImportingModel).to receive(:index_exists?).and_return(true) allow(DummyImportingModel).to receive(:__batch_to_bulk) allow(client).to receive(:bulk).and_return(response) @@ -75,7 +71,6 @@ def importing_mixin end context 'when no options are provided' do - before do expect(DummyImportingModel).to receive(:client).and_return(client) allow(DummyImportingModel).to receive(:index_exists?).and_return(true) @@ -87,7 +82,6 @@ def importing_mixin end context 'when there is an error' do - before do expect(DummyImportingModel).to receive(:client).and_return(client) allow(DummyImportingModel).to receive(:index_exists?).and_return(true) @@ -102,14 +96,12 @@ def importing_mixin end context 'when the method is called with the option to return the errors' do - it 'returns the errors' do expect(DummyImportingModel.import(return: 'errors')).to eq([{ 'index' => { 'error' => 'FAILED' } }]) end end context 'when the method is called with a block' do - it 'yields the response to the block' do DummyImportingModel.import do |response| expect(response['items'].size).to eq(2) @@ -119,7 +111,6 @@ def importing_mixin end context 'when the index does not exist' do - before do allow(DummyImportingModel).to receive(:index_exists?).and_return(false) end @@ -132,10 +123,9 @@ def importing_mixin end context 'when the method is called with the force option' do - before do expect(DummyImportingModel).to receive(:create_index!).with(force: true, index: 'foo').and_return(true) - expect(DummyImportingModel).to receive(:__find_in_batches).with(foo: 'bar').and_return(true) + expect(DummyImportingModel).to receive(:__find_in_batches).with({ foo: 'bar' }).and_return(true) end it 'deletes and creates the index' do @@ -144,10 +134,9 @@ def importing_mixin end context 'when the method is called with the refresh option' do - before do expect(DummyImportingModel).to receive(:refresh_index!).with(index: 'foo').and_return(true) - expect(DummyImportingModel).to receive(:__find_in_batches).with(foo: 'bar').and_return(true) + expect(DummyImportingModel).to receive(:__find_in_batches).with({ foo: 'bar' }).and_return(true) end it 'refreshes the index' do @@ -156,10 +145,9 @@ def importing_mixin end context 'when a different index name is provided' do - before do expect(DummyImportingModel).to receive(:client).and_return(client) - expect(client).to receive(:bulk).with(body: nil, index: 'my-new-index', type: 'foo').and_return(response) + expect(client).to receive(:bulk).with({ body: nil, index: 'my-new-index' }).and_return(response) end it 'uses the alternate index name' do @@ -167,20 +155,7 @@ def importing_mixin end end - context 'when a different document type is provided' do - - before do - expect(DummyImportingModel).to receive(:client).and_return(client) - expect(client).to receive(:bulk).with(body: nil, index: 'foo', type: 'my-new-type').and_return(response) - end - - it 'uses the alternate index name' do - expect(DummyImportingModel.import(type: 'my-new-type')).to eq(0) - end - end - context 'the transform method' do - before do expect(DummyImportingModel).to receive(:client).and_return(client) expect(DummyImportingModel).to receive(:__transform).and_return(transform) @@ -197,9 +172,7 @@ def importing_mixin end context 'when a transform is provided as an option' do - context 'when the transform option is not a lambda' do - let(:transform) do 'not_callable' end @@ -212,7 +185,6 @@ def importing_mixin end context 'when the transform option is a lambda' do - before do expect(DummyImportingModel).to receive(:client).and_return(client) expect(DummyImportingModel).to receive(:__batch_to_bulk).with(anything, transform) @@ -229,10 +201,9 @@ def importing_mixin end context 'when a pipeline is provided as an options' do - before do expect(DummyImportingModel).to receive(:client).and_return(client) - expect(client).to receive(:bulk).with(body: nil, index: 'foo', type: 'foo', pipeline: 'my-pipeline').and_return(response) + expect(client).to receive(:bulk).with({ body: nil, index: 'foo', pipeline: 'my-pipeline' }).and_return(response) end it 'uses the pipeline option' do diff --git a/elasticsearch-model/spec/elasticsearch/model/indexing_spec.rb b/elasticsearch-model/spec/elasticsearch/model/indexing_spec.rb index eb9651a73..b4c0d299d 100644 --- a/elasticsearch-model/spec/elasticsearch/model/indexing_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/indexing_spec.rb @@ -18,7 +18,6 @@ require 'spec_helper' describe Elasticsearch::Model::Indexing do - before(:all) do class ::DummyIndexingModel extend ActiveModel::Naming @@ -38,7 +37,6 @@ class NotFound < Exception; end end describe 'the Settings class' do - it 'should be convertible to a hash' do expect(Elasticsearch::Model::Indexing::Settings.new(foo: 'bar').to_hash).to eq(foo: 'bar') end @@ -49,13 +47,11 @@ class NotFound < Exception; end end describe '#settings' do - it 'returns an instance of the Settings class' do expect(DummyIndexingModel.settings).to be_a(Elasticsearch::Model::Indexing::Settings) end context 'when the settings are updated' do - before do DummyIndexingModel.settings(foo: 'boo') DummyIndexingModel.settings(bar: 'bam') @@ -67,7 +63,6 @@ class NotFound < Exception; end end context 'when the settings are updated with a yml file' do - before do DummyIndexingModel.settings File.open('spec/support/model.yml') DummyIndexingModel.settings bar: 'bam' @@ -79,7 +74,6 @@ class NotFound < Exception; end end context 'when the settings are updated with a json file' do - before do DummyIndexingModel.settings File.open('spec/support/model.json') DummyIndexingModel.settings bar: 'bam' @@ -92,68 +86,23 @@ class NotFound < Exception; end end describe '#mappings' do - let(:expected_mapping_hash) do - { :mytype => { foo: 'bar', :properties => {} } } + { foo: 'bar', :properties => {} } end it 'returns an instance of the Mappings class' do expect(DummyIndexingModel.mappings).to be_a(Elasticsearch::Model::Indexing::Mappings) end - it 'does not raise an exception when there is no type passed to the #initialize method' do - expect(Elasticsearch::Model::Indexing::Mappings.new) - end - it 'should be convertible to a hash' do - expect(Elasticsearch::Model::Indexing::Mappings.new(:mytype, { foo: 'bar' }).to_hash).to eq(expected_mapping_hash) + expect(Elasticsearch::Model::Indexing::Mappings.new({ foo: 'bar' }).to_hash).to eq(expected_mapping_hash) end it 'should be convertible to json' do - expect(Elasticsearch::Model::Indexing::Mappings.new(:mytype, { foo: 'bar' }).as_json).to eq(expected_mapping_hash) - end - - context 'when a type is specified' do - - let(:mappings) do - Elasticsearch::Model::Indexing::Mappings.new(:mytype) - end - - before do - mappings.indexes :foo, { type: 'boolean', include_in_all: false } - mappings.indexes :bar - end - - it 'creates the correct mapping definition' do - expect(mappings.to_hash[:mytype][:properties][:foo][:type]).to eq('boolean') - end - - it 'uses text as the default field type' do - expect(mappings.to_hash[:mytype][:properties][:bar][:type]).to eq('text') - end - - context 'when the \'include_type_name\' option is specified' do - - let(:mappings) do - Elasticsearch::Model::Indexing::Mappings.new(:mytype, include_type_name: true) - end - - before do - mappings.indexes :foo, { type: 'boolean', include_in_all: false } - end - - it 'creates the correct mapping definition' do - expect(mappings.to_hash[:mytype][:properties][:foo][:type]).to eq('boolean') - end - - it 'sets the \'include_type_name\' option' do - expect(mappings.to_hash[:mytype][:include_type_name]).to eq(true) - end - end + expect(Elasticsearch::Model::Indexing::Mappings.new({ foo: 'bar' }).as_json).to eq(expected_mapping_hash) end - context 'when a type is not specified' do - + context 'basic mappings' do let(:mappings) do Elasticsearch::Model::Indexing::Mappings.new end @@ -173,9 +122,8 @@ class NotFound < Exception; end end context 'when specific mappings are defined' do - let(:mappings) do - Elasticsearch::Model::Indexing::Mappings.new(:mytype, include_type_name: true) + Elasticsearch::Model::Indexing::Mappings.new(include_type_name: true) end before do @@ -184,15 +132,14 @@ class NotFound < Exception; end end it 'creates the correct mapping definition' do - expect(mappings.to_hash[:mytype][:properties][:foo][:type]).to eq('boolean') + expect(mappings.to_hash[:properties][:foo][:type]).to eq('boolean') end it 'uses text as the default type' do - expect(mappings.to_hash[:mytype][:properties][:bar][:type]).to eq('text') + expect(mappings.to_hash[:properties][:bar][:type]).to eq('text') end context 'when mappings are defined for multiple fields' do - before do mappings.indexes :my_field, type: 'text' do indexes :raw, type: 'keyword' @@ -200,14 +147,13 @@ class NotFound < Exception; end end it 'defines the mapping for all the fields' do - expect(mappings.to_hash[:mytype][:properties][:my_field][:type]).to eq('text') - expect(mappings.to_hash[:mytype][:properties][:my_field][:fields][:raw][:type]).to eq('keyword') - expect(mappings.to_hash[:mytype][:properties][:my_field][:fields][:raw][:properties]).to be_nil + expect(mappings.to_hash[:properties][:my_field][:type]).to eq('text') + expect(mappings.to_hash[:properties][:my_field][:fields][:raw][:type]).to eq('keyword') + expect(mappings.to_hash[:properties][:my_field][:fields][:raw][:properties]).to be_nil end end context 'when embedded properties are defined' do - before do mappings.indexes :foo do indexes :bar @@ -227,31 +173,30 @@ class NotFound < Exception; end end it 'defines mappings for the embedded properties' do - expect(mappings.to_hash[:mytype][:properties][:foo][:type]).to eq('object') - expect(mappings.to_hash[:mytype][:properties][:foo][:properties][:bar][:type]).to eq('text') - expect(mappings.to_hash[:mytype][:properties][:foo][:fields]).to be_nil + expect(mappings.to_hash[:properties][:foo][:type]).to eq('object') + expect(mappings.to_hash[:properties][:foo][:properties][:bar][:type]).to eq('text') + expect(mappings.to_hash[:properties][:foo][:fields]).to be_nil - expect(mappings.to_hash[:mytype][:properties][:foo_object][:type]).to eq('object') - expect(mappings.to_hash[:mytype][:properties][:foo_object][:properties][:bar][:type]).to eq('text') - expect(mappings.to_hash[:mytype][:properties][:foo_object][:fields]).to be_nil + expect(mappings.to_hash[:properties][:foo_object][:type]).to eq('object') + expect(mappings.to_hash[:properties][:foo_object][:properties][:bar][:type]).to eq('text') + expect(mappings.to_hash[:properties][:foo_object][:fields]).to be_nil - expect(mappings.to_hash[:mytype][:properties][:foo_nested][:type]).to eq('nested') - expect(mappings.to_hash[:mytype][:properties][:foo_nested][:properties][:bar][:type]).to eq('text') - expect(mappings.to_hash[:mytype][:properties][:foo_nested][:fields]).to be_nil + expect(mappings.to_hash[:properties][:foo_nested][:type]).to eq('nested') + expect(mappings.to_hash[:properties][:foo_nested][:properties][:bar][:type]).to eq('text') + expect(mappings.to_hash[:properties][:foo_nested][:fields]).to be_nil - expect(mappings.to_hash[:mytype][:properties][:foo_nested_as_symbol][:type]).to eq(:nested) - expect(mappings.to_hash[:mytype][:properties][:foo_nested_as_symbol][:properties]).not_to be_nil - expect(mappings.to_hash[:mytype][:properties][:foo_nested_as_symbol][:fields]).to be_nil + expect(mappings.to_hash[:properties][:foo_nested_as_symbol][:type]).to eq(:nested) + expect(mappings.to_hash[:properties][:foo_nested_as_symbol][:properties]).not_to be_nil + expect(mappings.to_hash[:properties][:foo_nested_as_symbol][:fields]).to be_nil end it 'defines the settings' do - expect(mappings.to_hash[:mytype][:include_type_name]).to be(true) + expect(mappings.to_hash[:include_type_name]).to be(true) end end end context 'when the method is called on a class' do - before do DummyIndexingModel.mappings(foo: 'boo') DummyIndexingModel.mappings(bar: 'bam') @@ -266,7 +211,6 @@ class NotFound < Exception; end end context 'when the method is called with a block' do - before do DummyIndexingModel.mapping do indexes :foo, type: 'boolean' @@ -279,16 +223,14 @@ class NotFound < Exception; end end context 'when the class has a document_type' do - before do DummyIndexingModel.instance_variable_set(:@mapping, nil) - DummyIndexingModel.document_type(:mytype) DummyIndexingModel.mappings(foo: 'boo') DummyIndexingModel.mappings(bar: 'bam') end let(:expected_mappings_hash) do - { mytype: { foo: "boo", bar: "bam", properties: {} } } + { foo: "boo", bar: "bam", properties: {} } end it 'sets the mappings' do @@ -299,7 +241,6 @@ class NotFound < Exception; end end describe 'instance methods' do - before(:all) do class ::DummyIndexingModelWithCallbacks extend Elasticsearch::Model::Indexing::ClassMethods @@ -366,9 +307,7 @@ def changes end context 'when the module is included' do - context 'when the model uses the old ActiveModel::Dirty' do - before do DummyIndexingModelWithOldDirty.__send__ :include, Elasticsearch::Model::Indexing::InstanceMethods end @@ -390,7 +329,6 @@ def changes end context 'when the model users the current ActiveModel::Dirty' do - before do DummyIndexingModelWithCallbacks.__send__ :include, Elasticsearch::Model::Indexing::InstanceMethods end @@ -413,12 +351,10 @@ def changes end describe '#index_document' do - before do expect(instance).to receive(:client).and_return(client) expect(instance).to receive(:as_indexed_json).and_return('JSON') expect(instance).to receive(:index_name).and_return('foo') - expect(instance).to receive(:document_type).twice.and_return('bar') expect(instance).to receive(:id).and_return('1') end @@ -431,9 +367,8 @@ def changes end context 'when no options are passed to the method' do - before do - expect(client).to receive(:index).with(index: 'foo', type: 'bar', id: '1', body: 'JSON').and_return(true) + expect(client).to receive(:index).with({ index: 'foo', id: '1', body: 'JSON' }).and_return(true) end it 'provides the method on an instance' do @@ -442,9 +377,8 @@ def changes end context 'when extra options are passed to the method' do - before do - expect(client).to receive(:index).with(index: 'foo', type: 'bar', id: '1', body: 'JSON', parent: 'A').and_return(true) + expect(client).to receive(:index).with({ index: 'foo', id: '1', body: 'JSON', parent: 'A' }).and_return(true) end it 'passes the extra options to the method call on the client' do @@ -454,11 +388,9 @@ def changes end describe '#delete_document' do - before do expect(instance).to receive(:client).and_return(client) expect(instance).to receive(:index_name).and_return('foo') - expect(instance).to receive(:document_type).twice.and_return('bar') expect(instance).to receive(:id).and_return('1') end @@ -471,9 +403,8 @@ def changes end context 'when no options are passed to the method' do - before do - expect(client).to receive(:delete).with(index: 'foo', type: 'bar', id: '1').and_return(true) + expect(client).to receive(:delete).with({ index: 'foo', id: '1' }).and_return(true) end it 'provides the method on an instance' do @@ -482,9 +413,8 @@ def changes end context 'when extra options are passed to the method' do - before do - expect(client).to receive(:delete).with(index: 'foo', type: 'bar', id: '1', parent: 'A').and_return(true) + expect(client).to receive(:delete).with({ index: 'foo', id: '1', parent: 'A' }).and_return(true) end it 'passes the extra options to the method call on the client' do @@ -494,7 +424,6 @@ def changes end describe '#update_document' do - let(:client) do double('client') end @@ -504,7 +433,6 @@ def changes end context 'when no changes are present' do - before do expect(instance).to receive(:index_document).and_return(true) expect(client).to receive(:update).never @@ -517,19 +445,16 @@ def changes end context 'when changes are present' do - before do allow(instance).to receive(:client).and_return(client) allow(instance).to receive(:index_name).and_return('foo') - allow(instance).to receive(:document_type).and_return('bar') allow(instance).to receive(:id).and_return('1') end context 'when the changes are included in the as_indexed_json representation' do - before do instance.instance_variable_set(:@__changed_model_attributes, { foo: 'bar' }) - expect(client).to receive(:update).with(index: 'foo', type: 'bar', id: '1', body: { doc: { foo: 'bar' } }).and_return(true) + expect(client).to receive(:update).with({ index: 'foo', id: '1', body: { doc: { foo: 'bar' } } }).and_return(true) end it 'updates the document' do @@ -538,14 +463,13 @@ def changes end context 'when the changes are not all included in the as_indexed_json representation' do - let(:instance) do DummyIndexingModelWithCallbacksAndCustomAsIndexedJson.new end before do instance.instance_variable_set(:@__changed_model_attributes, {'foo' => 'B', 'bar' => 'D' }) - expect(client).to receive(:update).with(index: 'foo', type: 'bar', id: '1', body: { doc: { foo: 'B' } }).and_return(true) + expect(client).to receive(:update).with({ index: 'foo', id: '1', body: { doc: { foo: 'B' } } }).and_return(true) end it 'updates the document' do @@ -554,7 +478,6 @@ def changes end context 'when none of the changes are included in the as_indexed_json representation' do - let(:instance) do DummyIndexingModelWithCallbacksAndCustomAsIndexedJson.new end @@ -569,7 +492,6 @@ def changes end context 'when there are partial updates' do - let(:instance) do DummyIndexingModelWithCallbacksAndCustomAsIndexedJson.new end @@ -577,7 +499,7 @@ def changes before do instance.instance_variable_set(:@__changed_model_attributes, { 'foo' => { 'bar' => 'BAR'} }) expect(instance).to receive(:as_indexed_json).and_return('foo' => 'BAR') - expect(client).to receive(:update).with(index: 'foo', type: 'bar', id: '1', body: { doc: { 'foo' => 'BAR' } }).and_return(true) + expect(client).to receive(:update).with({ index: 'foo', id: '1', body: { doc: { 'foo' => 'BAR' } } }).and_return(true) end it 'updates the document' do @@ -588,7 +510,6 @@ def changes end describe '#update_document_attributes' do - let(:client) do double('client') end @@ -598,19 +519,16 @@ def changes end context 'when changes are present' do - before do expect(instance).to receive(:client).and_return(client) expect(instance).to receive(:index_name).and_return('foo') - expect(instance).to receive(:document_type).twice.and_return('bar') expect(instance).to receive(:id).and_return('1') instance.instance_variable_set(:@__changed_model_attributes, { author: 'john' }) end context 'when no options are specified' do - before do - expect(client).to receive(:update).with(index: 'foo', type: 'bar', id: '1', body: { doc: { title: 'green' } }).and_return(true) + expect(client).to receive(:update).with({ index: 'foo', id: '1', body: { doc: { title: 'green' } } }).and_return(true) end it 'updates the document' do @@ -619,9 +537,8 @@ def changes end context 'when extra options are provided' do - before do - expect(client).to receive(:update).with(index: 'foo', type: 'bar', id: '1', body: { doc: { title: 'green' } }, refresh: true).and_return(true) + expect(client).to receive(:update).with({ index: 'foo', id: '1', body: { doc: { title: 'green' } }, refresh: true }).and_return(true) end it 'updates the document' do @@ -633,7 +550,6 @@ def changes end describe '#index_exists?' do - before do expect(DummyIndexingModel).to receive(:client).and_return(client) end @@ -649,8 +565,7 @@ def changes end end - context 'when the index does not exists' do - + context 'when the index does not exist' do let(:client) do double('client', indices: double('indices', exists: false)) end @@ -662,7 +577,6 @@ def changes end describe '#delete_index!' do - before(:all) do class ::DummyIndexingModelForRecreate extend ActiveModel::Naming @@ -677,19 +591,7 @@ class ::DummyIndexingModelForRecreate context 'when the index is not found' do let(:logger) { nil } - let(:transport) do - Elasticsearch::Transport::Client.new(logger: logger) - end - - let(:client) do - double('client', indices: indices, transport: transport) - end - - let(:indices) do - double('indices').tap do |ind| - expect(ind).to receive(:delete).and_raise(NotFound) - end - end + let(:client) { Elasticsearch::Client.new(logger: logger, transport_options: { ssl: { verify: false } }) } before do expect(DummyIndexingModelForRecreate).to receive(:client).at_most(3).times.and_return(client) @@ -705,32 +607,26 @@ class ::DummyIndexingModelForRecreate Logger.new(STDOUT).tap { |l| l.level = Logger::DEBUG } end - let(:client) do - double('client', indices: indices, transport: transport) - end - it 'deletes the index without raising an exception' do expect(DummyIndexingModelForRecreate.delete_index!(force: true)).to be_nil end it 'logs the message that the index is not found' do - expect(logger).to receive(:debug) + expect(logger).to receive(:debug).at_least(:once) expect(DummyIndexingModelForRecreate.delete_index!(force: true)).to be_nil end end end context 'when the force option is not provided' do - it 'raises an exception' do expect { DummyIndexingModelForRecreate.delete_index! - }.to raise_exception(NotFound) + }.to raise_exception(Elastic::Transport::Transport::Errors::NotFound) end end context 'when the exception is not NotFound' do - let(:indices) do double('indices').tap do |ind| expect(ind).to receive(:delete).and_raise(Exception) @@ -746,7 +642,6 @@ class ::DummyIndexingModelForRecreate end context 'when an index name is provided in the options' do - before do expect(DummyIndexingModelForRecreate).to receive(:client).and_return(client) expect(indices).to receive(:delete).with(index: 'custom-foo') @@ -767,7 +662,6 @@ class ::DummyIndexingModelForRecreate end describe '#create_index' do - before(:all) do class ::DummyIndexingModelForCreate extend ActiveModel::Naming @@ -797,14 +691,12 @@ class ::DummyIndexingModelForCreate end context 'when the index does not exist' do - before do expect(DummyIndexingModelForCreate).to receive(:client).and_return(client) expect(DummyIndexingModelForCreate).to receive(:index_exists?).and_return(false) end context 'when options are not provided' do - let(:expected_body) do { mappings: { properties: { foo: { analyzer: 'keyword', type: 'text' } } }, @@ -812,7 +704,7 @@ class ::DummyIndexingModelForCreate end before do - expect(indices).to receive(:create).with(index: 'foo', body: expected_body).and_return(true) + expect(indices).to receive(:create).with({ index: 'foo', body: expected_body }).and_return(true) end it 'creates the index' do @@ -821,14 +713,13 @@ class ::DummyIndexingModelForCreate end context 'when options are provided' do - let(:expected_body) do { mappings: { foobar: { properties: { foo: { analyzer: 'bar' } } } }, settings: { index: { number_of_shards: 3 } } } end before do - expect(indices).to receive(:create).with(index: 'foobar', body: expected_body).and_return(true) + expect(indices).to receive(:create).with({ index: 'foobar', body: expected_body }).and_return(true) end it 'creates the index' do @@ -842,7 +733,6 @@ class ::DummyIndexingModelForCreate end context 'when the index exists' do - before do expect(DummyIndexingModelForCreate).to receive(:index_exists?).and_return(true) expect(indices).to receive(:create).never @@ -854,7 +744,6 @@ class ::DummyIndexingModelForCreate end context 'when creating the index raises an exception' do - before do expect(DummyIndexingModelForCreate).to receive(:client).and_return(client) expect(DummyIndexingModelForCreate).to receive(:delete_index!).and_return(true) @@ -870,11 +759,10 @@ class ::DummyIndexingModelForCreate end context 'when an index name is provided in the options' do - before do expect(DummyIndexingModelForCreate).to receive(:client).and_return(client).twice expect(indices).to receive(:exists).and_return(false) - expect(indices).to receive(:create).with(index: 'custom-foo', body: expected_body) + expect(indices).to receive(:create).with({ index: 'custom-foo', body: expected_body }) end let(:expected_body) do @@ -892,7 +780,6 @@ class ::DummyIndexingModelForCreate end describe '#refresh_index!' do - before(:all) do class ::DummyIndexingModelForRefresh extend ActiveModel::Naming @@ -914,15 +801,7 @@ class ::DummyIndexingModelForRefresh end let(:client) do - double('client', indices: indices, transport: transport) - end - - let(:transport) do - Elasticsearch::Transport::Client.new(logger: nil) - end - - let(:indices) do - double('indices') + Elasticsearch::Client.new(logger: nil) end before do @@ -932,7 +811,7 @@ class ::DummyIndexingModelForRefresh context 'when the force option is true' do context 'when the operation raises a NotFound exception' do before do - expect(indices).to receive(:refresh).and_raise(NotFound) + expect(client).to receive_message_chain(:indices, :refresh).and_raise(NotFound) end it 'does not raise an exception' do @@ -945,11 +824,7 @@ class ::DummyIndexingModelForRefresh end let(:client) do - double('client', indices: indices, transport: transport) - end - - let(:transport) do - Elasticsearch::Transport::Client.new(logger: logger) + Elasticsearch::Client.new(logger: logger) end it 'does not raise an exception' do @@ -965,7 +840,7 @@ class ::DummyIndexingModelForRefresh context 'when the operation raises another type of exception' do before do - expect(indices).to receive(:refresh).and_raise(Exception) + expect(client).to receive_message_chain(:indices, :refresh).and_raise(Exception) end it 'does not raise an exception' do @@ -978,7 +853,7 @@ class ::DummyIndexingModelForRefresh context 'when an index name is provided in the options' do before do - expect(indices).to receive(:refresh).with(index: 'custom-foo') + expect(client).to receive_message_chain(:indices, :refresh).with(index: 'custom-foo') end it 'uses the index name' do diff --git a/elasticsearch-model/spec/elasticsearch/model/module_spec.rb b/elasticsearch-model/spec/elasticsearch/model/module_spec.rb index ed7a58297..8808475ee 100644 --- a/elasticsearch-model/spec/elasticsearch/model/module_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/module_spec.rb @@ -65,7 +65,6 @@ def self.search(query, options={}) expect(DummyIncludingModel).to respond_to(:mapping) expect(DummyIncludingModel).to respond_to(:settings) expect(DummyIncludingModel).to respond_to(:index_name) - expect(DummyIncludingModel).to respond_to(:document_type) expect(DummyIncludingModel).to respond_to(:import) end diff --git a/elasticsearch-model/spec/elasticsearch/model/multimodel_spec.rb b/elasticsearch-model/spec/elasticsearch/model/multimodel_spec.rb index 3652dac1e..31d429074 100644 --- a/elasticsearch-model/spec/elasticsearch/model/multimodel_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/multimodel_spec.rb @@ -24,29 +24,23 @@ end let(:model_1) do - double('Foo', index_name: 'foo_index', document_type: 'foo', to_ary: nil) + double('Foo', index_name: 'foo_index', to_ary: nil) end let(:model_2) do - double('Bar', index_name: 'bar_index', document_type: 'bar', to_ary: nil) + double('Bar', index_name: 'bar_index', to_ary: nil) end it 'has an index name' do expect(multimodel.index_name).to eq(['foo_index', 'bar_index']) end - it 'has an document type' do - expect(multimodel.document_type).to eq(['foo', 'bar']) - end - it 'has a client' do expect(multimodel.client).to eq(Elasticsearch::Model.client) end describe 'the model registry' do - before(:all) do - class JustAModel include Elasticsearch::Model end diff --git a/elasticsearch-model/spec/elasticsearch/model/naming_spec.rb b/elasticsearch-model/spec/elasticsearch/model/naming_spec.rb index 57a53b8d7..917bc099c 100644 --- a/elasticsearch-model/spec/elasticsearch/model/naming_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/naming_spec.rb @@ -51,13 +51,7 @@ class DummyNamingModelInNamespace expect(::MyNamespace::DummyNamingModelInNamespace.new.index_name).to eq('my_namespace-dummy_naming_model_in_namespaces') end - it 'returns nil' do - expect(DummyNamingModel.document_type).to be_nil - expect(DummyNamingModel.new.document_type).to be_nil - end - describe '#index_name' do - context 'when the index name is set on the class' do before do @@ -138,66 +132,4 @@ class DummyNamingModelInNamespace end end end - - describe '#document_type' do - - it 'returns nil' do - expect(DummyNamingModel.document_type).to be_nil - end - - context 'when the method is called with an argument' do - - before do - DummyNamingModel.document_type 'foo' - end - - it 'changes the document type' do - expect(DummyNamingModel.document_type).to eq('foo') - end - end - - context 'when the method is called on an instance' do - - let(:instance) do - DummyNamingModel.new - end - - before do - instance.document_type 'foobar_d' - end - - it 'changes the document type' do - expect(instance.document_type).to eq('foobar_d') - end - end - end - - describe '#document_type=' do - - context 'when the method is called on the class' do - - before do - DummyNamingModel.document_type = 'foo_z' - end - - it 'changes the document type' do - expect(DummyNamingModel.document_type).to eq('foo_z') - end - end - - context 'when the method is called on an instance' do - - let(:instance) do - DummyNamingModel.new - end - - before do - instance.document_type = 'foobar_b' - end - - it 'changes the document type' do - expect(instance.document_type).to eq('foobar_b') - end - end - end end diff --git a/elasticsearch-model/spec/elasticsearch/model/proxy_spec.rb b/elasticsearch-model/spec/elasticsearch/model/proxy_spec.rb index f21baad3d..5465c22a9 100644 --- a/elasticsearch-model/spec/elasticsearch/model/proxy_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/proxy_spec.rb @@ -18,7 +18,6 @@ require 'spec_helper' describe Elasticsearch::Model::Proxy do - before(:all) do class ::DummyProxyModel include Elasticsearch::Model::Proxy @@ -123,10 +122,9 @@ def changes_to_save expect(model).to eq(model_target) expect(duplicate).to eq(duplicate_target) end - end - it 'forwards keyword arguments to target methods' do - expect(DummyProxyModel.new.__elasticsearch__.keyword_method(foo: 'bar')).to eq('bar') + it 'forwards keyword arguments to target methods' do + expect(DummyProxyModel.new.__elasticsearch__.keyword_method(foo: 'bar')).to eq('bar') + end end - end diff --git a/elasticsearch-model/spec/elasticsearch/model/response/aggregations_spec.rb b/elasticsearch-model/spec/elasticsearch/model/response/aggregations_spec.rb index a455140ea..4bfd89efe 100644 --- a/elasticsearch-model/spec/elasticsearch/model/response/aggregations_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/response/aggregations_spec.rb @@ -22,7 +22,6 @@ before(:all) do class OriginClass def self.index_name; 'foo'; end - def self.document_type; 'bar'; end end end @@ -34,9 +33,10 @@ def self.document_type; 'bar'; end { 'aggregations' => { 'foo' => {'bar' => 10 }, - 'price' => { 'doc_count' => 123, - 'min' => { 'value' => 1.0}, - 'max' => { 'value' => 99 } + 'price' => { + 'doc_count' => 123, + 'min' => { 'value' => 1.0}, + 'max' => { 'value' => 99 } } } } diff --git a/elasticsearch-model/spec/elasticsearch/model/response/base_spec.rb b/elasticsearch-model/spec/elasticsearch/model/response/base_spec.rb index d3459b93b..dd5ff2d26 100644 --- a/elasticsearch-model/spec/elasticsearch/model/response/base_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/response/base_spec.rb @@ -26,7 +26,6 @@ class DummyBaseClass class OriginClass def self.index_name; 'foo'; end - def self.document_type; 'bar'; end end end diff --git a/elasticsearch-model/spec/elasticsearch/model/response/pagination/kaminari_spec.rb b/elasticsearch-model/spec/elasticsearch/model/response/pagination/kaminari_spec.rb index 15ee6113c..cb01c86cb 100644 --- a/elasticsearch-model/spec/elasticsearch/model/response/pagination/kaminari_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/response/pagination/kaminari_spec.rb @@ -23,7 +23,6 @@ class ModelClass include ::Kaminari::ConfigurationMethods def self.index_name; 'foo'; end - def self.document_type; 'bar'; end end end @@ -58,7 +57,7 @@ def self.document_type; 'bar'; end context 'when page is called once' do let(:search_request) do - { index: index_field, from: 25, size: 25, q: '*', type: type_field} + { index: index_field, from: 25, size: 25, q: '*' } end before do @@ -75,11 +74,11 @@ def self.document_type; 'bar'; end context 'when page is called more than once' do let(:search_request_one) do - { index: index_field, from: 25, size: 25, q: '*', type: type_field} + { index: index_field, from: 25, size: 25, q: '*' } end let(:search_request_two) do - { index: index_field, from: 75, size: 25, q: '*', type: type_field} + { index: index_field, from: 75, size: 25, q: '*' } end before do diff --git a/elasticsearch-model/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb b/elasticsearch-model/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb index 25f1f0d1e..0f7303adf 100644 --- a/elasticsearch-model/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb @@ -22,7 +22,6 @@ before(:all) do class ModelClass def self.index_name; 'foo'; end - def self.document_type; 'bar'; end def self.per_page 33 diff --git a/elasticsearch-model/spec/elasticsearch/model/response/records_spec.rb b/elasticsearch-model/spec/elasticsearch/model/response/records_spec.rb index 2a80dcfc6..a4e5e7072 100644 --- a/elasticsearch-model/spec/elasticsearch/model/response/records_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/response/records_spec.rb @@ -31,7 +31,6 @@ def foo; 'BAR'; end class DummyModel def self.index_name; 'foo'; end - def self.document_type; 'bar'; end def self.find(*args) DummyCollection.new diff --git a/elasticsearch-model/spec/elasticsearch/model/response/response_spec.rb b/elasticsearch-model/spec/elasticsearch/model/response/response_spec.rb index e9a423812..7186b4710 100644 --- a/elasticsearch-model/spec/elasticsearch/model/response/response_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/response/response_spec.rb @@ -22,7 +22,6 @@ before(:all) do class OriginClass def self.index_name; 'foo'; end - def self.document_type; 'bar'; end end end diff --git a/elasticsearch-model/spec/elasticsearch/model/response/result_spec.rb b/elasticsearch-model/spec/elasticsearch/model/response/result_spec.rb index 5aa7c8f4f..cf5abd38f 100644 --- a/elasticsearch-model/spec/elasticsearch/model/response/result_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/response/result_spec.rb @@ -19,7 +19,6 @@ require 'active_support/json/encoding' describe Elasticsearch::Model::Response::Result do - let(:result) do described_class.new(foo: 'bar', bar: { bam: 'baz' }) end @@ -45,23 +44,7 @@ end end - describe '#type' do - - let(:result) do - described_class.new(foo: 'bar', _type: 'baz', _source: { type: 'BAM' }) - end - - it 'returns the _type field' do - expect(result.type).to eq('baz') - end - - it 'provides access to the source type field' do - expect(result._source.type).to eq('BAM') - end - end - describe 'method delegation' do - let(:result) do described_class.new(foo: 'bar', _source: { bar: { bam: 'baz' } }) end diff --git a/elasticsearch-model/spec/elasticsearch/model/response/results_spec.rb b/elasticsearch-model/spec/elasticsearch/model/response/results_spec.rb index f69db2c01..f944e1877 100644 --- a/elasticsearch-model/spec/elasticsearch/model/response/results_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/response/results_spec.rb @@ -22,7 +22,6 @@ before(:all) do class OriginClass def self.index_name; 'foo'; end - def self.document_type; 'bar'; end end end diff --git a/elasticsearch-model/spec/elasticsearch/model/searching_search_request_spec.rb b/elasticsearch-model/spec/elasticsearch/model/searching_search_request_spec.rb index 1f5e72bf2..1ab23365a 100644 --- a/elasticsearch-model/spec/elasticsearch/model/searching_search_request_spec.rb +++ b/elasticsearch-model/spec/elasticsearch/model/searching_search_request_spec.rb @@ -23,7 +23,6 @@ class ::DummySearchingModel extend Elasticsearch::Model::Searching::ClassMethods def self.index_name; 'foo'; end - def self.document_type; 'bar'; end end end @@ -44,7 +43,7 @@ def self.document_type; 'bar'; end context 'when the search definition is a simple query' do before do - expect(client).to receive(:search).with(index: 'foo', type: 'bar', q: 'foo').and_return({}) + expect(client).to receive(:search).with({ index: 'foo', q: 'foo' }).and_return({}) end let(:search) do @@ -59,7 +58,7 @@ def self.document_type; 'bar'; end context 'when the search definition is a hash' do before do - expect(client).to receive(:search).with(index: 'foo', type: 'bar', body: { foo: 'bar' }).and_return({}) + expect(client).to receive(:search).with({ index: 'foo', body: { foo: 'bar' } }).and_return({}) end let(:search) do @@ -74,7 +73,7 @@ def self.document_type; 'bar'; end context 'when the search definition is a json string' do before do - expect(client).to receive(:search).with(index: 'foo', type: 'bar', body: '{"foo":"bar"}').and_return({}) + expect(client).to receive(:search).with({ index: 'foo', body: '{"foo":"bar"}' }).and_return({}) end let(:search) do @@ -99,7 +98,7 @@ def to_hash; {foo: 'bar'}; end end before do - expect(client).to receive(:search).with(index: 'foo', type: 'bar', body: {foo: 'bar'}).and_return({}) + expect(client).to receive(:search).with({ index: 'foo', body: {foo: 'bar'} }).and_return({}) end let(:search) do @@ -114,7 +113,7 @@ def to_hash; {foo: 'bar'}; end context 'when extra options are specified' do before do - expect(client).to receive(:search).with(index: 'foo', type: 'bar', q: 'foo', size: 15).and_return({}) + expect(client).to receive(:search).with({ index: 'foo', q: 'foo', size: 15 }).and_return({}) end let(:search) do diff --git a/elasticsearch-model/spec/spec_helper.rb b/elasticsearch-model/spec/spec_helper.rb index 413b5f03e..7c4f21a4a 100644 --- a/elasticsearch-model/spec/spec_helper.rb +++ b/elasticsearch-model/spec/spec_helper.rb @@ -31,6 +31,10 @@ require 'yaml' require 'active_record' +# Load all of ActiveSupport to be sure of complete compatibility - +# see https://github.com/elastic/elasticsearch-rails/pull/1075 for details +require 'active_support/all' + unless defined?(ELASTICSEARCH_URL) ELASTICSEARCH_URL = ENV['ELASTICSEARCH_URL'] || "localhost:#{(ENV['TEST_CLUSTER_PORT'] || 9200)}" end @@ -45,7 +49,8 @@ tracer.formatter = lambda { |s, d, p, m| "#{m.gsub(/^.*$/) { |n| ' ' + n }.ansi(:faint)}\n" } Elasticsearch::Model.client = Elasticsearch::Client.new( host: ELASTICSEARCH_URL, - tracer: (ENV['QUIET'] ? nil : tracer) + tracer: (ENV['QUIET'] ? nil : tracer), + transport_options: { :ssl => { verify: false } } ) puts "Elasticsearch Version: #{Elasticsearch::Model.client.info['version']}" @@ -65,15 +70,6 @@ end end -# Is the ActiveRecord version at least 4.0? -# -# @return [ true, false ] Whether the ActiveRecord version is at least 4.0. -# -# @since 6.0.1 -def active_record_at_least_4? - defined?(::ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 4 -end - # Delete all documents from the indices of the provided list of models. # # @param [ Array ] models The list of models. diff --git a/elasticsearch-model/spec/support/app/answer.rb b/elasticsearch-model/spec/support/app/answer.rb index 9c58cc991..ec010e3d2 100644 --- a/elasticsearch-model/spec/support/app/answer.rb +++ b/elasticsearch-model/spec/support/app/answer.rb @@ -23,7 +23,6 @@ class Answer < ActiveRecord::Base JOIN_TYPE = 'answer'.freeze index_name 'questions_and_answers'.freeze - document_type 'doc'.freeze before_create :randomize_id diff --git a/elasticsearch-model/spec/support/app/article.rb b/elasticsearch-model/spec/support/app/article.rb index 2c122dd77..659d16cec 100644 --- a/elasticsearch-model/spec/support/app/article.rb +++ b/elasticsearch-model/spec/support/app/article.rb @@ -19,8 +19,6 @@ class ::Article < ActiveRecord::Base include Elasticsearch::Model include Elasticsearch::Model::Callbacks - document_type 'article' - settings index: {number_of_shards: 1, number_of_replicas: 0} do mapping do indexes :title, type: 'text', analyzer: 'snowball' diff --git a/elasticsearch-model/spec/support/app/article_no_type.rb b/elasticsearch-model/spec/support/app/article_no_type.rb index d3cb6b4e3..9e6b8443f 100644 --- a/elasticsearch-model/spec/support/app/article_no_type.rb +++ b/elasticsearch-model/spec/support/app/article_no_type.rb @@ -21,7 +21,7 @@ class ::ArticleNoType < ActiveRecord::Base settings index: {number_of_shards: 1, number_of_replicas: 0} do mapping do - indexes :title, type: 'text', analyzer: 'snowball' + indexes :title, analyzer: 'snowball' indexes :body, type: 'text' indexes :clicks, type: 'integer' indexes :created_at, type: 'date' diff --git a/elasticsearch-model/spec/support/app/namespaced_book.rb b/elasticsearch-model/spec/support/app/namespaced_book.rb index f6d9c838c..29949772a 100644 --- a/elasticsearch-model/spec/support/app/namespaced_book.rb +++ b/elasticsearch-model/spec/support/app/namespaced_book.rb @@ -20,8 +20,6 @@ class Book < ActiveRecord::Base include Elasticsearch::Model include Elasticsearch::Model::Callbacks - document_type 'book' - mapping { indexes :title } end end diff --git a/elasticsearch-model/spec/support/app/parent_and_child_searchable.rb b/elasticsearch-model/spec/support/app/parent_and_child_searchable.rb index 91693479f..210e44076 100644 --- a/elasticsearch-model/spec/support/app/parent_and_child_searchable.rb +++ b/elasticsearch-model/spec/support/app/parent_and_child_searchable.rb @@ -26,10 +26,12 @@ def create_index!(options={}) settings = Question.settings.to_hash.merge Answer.settings.to_hash mapping_properties = { join_field: { type: JOIN, relations: { Question::JOIN_TYPE => Answer::JOIN_TYPE } } } - - merged_properties = mapping_properties.merge(Question.mappings.to_hash[:doc][:properties]).merge( - Answer.mappings.to_hash[:doc][:properties]) - mappings = { doc: { properties: merged_properties }} + merged_properties = mapping_properties.merge( + Question.mappings.to_hash[:properties] + ).merge( + Answer.mappings.to_hash[:properties] + ) + mappings = { properties: merged_properties } client.indices.create({ index: INDEX_NAME, body: { diff --git a/elasticsearch-model/spec/support/app/question.rb b/elasticsearch-model/spec/support/app/question.rb index 62a7d4550..fce543139 100644 --- a/elasticsearch-model/spec/support/app/question.rb +++ b/elasticsearch-model/spec/support/app/question.rb @@ -24,7 +24,6 @@ class Question < ActiveRecord::Base JOIN_METADATA = { join_field: JOIN_TYPE}.freeze index_name 'questions_and_answers'.freeze - document_type 'doc'.freeze mapping do indexes :title diff --git a/elasticsearch-persistence/Gemfile b/elasticsearch-persistence/Gemfile index 17e92d051..4e228558e 100644 --- a/elasticsearch-persistence/Gemfile +++ b/elasticsearch-persistence/Gemfile @@ -25,6 +25,7 @@ gem 'elasticsearch-model', require: false group :development, :testing do + gem 'debug' unless defined?(JRUBY_VERSION) gem 'pry-nav' gem 'rspec' end diff --git a/elasticsearch-persistence/README.md b/elasticsearch-persistence/README.md index e8cb0aa8a..47747b6ff 100644 --- a/elasticsearch-persistence/README.md +++ b/elasticsearch-persistence/README.md @@ -4,18 +4,19 @@ Persistence layer for Ruby domain objects in Elasticsearch, using the Repository ## Compatibility -This library is compatible with Ruby 2.4 and higher. +This library is compatible with Ruby 3.1 and higher. -The version numbers follow the Elasticsearch major versions. Currently the `main` branch is compatible with version `7.x` of the Elasticsearch stack. **We haven't tested and updated the code for Elasticsearch `8.0` yet**. +The version numbers follow the Elasticsearch major versions. Currently the `main` branch is compatible with version `8.x` of the Elasticsearch stack. -| Rubygem | | Elasticsearch | -|:-------------:|:-:| :-----------: | -| 0.1 | → | 1.x | -| 2.x | → | 2.x | -| 5.x | → | 5.x | -| 6.x | → | 6.x | -| 7.x | → | 7.x | -| main | → | 7.x | +| Rubygem | | Elasticsearch | +|:-------:|:-:|:-------------:| +| 0.1 | → | 1.x | +| 2.x | → | 2.x | +| 5.x | → | 5.x | +| 6.x | → | 6.x | +| 7.x | → | 7.x | +| 8.x | → | 8.x | +| main | → | 8.x | ## Installation @@ -78,7 +79,7 @@ note = Note.new id: 1, text: 'Test' repository.save(note) # PUT http://localhost:9200/repository/_doc/1 [status:201, request:0.210s, query:n/a] # > {"id":1,"text":"Test"} -# < {"_index":"repository","_type":"note","_id":"1","_version":1,"created":true} +# < {"_index":"repository","_id":"1","_version":1,"created":true} ``` ...find it... @@ -86,7 +87,7 @@ repository.save(note) ```ruby n = repository.find(1) # GET http://localhost:9200/repository/_doc/1 [status:200, request:0.003s, query:n/a] -# < {"_index":"repository","_type":"note","_id":"1","_version":2,"found":true, "_source" : {"id":1,"text":"Test"}} +# < {"_index":"repository","_id":"1","_version":2,"found":true, "_source" : {"id":1,"text":"Test"}} => 1, "text"=>"Test"}> ``` @@ -105,14 +106,14 @@ repository.search(query: { match: { text: 'test' } }).first ```ruby repository.delete(note) # DELETE http://localhost:9200/repository/_doc/1 [status:200, request:0.014s, query:n/a] -# < {"found":true,"_index":"repository","_type":"note","_id":"1","_version":3} -=> {"found"=>true, "_index"=>"repository", "_type"=>"note", "_id"=>"1", "_version"=>2} +# < {"found":true,"_index":"repository","_id":"1","_version":3} +=> {"found"=>true, "_index"=>"repository", "_id"=>"1", "_version"=>2} ``` The repository module provides a number of features and facilities to configure and customize the behavior: * Configuring the Elasticsearch [client](https://github.com/elastic/elasticsearch-ruby#usage) being used -* Setting the index name, document type, and object class for deserialization +* Setting the index name, and object class for deserialization * Composing mappings and settings for the index * Creating, deleting or refreshing the index * Finding or searching for documents @@ -145,7 +146,7 @@ class MyRepository end client = Elasticsearch::Client.new(url: ENV['ELASTICSEARCH_URL'], log: true) -repository = MyRepository.new(client: client, index_name: :my_notes, type: :note, klass: Note) +repository = MyRepository.new(client: client, index_name: :my_notes, klass: Note) repository.settings number_of_shards: 1 do mapping do indexes :text, analyzer: 'snowball' @@ -153,8 +154,7 @@ repository.settings number_of_shards: 1 do end ``` -The custom Elasticsearch client will be used now, with a custom index and type names, -as well as the custom serialization and de-serialization logic. +The custom Elasticsearch client will be used now, with a custom index, as well as the custom serialization and de-serialization logic. We can create the index with the desired settings and mappings: @@ -170,7 +170,7 @@ Save the document with extra properties added by the `serialize` method: repository.save(note) # PUT http://localhost:9200/my_notes/note/1 # > {"id":1,"text":"Test","my_special_key":"my_special_stuff"} -{"_index"=>"my_notes", "_type"=>"my_note", "_id"=>"1", "_version"=>4, ... } +{"_index"=>"my_notes", "_id"=>"1", "_version"=>4, ... } ``` And `deserialize` it: @@ -194,7 +194,6 @@ class NoteRepository include Elasticsearch::Persistence::Repository::DSL index_name 'notes' - document_type 'note' klass Note settings number_of_shards: 1 do @@ -237,7 +236,7 @@ You can also override the default configuration with options passed to the initi ```ruby client = Elasticsearch::Client.new(url: 'http://localhost:9250/', log: true) -client.transport.transport.logger.formatter = proc { |s, d, p, m| "\e[2m# #{m}\n\e[0m" } +client.transport.logger.formatter = proc { |s, d, p, m| "\e[2m# #{m}\n\e[0m" } repository = NoteRepository.new(client: client, index_name: 'notes_development') repository.create_index!(force: true) @@ -268,7 +267,7 @@ The repository uses the standard Elasticsearch [client](https://github.com/elast ```ruby client = Elasticsearch::Client.new(url: 'http://search.server.org/') repository = NoteRepository.new(client: client) -repository.client.transport.transport.logger = Logger.new(STDERR) +repository.client.transport.logger = Logger.new(STDERR) repository.client # => Elasticsearch::Client @@ -318,36 +317,8 @@ repository.index_name ``` -The `document_type` method specifies the Elasticsearch document type to use for storage, lookup and search. The default value is -'_doc'. Keep in mind that future versions of Elasticsearch will not allow you to set this yourself and will use the type, -'_doc'. - -```ruby -repository = NoteRepository.new(document_type: 'note') -repository.document_type -# => 'note' - -``` - -or with the DSL mixin: - -```ruby -class NoteRepository - include Elasticsearch::Persistence::Repository - include Elasticsearch::Persistence::Repository::DSL - - document_type 'note' -end - -repository = NoteRepository.new -repository.document_type -# => 'note' - -``` - The `klass` method specifies the Ruby class name to use when initializing objects from -documents retrieved from the repository. If this value is not set, a Hash representation of the document will be -returned instead. +documents retrieved from the repository. If this value is not set, a Hash representation of the document will be returned instead. ```ruby repository = NoteRepository.new(klass: Note) @@ -452,7 +423,7 @@ The `save` method allows you to store a domain object in the repository: ```ruby note = Note.new id: 1, title: 'Quick Brown Fox' repository.save(note) -# => {"_index"=>"notes_development", "_type"=>"_doc", "_id"=>"1", "_version"=>1, "created"=>true} +# => {"_index"=>"notes_development", "_id"=>"1", "_version"=>1, "created"=>true} ``` The `update` method allows you to perform a partial update of a document in the repository. @@ -460,14 +431,14 @@ Use either a partial document: ```ruby repository.update id: 1, title: 'UPDATED', tags: [] -# => {"_index"=>"notes_development", "_type"=>"_doc", "_id"=>"1", "_version"=>2} +# => {"_index"=>"notes_development", "_id"=>"1", "_version"=>2} ``` Or a script (optionally with parameters): ```ruby repository.update 1, script: 'if (!ctx._source.tags.contains(t)) { ctx._source.tags += t }', params: { t: 'foo' } -# => {"_index"=>"notes_development", "_type"=>"_doc", "_id"=>"1", "_version"=>3} +# => {"_index"=>"notes_development", "_id"=>"1", "_version"=>3} ``` diff --git a/elasticsearch-persistence/elasticsearch-persistence.gemspec b/elasticsearch-persistence/elasticsearch-persistence.gemspec index 893103d4b..6dbb7386f 100644 --- a/elasticsearch-persistence/elasticsearch-persistence.gemspec +++ b/elasticsearch-persistence/elasticsearch-persistence.gemspec @@ -39,12 +39,12 @@ Gem::Specification.new do |s| s.extra_rdoc_files = ['README.md', 'LICENSE.txt'] s.rdoc_options = ['--charset=UTF-8'] - s.required_ruby_version = '>= 1.9.3' + s.required_ruby_version = '>= 3' s.add_dependency 'activemodel', '> 4' s.add_dependency 'activesupport', '> 4' - s.add_dependency 'elasticsearch', '~> 7' - s.add_dependency 'elasticsearch-model', '7.2.1' + s.add_dependency 'elasticsearch', '~> 8' + s.add_dependency 'elasticsearch-model', '8' s.add_dependency 'hashie' s.add_development_dependency 'bundler' diff --git a/elasticsearch-persistence/examples/notes/application.rb b/elasticsearch-persistence/examples/notes/application.rb index 0f1724476..9b7bc88ae 100644 --- a/elasticsearch-persistence/examples/notes/application.rb +++ b/elasticsearch-persistence/examples/notes/application.rb @@ -75,7 +75,6 @@ class NoteRepository client Elasticsearch::Client.new url: ENV['ELASTICSEARCH_URL'], log: true index_name :notes - document_type :note mapping do indexes :text, analyzer: 'snowball' diff --git a/elasticsearch-persistence/examples/notes/test.rb b/elasticsearch-persistence/examples/notes/test.rb index 27922933b..b57105341 100644 --- a/elasticsearch-persistence/examples/notes/test.rb +++ b/elasticsearch-persistence/examples/notes/test.rb @@ -90,7 +90,7 @@ def app app.settings.repository.client = Elasticsearch::Client.new \ hosts: [{ host: 'localhost', port: ENV.fetch('http://github.com/TEST_CLUSTER_PORT', 9250)}], log: true - app.settings.repository.client.transport.transport.logger.formatter = proc { |s, d, p, m| "\e[2m#{m}\n\e[0m" } + app.settings.repository.client.transport.logger.formatter = proc { |s, d, p, m| "\e[2m#{m}\n\e[0m" } app.settings.repository.create_index! force: true app.settings.repository.client.cluster.health wait_for_status: 'yellow' end diff --git a/elasticsearch-persistence/lib/elasticsearch/persistence/repository.rb b/elasticsearch-persistence/lib/elasticsearch/persistence/repository.rb index 607de1769..e5fb23c13 100644 --- a/elasticsearch-persistence/lib/elasticsearch/persistence/repository.rb +++ b/elasticsearch-persistence/lib/elasticsearch/persistence/repository.rb @@ -58,7 +58,6 @@ module ClassMethods # @param [ Proc ] block A block to evaluate on the new repository instance. # # @option options [ Symbol, String ] :index_name The name of the index. - # @option options [ Symbol, String ] :document_type The type of documents persisted in this repository. # @option options [ Symbol, String ] :client The client used to handle requests to and from Elasticsearch. # @option options [ Symbol, String ] :klass The class used to instantiate an object when documents are # deserialized. The default is nil, in which case the raw document will be returned as a Hash. @@ -95,7 +94,6 @@ def create(options = {}, &block) # @param [ Hash ] options The options to use. # # @option options [ Symbol, String ] :index_name The name of the index. - # @option options [ Symbol, String ] :document_type The type of documents persisted in this repository. # @option options [ Symbol, String ] :client The client used to handle requests to and from Elasticsearch. # @option options [ Symbol, String ] :klass The class used to instantiate an object when documents are # deserialized. The default is nil, in which case the raw document will be returned as a Hash. @@ -121,19 +119,6 @@ def client Elasticsearch::Client.new end - # Get the document type used by the repository object. - # - # @example - # repository.document_type - # - # @return [ String, Symbol ] The repository's document type. - # - # @since 6.0.0 - def document_type - @document_type ||= @options[:document_type] || - __get_class_value(:document_type) - end - # Get the index name used by the repository. # # @example @@ -180,7 +165,6 @@ def klass def mapping(*args) @memoized_mapping ||= @options[:mapping] || (begin if _mapping = __get_class_value(:mapping) - _mapping.instance_variable_set(:@type, document_type) _mapping end end) || (super && @mapping) @@ -229,7 +213,7 @@ def index_exists?(*args) # # @since 6.0.0 def inspect - "#<#{self.class}:0x#{object_id} index_name=#{index_name} document_type=#{document_type} klass=#{klass}>" + "#<#{self.class}:0x#{object_id} index_name=#{index_name} klass=#{klass}>" end private diff --git a/elasticsearch-persistence/lib/elasticsearch/persistence/repository/dsl.rb b/elasticsearch-persistence/lib/elasticsearch/persistence/repository/dsl.rb index de2848071..cab567d1d 100644 --- a/elasticsearch-persistence/lib/elasticsearch/persistence/repository/dsl.rb +++ b/elasticsearch-persistence/lib/elasticsearch/persistence/repository/dsl.rb @@ -23,7 +23,6 @@ module Repository # # @since 6.0.0 module DSL - def self.included(base) base.send(:extend, Elasticsearch::Model::Indexing::ClassMethods) base.send(:extend, ClassMethods) @@ -34,19 +33,6 @@ def self.included(base) # # @since 6.0.0 module ClassMethods - - # Get or set the class-level document type setting. - # - # @example - # MyRepository.document_type - # - # @return [ String, Symbol ] _type The repository's document type. - # - # @since 6.0.0 - def document_type(_type = nil) - @document_type ||= _type - end - # Get or set the class-level index name setting. # # @example diff --git a/elasticsearch-persistence/lib/elasticsearch/persistence/repository/find.rb b/elasticsearch-persistence/lib/elasticsearch/persistence/repository/find.rb index cdd50c042..281486a4a 100644 --- a/elasticsearch-persistence/lib/elasticsearch/persistence/repository/find.rb +++ b/elasticsearch-persistence/lib/elasticsearch/persistence/repository/find.rb @@ -64,7 +64,6 @@ def find(*args) # def exists?(id, options={}) request = { index: index_name, id: id } - request[:type] = document_type if document_type client.exists(request.merge(options)) end @@ -84,10 +83,9 @@ def exists?(id, options={}) # def __find_one(id, options={}) request = { index: index_name, id: id } - request[:type] = document_type if document_type document = client.get(request.merge(options)) deserialize(document) - rescue Elasticsearch::Transport::Transport::Errors::NotFound => e + rescue Elastic::Transport::Transport::Errors::NotFound => e raise DocumentNotFound, e.message, caller end @@ -95,7 +93,6 @@ def __find_one(id, options={}) # def __find_many(ids, options={}) request = { index: index_name, body: { ids: ids } } - request[:type] = document_type if document_type documents = client.mget(request.merge(options)) documents[DOCS].map do |document| deserialize(document) if document[FOUND] diff --git a/elasticsearch-persistence/lib/elasticsearch/persistence/repository/search.rb b/elasticsearch-persistence/lib/elasticsearch/persistence/repository/search.rb index 2aa7db725..db7788682 100644 --- a/elasticsearch-persistence/lib/elasticsearch/persistence/repository/search.rb +++ b/elasticsearch-persistence/lib/elasticsearch/persistence/repository/search.rb @@ -60,8 +60,7 @@ module Search # @return [Elasticsearch::Persistence::Repository::Response::Results] # def search(query_or_definition, options={}) - request = { index: index_name, - type: document_type } + request = { index: index_name } if query_or_definition.respond_to?(:to_hash) request[:body] = query_or_definition.to_hash elsif query_or_definition.is_a?(String) @@ -98,8 +97,7 @@ def search(query_or_definition, options={}) # def count(query_or_definition=nil, options={}) query_or_definition ||= { query: { match_all: {} } } - request = { index: index_name, - type: document_type } + request = { index: index_name } if query_or_definition.respond_to?(:to_hash) request[:body] = query_or_definition.to_hash diff --git a/elasticsearch-persistence/lib/elasticsearch/persistence/repository/store.rb b/elasticsearch-persistence/lib/elasticsearch/persistence/repository/store.rb index a8eeb1866..0986d5540 100644 --- a/elasticsearch-persistence/lib/elasticsearch/persistence/repository/store.rb +++ b/elasticsearch-persistence/lib/elasticsearch/persistence/repository/store.rb @@ -27,7 +27,7 @@ module Store # # @example # repository.save(myobject) - # => {"_index"=>"...", "_type"=>"...", "_id"=>"...", "_version"=>1, "created"=>true} + # => {"_index"=>"...", "_id"=>"...", "_version"=>1, "created"=>true} # # @param [ Object ] document The document to save into Elasticsearch. # @param [ Hash ] options The save request options. @@ -40,7 +40,6 @@ def save(document, options={}) request = { index: index_name, id: id, body: serialized } - request[:type] = document_type if document_type client.index(request.merge(options)) end @@ -49,12 +48,12 @@ def save(document, options={}) # @example Update the document with partial data # # repository.update id: 1, title: 'UPDATED', tags: [] - # # => {"_index"=>"...", "_type"=>"...", "_id"=>"1", "_version"=>2} + # # => {"_index"=>"...", "_id"=>"1", "_version"=>2} # # @example Update the document with a script # # repository.update 1, script: 'ctx._source.views += 1' - # # => {"_index"=>"...", "_type"=>"...", "_id"=>"1", "_version"=>3} + # # => {"_index"=>"...", "_id"=>"1", "_version"=>3} # # @param [ Object ] document_or_id The document to update or the id of the document to update. # @param [ Hash ] options The update request options. @@ -65,7 +64,6 @@ def update(document_or_id, options = {}) if document_or_id.is_a?(String) || document_or_id.is_a?(Integer) id = document_or_id body = options - type = document_type else document = serialize(document_or_id) id = __extract_id_from_document(document) @@ -74,9 +72,8 @@ def update(document_or_id, options = {}) else body = { doc: document }.merge(options) end - type = document.delete(:type) || document_type end - client.update(index: index_name, id: id, type: type, body: body) + client.update(index: index_name, id: id, body: body) end # Remove the serialized object or document with specified ID from Elasticsearch @@ -84,7 +81,7 @@ def update(document_or_id, options = {}) # @example Remove the document with ID 1 # # repository.delete(1) - # # => {"_index"=>"...", "_type"=>"...", "_id"=>"1", "_version"=>4} + # # => {"_index"=>"...", "_id"=>"1", "_version"=>4} # # @param [ Object ] document_or_id The document to delete or the id of the document to delete. # @param [ Hash ] options The delete request options. @@ -98,7 +95,7 @@ def delete(document_or_id, options = {}) serialized = serialize(document_or_id) id = __get_id_from_document(serialized) end - client.delete({ index: index_name, type: document_type, id: id }.merge(options)) + client.delete({ index: index_name, id: id }.merge(options)) end end end diff --git a/elasticsearch-persistence/lib/elasticsearch/persistence/version.rb b/elasticsearch-persistence/lib/elasticsearch/persistence/version.rb index 18fe2466d..7fa2ce112 100644 --- a/elasticsearch-persistence/lib/elasticsearch/persistence/version.rb +++ b/elasticsearch-persistence/lib/elasticsearch/persistence/version.rb @@ -17,6 +17,6 @@ module Elasticsearch module Persistence - VERSION = '7.2.1' + VERSION = '8.0.0'.freeze end end diff --git a/elasticsearch-persistence/spec/repository/find_spec.rb b/elasticsearch-persistence/spec/repository/find_spec.rb index 083ee4c25..22cc5af5e 100644 --- a/elasticsearch-persistence/spec/repository/find_spec.rb +++ b/elasticsearch-persistence/spec/repository/find_spec.rb @@ -18,7 +18,6 @@ require 'spec_helper' describe Elasticsearch::Persistence::Repository::Find do - after do begin; repository.delete_index!; rescue; end end @@ -28,9 +27,7 @@ end describe '#exists?' do - context 'when the document exists' do - let(:id) do repository.save(a: 1)['_id'] end @@ -41,30 +38,15 @@ end context 'when the document does not exist' do - it 'returns false' do expect(repository.exists?('1')).to be(false) end end - - context 'when options are provided' do - - let(:id) do - repository.save(a: 1)['_id'] - end - - it 'applies the options' do - expect(repository.exists?(id, type: 'other_type')).to be(false) - end - end end describe '#find' do - context 'when options are not provided' do - context 'when a single id is provided' do - let!(:id) do repository.save(a: 1)['_id'] end @@ -75,7 +57,6 @@ end context 'when an array of ids is provided' do - let!(:ids) do 3.times.collect do |i| repository.save(a: i)['_id'] @@ -83,28 +64,30 @@ end it 'retrieves the documents' do - expect(repository.find(ids)).to eq([{ 'a' =>0 }, - { 'a' => 1 }, - { 'a' => 2 }]) + expect(repository.find(ids)).to eq([ + { 'a' =>0 }, + { 'a' => 1 }, + { 'a' => 2 } + ]) end context 'when some documents are found and some are not' do - before do ids[1] = 22 ids end it 'returns nil in the result list for the documents not found' do - expect(repository.find(ids)).to eq([{ 'a' =>0 }, + expect(repository.find(ids)).to eq([ + { 'a' =>0 }, nil, - { 'a' => 2 }]) + { 'a' => 2 } + ]) end end end context 'when multiple ids are provided' do - let!(:ids) do 3.times.collect do |i| repository.save(a: i)['_id'] @@ -112,14 +95,15 @@ end it 'retrieves the documents' do - expect(repository.find(*ids)).to eq([{ 'a' =>0 }, - { 'a' => 1 }, - { 'a' => 2 }]) + expect(repository.find(*ids)).to eq([ + { 'a' =>0 }, + { 'a' => 1 }, + { 'a' => 2 } + ]) end end context 'when the document cannot be found' do - before do begin; repository.create_index!; rescue; end end @@ -131,66 +115,5 @@ end end end - - context 'when options are provided' do - - context 'when a single id is passed' do - - let!(:id) do - repository.save(a: 1)['_id'] - end - - it 'applies the options' do - expect { - repository.find(id, type: 'none') - }.to raise_exception(Elasticsearch::Persistence::Repository::DocumentNotFound) - end - end - - context 'when an array of ids is passed' do - - let!(:ids) do - 3.times.collect do |i| - repository.save(a: i)['_id'] - end - end - - it 'applies the options' do - expect(repository.find(ids, type: 'none')).to eq([nil, nil, nil]) - end - end - - context 'when multiple ids are passed' do - - let!(:ids) do - 3.times.collect do |i| - repository.save(a: i)['_id'] - end - end - - it 'applies the options' do - expect(repository.find(*ids, type: 'none')).to eq([nil, nil, nil]) - end - end - end - - context 'when a document_type is defined on the class' do - - let(:repository) do - MyTestRepository.new(document_type:'other_type', client: DEFAULT_CLIENT, index_name: 'test') - end - - let!(:ids) do - 3.times.collect do |i| - repository.save(a: i)['_id'] - end - end - - it 'uses the document type in the query' do - expect(repository.find(ids)).to eq([{ 'a' =>0 }, - { 'a' => 1 }, - { 'a' => 2 }]) - end - end end end diff --git a/elasticsearch-persistence/spec/repository/response/results_spec.rb b/elasticsearch-persistence/spec/repository/response/results_spec.rb index 9d98cfc79..c4ca44683 100644 --- a/elasticsearch-persistence/spec/repository/response/results_spec.rb +++ b/elasticsearch-persistence/spec/repository/response/results_spec.rb @@ -43,23 +43,24 @@ def deserialize(document) { "took" => 2, "timed_out" => false, "_shards" => {"total" => 5, "successful" => 5, "failed" => 0}, - "hits" => - { "total" => 2, - "max_score" => 0.19, - "hits" => - [{"_index" => "my_index", - "_type" => "note", - "_id" => "1", - "_score" => 0.19, - "_source" => {"id" => 1, "title" => "Test 1"}}, - - {"_index" => "my_index", - "_type" => "note", - "_id" => "2", - "_score" => 0.19, - "_source" => {"id" => 2, "title" => "Test 2"}} - ] - } + "hits" => { + "total" => 2, + "max_score" => 0.19, + "hits" => [ + { + "_index" => "my_index", + "_id" => "1", + "_score" => 0.19, + "_source" => {"id" => 1, "title" => "Test 1"} + }, + { + "_index" => "my_index", + "_id" => "2", + "_score" => 0.19, + "_source" => {"id" => 2, "title" => "Test 2"} + } + ] + } } end diff --git a/elasticsearch-persistence/spec/repository/search_spec.rb b/elasticsearch-persistence/spec/repository/search_spec.rb index 8e94ecc1d..d2e323791 100644 --- a/elasticsearch-persistence/spec/repository/search_spec.rb +++ b/elasticsearch-persistence/spec/repository/search_spec.rb @@ -18,180 +18,54 @@ require 'spec_helper' describe Elasticsearch::Persistence::Repository::Search do - after do begin; repository.delete_index!; rescue; end end - describe '#search' do + let(:repository) do + DEFAULT_REPOSITORY + end - let(:repository) do - DEFAULT_REPOSITORY + describe '#search' do + before do + repository.save({ name: 'user' }, refresh: true) end - context 'when the repository does not have a type set' do - - before do - repository.save({ name: 'user' }, refresh: true) - end - - context 'when a query definition is provided as a hash' do - - it 'uses the default document type' do - expect(repository.search({ query: { match: { name: 'user' } } }).first).to eq('name' => 'user') - end - end - - context 'when a query definition is provided as a string' do - - it 'uses the default document type' do - expect(repository.search('user').first).to eq('name' => 'user') - end - end - - context 'when the query definition is neither a String nor a Hash' do - - it 'raises an ArgumentError' do - expect { - repository.search(1) - }.to raise_exception(ArgumentError) - end - end - - context 'when options are provided' do - - context 'when a query definition is provided as a hash' do - - it 'uses the default document type' do - expect(repository.search({ query: { match: { name: 'user' } } }, type: 'other').first).to be_nil - end - end - - context 'when a query definition is provided as a string' do - - it 'uses the default document type' do - expect(repository.search('user', type: 'other').first).to be_nil - end - end - - context 'when the query definition is neither a String nor a Hash' do - - it 'raises an ArgumentError' do - expect { - repository.search(1) - }.to raise_exception(ArgumentError) - end - end + context 'when a query definition is provided as a hash' do + it 'searches' do + expect(repository.search({ query: { match: { name: 'user' } } }).first).to eq('name' => 'user') end end - context 'when the repository does have a type set' do - - let(:repository) do - MyTestRepository.new(document_type: 'other_note') - end - - before do - repository.save({ name: 'user' }, refresh: true) + context 'when a query definition is provided as a string' do + it 'searches' do + expect(repository.search('user').first).to eq('name' => 'user') end + end - context 'when options are provided' do - - context 'when a query definition is provided as a hash' do - - it 'uses the options' do - expect(repository.search({ query: { match: { name: 'user' } } }, type: 'other').first).to be_nil - end - end - - context 'when a query definition is provided as a string' do - - it 'uses the options' do - expect(repository.search('user', type: 'other').first).to be_nil - end - end - - context 'when the query definition is neither a String nor a Hash' do - - it 'raises an ArgumentError' do - expect { - repository.search(1) - }.to raise_exception(ArgumentError) - end - end + context 'when the query definition is neither a String nor a Hash' do + it 'raises an ArgumentError' do + expect { + repository.search(1) + }.to raise_exception(ArgumentError) end end end describe '#count' do - - context 'when the repository does not have a type set' do - - let(:repository) do - DEFAULT_REPOSITORY - end - - before do - repository.save({ name: 'user' }, refresh: true) - end - - context 'when a query definition is provided as a hash' do - - it 'uses the default document type' do - expect(repository.count({ query: { match: { name: 'user' } } })).to eq(1) - end - end - - context 'when a query definition is provided as a string' do - - it 'uses the default document type' do - expect(repository.count('user')).to eq(1) - end - end - - context 'when options are provided' do - - context 'when a query definition is provided as a hash' do - - it 'uses the options' do - expect(repository.count({ query: { match: { name: 'user' } } }, type: 'other')).to eq(0) - end - end - - context 'when a query definition is provided as a string' do - - it 'uses the options' do - expect(repository.count('user', type: 'other')).to eq(0) - end - end - end + before do + repository.save({ name: 'usuario' }, refresh: true) end - context 'when the repository does have a type set' do - - let(:repository) do - MyTestRepository.new(document_type: 'other_note') + context 'when a query definition is provided as a hash' do + it 'uses the default document type' do + expect(repository.count({ query: { match: { name: 'usuario' } } })).to eq(1) end + end - before do - repository.save({ name: 'user' }, refresh: true) - end - - context 'when options are provided' do - - context 'when a query definition is provided as a hash' do - - it 'uses the options' do - expect(repository.count({ query: { match: { name: 'user' } } }, type: 'other')).to eq(0) - end - end - - context 'when a query definition is provided as a string' do - - it 'uses the options' do - expect(repository.count('user', type: 'other')).to eq(0) - end - end + context 'when a query definition is provided as a string' do + it 'uses the default document type' do + expect(repository.count('usuario')).to eq(1) end end end diff --git a/elasticsearch-persistence/spec/repository/store_spec.rb b/elasticsearch-persistence/spec/repository/store_spec.rb index bebf810aa..5be0b5df8 100644 --- a/elasticsearch-persistence/spec/repository/store_spec.rb +++ b/elasticsearch-persistence/spec/repository/store_spec.rb @@ -18,7 +18,6 @@ require 'spec_helper' describe Elasticsearch::Persistence::Repository::Store do - let(:repository) do DEFAULT_REPOSITORY end @@ -28,7 +27,6 @@ end describe '#save' do - let(:document) do { a: 1 } end @@ -42,7 +40,6 @@ end context 'when the repository defines a custom serialize method' do - before do class OtherNoteRepository include Elasticsearch::Persistence::Repository @@ -70,24 +67,9 @@ def serialize(document) expect(repository.find(response['_id'])).to eq('b' => 1) end end - - context 'when options are provided' do - - let!(:response) do - repository.save(document, type: 'other_note') - end - - it 'saves the document using the options' do - expect { - repository.find(response['_id']) - }.to raise_exception(Elasticsearch::Persistence::Repository::DocumentNotFound) - expect(repository.find(response['_id'], type: 'other_note')).to eq('a' => 1) - end - end end describe '#update' do - before(:all) do class Note def to_hash @@ -103,15 +85,12 @@ def to_hash end context 'when the document exists' do - let!(:id) do repository.save(Note.new)['_id'] end context 'when an id is provided' do - context 'when a doc is specified in the options' do - before do repository.update(id, doc: { text: 'testing_2' }) end @@ -122,7 +101,6 @@ def to_hash end context 'when a script is specified in the options' do - before do repository.update(id, script: { inline: 'ctx._source.views += 1' }) end @@ -133,7 +111,6 @@ def to_hash end context 'when params are specified in the options' do - before do repository.update(id, script: { inline: 'ctx._source.views += params.count', params: { count: 2 } }) @@ -145,7 +122,6 @@ def to_hash end context 'when upsert is specified in the options' do - before do repository.update(id, script: { inline: 'ctx._source.views += 1' }, upsert: { text: 'testing_2' }) @@ -157,7 +133,6 @@ def to_hash end context 'when doc_as_upsert is specified in the options' do - before do repository.update(id, doc: { text: 'testing_2' }, doc_as_upsert: true) @@ -170,9 +145,7 @@ def to_hash end context 'when a document is provided as the query criteria' do - context 'when no options are provided' do - before do repository.update(id: id, text: 'testing_2') end @@ -183,9 +156,7 @@ def to_hash end context 'when options are provided' do - context 'when a doc is specified in the options' do - before do repository.update({ id: id, text: 'testing' }, doc: { text: 'testing_2' }) end @@ -196,10 +167,11 @@ def to_hash end context 'when a script is specified in the options' do - before do - repository.update({ id: id, text: 'testing' }, - script: { inline: 'ctx._source.views += 1' }) + repository.update( + { id: id, text: 'testing' }, + script: { inline: 'ctx._source.views += 1' } + ) end it 'updates using the id and script from the options' do @@ -208,7 +180,6 @@ def to_hash end context 'when params are specified in the options' do - before do repository.update({ id: id, text: 'testing' }, script: { inline: 'ctx._source.views += params.count', @@ -221,7 +192,6 @@ def to_hash end context 'when upsert is specified in the options' do - before do repository.update({ id: id, text: 'testing_2' }, doc_as_upsert: true) @@ -236,17 +206,14 @@ def to_hash end context 'when the document does not exist' do - context 'when an id is provided 'do - it 'raises an exception' do expect { repository.update(1, doc: { text: 'testing_2' }) - }.to raise_exception(Elasticsearch::Transport::Transport::Errors::NotFound) + }.to raise_exception(Elastic::Transport::Transport::Errors::NotFound) end context 'when upsert is provided' do - before do repository.update(1, doc: { text: 'testing' }, doc_as_upsert: true) end @@ -258,15 +225,13 @@ def to_hash end context 'when a document is provided' do - it 'raises an exception' do expect { repository.update(id: 1, text: 'testing_2') - }.to raise_exception(Elasticsearch::Transport::Transport::Errors::NotFound) + }.to raise_exception(Elastic::Transport::Transport::Errors::NotFound) end context 'when upsert is provided' do - before do repository.update({ id: 1, text: 'testing' }, doc_as_upsert: true) end @@ -280,7 +245,6 @@ def to_hash end describe '#delete' do - before(:all) do class Note def to_hash @@ -296,13 +260,11 @@ def to_hash end context 'when the document exists' do - let!(:id) do repository.save(Note.new)['_id'] end context 'an id is provided' do - before do repository.delete(id) end @@ -315,7 +277,6 @@ def to_hash end context 'when a document is provided' do - before do repository.delete(id: id, text: 'testing') end @@ -329,15 +290,14 @@ def to_hash end context 'when the document does not exist' do - before do - repository.create_index!(include_type_name: true) + repository.create_index! end it 'raises an exception' do expect { repository.delete(1) - }.to raise_exception(Elasticsearch::Transport::Transport::Errors::NotFound) + }.to raise_exception(Elastic::Transport::Transport::Errors::NotFound) end end end diff --git a/elasticsearch-persistence/spec/repository_spec.rb b/elasticsearch-persistence/spec/repository_spec.rb index 05aeb1f53..a605a5250 100644 --- a/elasticsearch-persistence/spec/repository_spec.rb +++ b/elasticsearch-persistence/spec/repository_spec.rb @@ -18,9 +18,7 @@ require 'spec_helper' describe Elasticsearch::Persistence::Repository do - describe '#create' do - before(:all) do class RepositoryWithoutDSL include Elasticsearch::Persistence::Repository @@ -37,21 +35,9 @@ class RepositoryWithoutDSL expect(RepositoryWithoutDSL.create).to be_a(RepositoryWithoutDSL) end - context 'when options are provided' do - - let(:repository) do - RepositoryWithoutDSL.create(document_type: 'note') - end - - it 'sets the options on the instance' do - expect(repository.document_type).to eq('note') - end - end - context 'when a block is passed' do - let(:repository) do - RepositoryWithoutDSL.create(document_type: 'note') do + RepositoryWithoutDSL.create do mapping dynamic: 'strict' do indexes :foo end @@ -59,13 +45,12 @@ class RepositoryWithoutDSL end it 'executes the block on the instance' do - expect(repository.mapping.to_hash).to eq(note: { dynamic: 'strict', properties: { foo: { type: 'text' } } }) + expect(repository.mapping.to_hash).to eq({ dynamic: 'strict', properties: { foo: { type: 'text' } } }) end context 'when options are provided in the args and set in the block' do - let(:repository) do - RepositoryWithoutDSL.create(mapping: double('mapping', to_hash: {}), document_type: 'note') do + RepositoryWithoutDSL.create(mapping: double('mapping', to_hash: {})) do mapping dynamic: 'strict' do indexes :foo end @@ -80,7 +65,6 @@ class RepositoryWithoutDSL end describe '#initialize' do - before(:all) do class RepositoryWithoutDSL include Elasticsearch::Persistence::Repository @@ -98,7 +82,6 @@ class RepositoryWithoutDSL end context 'when options are not provided' do - let(:repository) do RepositoryWithoutDSL.new end @@ -118,23 +101,18 @@ class RepositoryWithoutDSL end context 'when options are provided' do - let(:client) do Elasticsearch::Client.new end let(:repository) do - RepositoryWithoutDSL.new(client: client, document_type: 'user', index_name: 'users', klass: Array) + RepositoryWithoutDSL.new(client: client, index_name: 'users', klass: Array) end it 'sets the client' do expect(repository.client).to be(client) end - it 'sets document type' do - expect(repository.document_type).to eq('user') - end - it 'sets index name' do expect(repository.index_name).to eq('users') end @@ -146,13 +124,11 @@ class RepositoryWithoutDSL end context 'when the DSL module is included' do - before(:all) do class RepositoryWithDSL include Elasticsearch::Persistence::Repository include Elasticsearch::Persistence::Repository::DSL - document_type 'note' index_name 'notes_repo' klass Hash client DEFAULT_CLIENT @@ -179,7 +155,6 @@ class RepositoryWithDSL end context '#client' do - it 'allows the value to be set only once on the class' do RepositoryWithDSL.client(double('client', class: 'other_client')) expect(RepositoryWithDSL.client).to be(DEFAULT_CLIENT) @@ -199,7 +174,6 @@ class RepositoryWithDSL end context '#klass' do - it 'allows the value to be set only once on the class' do RepositoryWithDSL.klass(Array) expect(RepositoryWithDSL.klass).to eq(Hash) @@ -229,28 +203,7 @@ class RepositoryWithDSL end end - context '#document_type' do - - it 'allows the value to be set only once on the class' do - RepositoryWithDSL.document_type('other_note') - expect(RepositoryWithDSL.document_type).to eq('note') - end - - it 'sets the value at the class level' do - expect(RepositoryWithDSL.document_type).to eq('note') - end - - it 'sets the value as the default at the instance level' do - expect(RepositoryWithDSL.new.document_type).to eq('note') - end - - it 'allows the value to be overridden with options on the instance' do - expect(RepositoryWithDSL.new(document_type: 'other_note').document_type).to eq('other_note') - end - end - context '#index_name' do - it 'allows the value to be set only once on the class' do RepositoryWithDSL.index_name('other_name') expect(RepositoryWithDSL.index_name).to eq('notes_repo') @@ -270,16 +223,14 @@ class RepositoryWithDSL end describe '#create_index!' do - context 'when the method is called on an instance' do - let(:repository) do RepositoryWithDSL.new end before do begin; repository.delete_index!; rescue; end - repository.create_index!(include_type_name: true) + repository.create_index! end it 'creates the index' do @@ -288,7 +239,6 @@ class RepositoryWithDSL end context 'when the method is called on the class' do - it 'raises a NotImplementedError' do expect { RepositoryWithDSL.create_index! @@ -298,9 +248,7 @@ class RepositoryWithDSL end describe '#delete_index!' do - context 'when the method is called on an instance' do - let(:repository) do RepositoryWithDSL.new end @@ -316,7 +264,6 @@ class RepositoryWithDSL end context 'when the method is called on the class' do - it 'raises a NotImplementedError' do expect { RepositoryWithDSL.delete_index! @@ -326,15 +273,13 @@ class RepositoryWithDSL end describe '#refresh_index!' do - context 'when the method is called on an instance' do - let(:repository) do RepositoryWithDSL.new end before do - repository.create_index!(include_type_name: true) + repository.create_index! end it 'refreshes the index' do @@ -343,7 +288,6 @@ class RepositoryWithDSL end context 'when the method is called on the class' do - it 'raises a NotImplementedError' do expect { RepositoryWithDSL.refresh_index! @@ -353,15 +297,13 @@ class RepositoryWithDSL end describe '#index_exists?' do - context 'when the method is called on an instance' do - let(:repository) do RepositoryWithDSL.new end before do - repository.create_index!(include_type_name: true) + repository.create_index! end it 'determines if the index exists' do @@ -377,7 +319,6 @@ class RepositoryWithDSL end context 'when the method is called on the class' do - it 'raises a NotImplementedError' do expect { RepositoryWithDSL.index_exists? @@ -387,13 +328,15 @@ class RepositoryWithDSL end describe '#mapping' do - let(:expected_mapping) do - { note: { dynamic: 'strict', - properties: { foo: { type: 'object', - properties: { bar: { type: 'text' } } }, - baz: { type: 'text' } } - } + { + dynamic: 'strict', + properties: { + foo: { + type: 'object', + properties: { bar: { type: 'text' } } }, + baz: { type: 'text' } + } } end @@ -410,24 +353,25 @@ class RepositoryWithDSL end context 'when the instance has a different document type' do - let(:expected_mapping) do - { other_note: { dynamic: 'strict', - properties: { foo: { type: 'object', - properties: { bar: { type: 'text' } } }, - baz: { type: 'text' } } - } + { + other_note: + { + dynamic: 'strict', + properties: { + foo: { + type: 'object', + properties: { bar: { type: 'text' } } + }, + baz: { type: 'text' } + } + } } end - - it 'updates the mapping to use the document type' do - expect(RepositoryWithDSL.new(document_type: 'other_note').mapping.to_hash).to eq(expected_mapping) - end end end describe '#settings' do - it 'sets the value at the class level' do expect(RepositoryWithDSL.settings.to_hash).to eq(number_of_shards: 1, number_of_replicas: 0) end @@ -443,7 +387,6 @@ class RepositoryWithDSL end context 'when the DSL module is not included' do - before(:all) do class RepositoryWithoutDSL include Elasticsearch::Persistence::Repository @@ -490,21 +433,8 @@ class RepositoryWithoutDSL end end - context '#document_type' do - - it 'does not define the method at the class level' do - expect { - RepositoryWithoutDSL.document_type - }.to raise_exception(NoMethodError) - end - - it 'allows the value to be overridden with options on the instance' do - expect(RepositoryWithoutDSL.new(document_type: 'notes').document_type).to eq('notes') - end - end context '#index_name' do - it 'does not define the method at the class level' do expect { RepositoryWithoutDSL.index_name @@ -521,7 +451,6 @@ class RepositoryWithoutDSL end describe '#create_index!' do - let(:repository) do RepositoryWithoutDSL.new(client: DEFAULT_CLIENT) end @@ -540,37 +469,9 @@ class RepositoryWithoutDSL repository.create_index! expect(repository.index_exists?).to eq(true) end - - context 'when the repository has a document type defined' do - - let(:repository) do - RepositoryWithoutDSL.new(client: DEFAULT_CLIENT, document_type: 'mytype') - end - - context 'when the server is version >= 7.0', if: server_version > '7.0' do - - context 'when the include_type_name option is specified' do - - it 'creates an index' do - repository.create_index!(include_type_name: true) - expect(repository.index_exists?).to eq(true) - end - end - - context 'when the include_type_name option is not specified' do - - it 'raises an error' do - expect { - repository.create_index! - }.to raise_exception(Elasticsearch::Transport::Transport::Errors::BadRequest) - end - end - end - end end describe '#delete_index!' do - let(:repository) do RepositoryWithoutDSL.new(client: DEFAULT_CLIENT) end @@ -582,14 +483,13 @@ class RepositoryWithoutDSL end it 'deletes an index' do - repository.create_index!(include_type_name: true) + repository.create_index! repository.delete_index! expect(repository.index_exists?).to eq(false) end end describe '#refresh_index!' do - let(:repository) do RepositoryWithoutDSL.new(client: DEFAULT_CLIENT) end @@ -605,7 +505,7 @@ class RepositoryWithoutDSL end it 'refreshes an index' do - repository.create_index!(include_type_name: true) + repository.create_index! expect(repository.refresh_index!['_shards']).to be_a(Hash) end end @@ -627,7 +527,7 @@ class RepositoryWithoutDSL end it 'returns whether the index exists' do - repository.create_index!(include_type_name: true) + repository.create_index! expect(repository.index_exists?).to be(true) end end @@ -651,16 +551,20 @@ class RepositoryWithoutDSL context 'when a block is passed to the create method' do let(:expected_mapping) do - { note: { dynamic: 'strict', - properties: { foo: { type: 'object', - properties: { bar: { type: 'text' } } }, - baz: { type: 'text' } } + { + dynamic: 'strict', + properties: { + foo: { + type: 'object', + properties: { bar: { type: 'text' } } + }, + baz: { type: 'text' } } } end let(:repository) do - RepositoryWithoutDSL.create(document_type: 'note') do + RepositoryWithoutDSL.create do mapping dynamic: 'strict' do indexes :foo do indexes :bar @@ -695,7 +599,6 @@ class RepositoryWithoutDSL end describe '#settings' do - it 'does not define the method at the class level' do expect { RepositoryWithoutDSL.settings @@ -711,9 +614,8 @@ class RepositoryWithoutDSL end context 'when a block is passed to the #create method' do - let(:repository) do - RepositoryWithoutDSL.create(document_type: 'note') do + RepositoryWithoutDSL.create do settings number_of_shards: 1, number_of_replicas: 0 end end @@ -723,18 +625,21 @@ class RepositoryWithoutDSL end context 'when a mapping is set in the block as well' do - let(:expected_mapping) do - { note: { dynamic: 'strict', - properties: { foo: { type: 'object', - properties: { bar: { type: 'text' } } }, - baz: { type: 'text' } } - } + { + dynamic: 'strict', + properties: { + foo: { + type: 'object', + properties: { bar: { type: 'text' } } + }, + baz: { type: 'text' } + } } end let(:repository) do - RepositoryWithoutDSL.create(document_type: 'note') do + RepositoryWithoutDSL.create do settings number_of_shards: 1, number_of_replicas: 0 do mapping dynamic: 'strict' do indexes :foo do diff --git a/elasticsearch-persistence/spec/spec_helper.rb b/elasticsearch-persistence/spec/spec_helper.rb index 6e5f58402..bf9ac3e07 100644 --- a/elasticsearch-persistence/spec/spec_helper.rb +++ b/elasticsearch-persistence/spec/spec_helper.rb @@ -36,7 +36,8 @@ # # @since 6.0.0 DEFAULT_CLIENT = Elasticsearch::Client.new(host: ELASTICSEARCH_URL, - tracer: (ENV['QUIET'] ? nil : ::Logger.new(STDERR))) + tracer: (ENV['QUIET'] ? nil : ::Logger.new(STDERR)), + transport_options: { :ssl => { verify: false } }) class MyTestRepository include Elasticsearch::Persistence::Repository @@ -47,7 +48,7 @@ class MyTestRepository # The default repository to be used by tests. # # @since 6.0.0 -DEFAULT_REPOSITORY = MyTestRepository.new(index_name: 'my_test_repository', document_type: 'test') +DEFAULT_REPOSITORY = MyTestRepository.new(index_name: 'my_test_repository') # Get the Elasticsearch server version. # diff --git a/elasticsearch-rails/Gemfile b/elasticsearch-rails/Gemfile index 90572cba1..4be2dd014 100644 --- a/elasticsearch-rails/Gemfile +++ b/elasticsearch-rails/Gemfile @@ -31,5 +31,8 @@ gem 'elasticsearch-persistence', group :development, :testing do gem 'pry-nav' gem 'rspec' - gem 'sqlite3' unless defined?(JRUBY_VERSION) + unless defined?(JRUBY_VERSION) + gem 'sqlite3', '~> 1.4' + gem 'debug' + end end diff --git a/elasticsearch-rails/README.md b/elasticsearch-rails/README.md index 12e7d7d59..4ec8ac2f8 100644 --- a/elasticsearch-rails/README.md +++ b/elasticsearch-rails/README.md @@ -6,18 +6,19 @@ library, providing features suitable for Ruby on Rails applications. ## Compatibility -This library is compatible with Ruby 1.9.3 and higher. +This library is compatible with Ruby 3.1 and higher. -The version numbers follow the Elasticsearch major versions. Currently the `main` branch is compatible with version `7.x` of the Elasticsearch stack. **We haven't tested and updated the code for Elasticsearch `8.0` yet**. +The version numbers follow the Elasticsearch major versions. Currently the `main` branch is compatible with version `8.x` of the Elasticsearch stack. -| Rubygem | | Elasticsearch | -|:-------------:|:-:| :-----------: | -| 0.1 | → | 1.x | -| 2.x | → | 2.x | -| 5.x | → | 5.x | -| 6.x | → | 6.x | -| 7.x | → | 7.x | -| main | → | 7.x | +| Rubygem | | Elasticsearch | +|:-------:|:-:|:-------------:| +| 0.1 | → | 1.x | +| 2.x | → | 2.x | +| 5.x | → | 5.x | +| 6.x | → | 6.x | +| 7.x | → | 7.x | +| 8.x | → | 8.x | +| main | → | 8.x | ## Installation @@ -137,9 +138,9 @@ This software is licensed under the Apache 2 license, quoted below. the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/elasticsearch-rails/elasticsearch-rails.gemspec b/elasticsearch-rails/elasticsearch-rails.gemspec index ac9375233..f7f2f5077 100644 --- a/elasticsearch-rails/elasticsearch-rails.gemspec +++ b/elasticsearch-rails/elasticsearch-rails.gemspec @@ -44,7 +44,7 @@ Gem::Specification.new do |s| s.extra_rdoc_files = ['README.md', 'LICENSE.txt'] s.rdoc_options = ['--charset=UTF-8'] - s.required_ruby_version = '>= 2.4' + s.required_ruby_version = '>= 3' s.add_development_dependency 'bundler' s.add_development_dependency 'cane' diff --git a/elasticsearch-rails/lib/elasticsearch/rails/instrumentation/log_subscriber.rb b/elasticsearch-rails/lib/elasticsearch/rails/instrumentation/log_subscriber.rb index c388961c0..a9f112f5d 100644 --- a/elasticsearch-rails/lib/elasticsearch/rails/instrumentation/log_subscriber.rb +++ b/elasticsearch-rails/lib/elasticsearch/rails/instrumentation/log_subscriber.rb @@ -46,8 +46,19 @@ def search(event) payload = event.payload name = "#{payload[:klass]} #{payload[:name]} (#{event.duration.round(1)}ms)" search = payload[:search].inspect.gsub(/:(\w+)=>/, '\1: ') + debug %Q| #{color(name, GREEN, color_option(true))} #{colorize_logging ? "\e[2m#{search}\e[0m" : search}| + end + + private + + def color_option(bold_value) + new_color_syntax? ? { bold: bold_value } : bold_value + end + + def new_color_syntax? + return @new_color_syntax if defined?(@new_color_syntax) - debug %Q| #{color(name, GREEN, true)} #{colorize_logging ? "\e[2m#{search}\e[0m" : search}| + @new_color_syntax = ::Rails.respond_to?(:gem_version) && ::Rails.gem_version >= '7.1' end end diff --git a/elasticsearch-rails/lib/elasticsearch/rails/tasks/import.rb b/elasticsearch-rails/lib/elasticsearch/rails/tasks/import.rb index b43d67163..dcdc82d89 100644 --- a/elasticsearch-rails/lib/elasticsearch/rails/tasks/import.rb +++ b/elasticsearch-rails/lib/elasticsearch/rails/tasks/import.rb @@ -80,7 +80,6 @@ total_errors = klass.__elasticsearch__.import force: ENV.fetch('http://github.com/FORCE', false), batch_size: ENV.fetch('http://github.com/BATCH', 1000).to_i, index: ENV.fetch('http://github.com/INDEX', nil), - type: ENV.fetch('http://github.com/TYPE', nil), scope: ENV.fetch('http://github.com/SCOPE', nil) do |response| pbar.inc response['items'].size if pbar STDERR.flush diff --git a/elasticsearch-rails/lib/elasticsearch/rails/version.rb b/elasticsearch-rails/lib/elasticsearch/rails/version.rb index 07d084dae..6506ad906 100644 --- a/elasticsearch-rails/lib/elasticsearch/rails/version.rb +++ b/elasticsearch-rails/lib/elasticsearch/rails/version.rb @@ -17,6 +17,6 @@ module Elasticsearch module Rails - VERSION = "7.2.1" + VERSION = '8.0.0'.freeze end end diff --git a/elasticsearch-rails/lib/rails/templates/indexer.rb b/elasticsearch-rails/lib/rails/templates/indexer.rb index 1ea1d9b6c..4ba92a45e 100644 --- a/elasticsearch-rails/lib/rails/templates/indexer.rb +++ b/elasticsearch-rails/lib/rails/templates/indexer.rb @@ -37,7 +37,7 @@ def perform(operation, klass, record_id, options={}) record.__elasticsearch__.client = Client record.__elasticsearch__.__send__ "#{operation}_document" when /delete/ - Client.delete index: klass.constantize.index_name, type: klass.constantize.document_type, id: record_id + Client.delete index: klass.constantize.index_name, id: record_id else raise ArgumentError, "Unknown operation '#{operation}'" end end diff --git a/elasticsearch-rails/spec/instrumentation/log_subscriber_spec.rb b/elasticsearch-rails/spec/instrumentation/log_subscriber_spec.rb new file mode 100644 index 000000000..7512f006a --- /dev/null +++ b/elasticsearch-rails/spec/instrumentation/log_subscriber_spec.rb @@ -0,0 +1,57 @@ +# Licensed to Elasticsearch B.V. under one or more contributor +# license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright +# ownership. Elasticsearch B.V. licenses this file to you under +# the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +require 'spec_helper' +require 'elasticsearch/rails/instrumentation/log_subscriber' + +describe Elasticsearch::Rails::Instrumentation::LogSubscriber do + subject(:instance) { described_class.new } + + let(:logger) { instance_double(Logger) } + + before do + allow(instance).to receive(:logger) { logger } + end + + describe "#search" do + subject { instance.search(event) } + + let(:event) { double("search.elasticsearch", duration: 1.2345, payload: { name: "execute", search: { query: { match_all: {}}}}) } + + it "logs the event" do + expect(instance).to receive(:color).with(" execute (1.2ms)", described_class::GREEN, { bold: true }).and_call_original + expect(logger).to receive(:debug?) { true } + expect(logger).to receive(:debug).with(" \e[1m\e[32m execute (1.2ms)\e[0m \e[2m{query: {match_all: {}}}\e[0m") + subject + end + + context "when Rails version is older" do + let(:rails_version) { "7.0.0" } + + before do + allow(::Rails).to receive(:gem_version) { Gem::Version.new(rails_version) } + end + + it "logs the event" do + expect(instance).to receive(:color).with(" execute (1.2ms)", described_class::GREEN, true).and_call_original + expect(logger).to receive(:debug?) { true } + expect(logger).to receive(:debug).with(" \e[1m\e[32m execute (1.2ms)\e[0m \e[2m{query: {match_all: {}}}\e[0m") + subject + end + end + end +end diff --git a/elasticsearch-rails/spec/instrumentation_spec.rb b/elasticsearch-rails/spec/instrumentation_spec.rb index 3fcbc5916..9245549af 100644 --- a/elasticsearch-rails/spec/instrumentation_spec.rb +++ b/elasticsearch-rails/spec/instrumentation_spec.rb @@ -18,13 +18,10 @@ require 'spec_helper' describe 'ActiveSupport::Instrumentation integration' do - before(:all) do class DummyInstrumentationModel extend Elasticsearch::Model::Searching::ClassMethods - - def self.index_name; 'foo'; end - def self.document_type; 'bar'; end + def self.index_name; 'foo'; end end end @@ -33,10 +30,14 @@ def self.document_type; 'bar'; end end let(:response_document) do - { 'took' => '5ms', - 'hits' => { 'total' => 123, - 'max_score' => 456, - 'hits' => [] } } + { + 'took' => '5ms', + 'hits' => { + 'total' => 123, + 'max_score' => 456, + 'hits' => [] + } + } end let(:search) do @@ -53,7 +54,6 @@ def self.document_type; 'bar'; end end context 'SearchRequest#execute!' do - it 'wraps the method with instrumentation' do expect(search).to respond_to(:execute_without_instrumentation!) expect(search).to respond_to(:execute_with_instrumentation!) @@ -61,14 +61,19 @@ def self.document_type; 'bar'; end end context 'Model#search' do - before do - expect(ActiveSupport::Notifications).to receive(:instrument).with('search.elasticsearch', - { klass: 'DummyInstrumentationModel', - name: 'Search', - search: { body: query, - index: 'foo', - type: 'bar' } }).and_return({}) + expect(ActiveSupport::Notifications). + to receive(:instrument). + with('search.elasticsearch', + { + klass: 'DummyInstrumentationModel', + name: 'Search', + search: { + body: query, + index: 'foo', + } + } + ).and_return({}) end let(:query) do diff --git a/elasticsearch-rails/spec/lograge_spec.rb b/elasticsearch-rails/spec/lograge_spec.rb index 980aa9f1b..3b54f1839 100644 --- a/elasticsearch-rails/spec/lograge_spec.rb +++ b/elasticsearch-rails/spec/lograge_spec.rb @@ -38,14 +38,15 @@ require 'elasticsearch/rails/lograge' describe 'ActiveSupport::Instrumentation integration' do - before do Elasticsearch::Rails::Lograge::Railtie.run_initializers end it 'customizes the Lograge configuration' do - expect(Elasticsearch::Rails::Lograge::Railtie.initializers - .select { |i| i.name == 'elasticsearch.lograge' } - .first).not_to be_nil + expect( + Elasticsearch::Rails::Lograge::Railtie.initializers + .select { |i| i.name == 'elasticsearch.lograge' } + .first + ).not_to be_nil end end diff --git a/elasticsearch-rails/spec/spec_helper.rb b/elasticsearch-rails/spec/spec_helper.rb index e0a299964..3a9eb8e6c 100644 --- a/elasticsearch-rails/spec/spec_helper.rb +++ b/elasticsearch-rails/spec/spec_helper.rb @@ -20,6 +20,7 @@ require 'elasticsearch/model' require 'elasticsearch/rails' require 'rails/railtie' +require 'rails/version' require 'elasticsearch/rails/instrumentation' @@ -36,7 +37,8 @@ tracer = ::Logger.new(STDERR) tracer.formatter = lambda { |s, d, p, m| "#{m.gsub(/^.*$/) { |n| ' ' + n }.ansi(:faint)}\n" } Elasticsearch::Model.client = Elasticsearch::Client.new host: ELASTICSEARCH_URL, - tracer: (ENV['QUIET'] ? nil : tracer) + tracer: (ENV['QUIET'] ? nil : tracer), + transport_options: { :ssl => { verify: false } } puts "Elasticsearch Version: #{Elasticsearch::Model.client.info['version']}" unless ActiveRecord::Base.connected?