diff --git a/CHANGELOG.md b/CHANGELOG.md index bf79a59..40b7103 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 5.0.0 (unreleased) - Searches now use lazy loading (similar to Active Record) +- Added `unscope` option to better support working with default scopes - Added support for `:async` and `:queue` modes for `reindex` on relation - Added basic protection from unfiltered parameters to `where` option - Added `models` option to `similar` method diff --git a/lib/searchkick.rb b/lib/searchkick.rb index b40f87e..ca98887 100644 --- a/lib/searchkick.rb +++ b/lib/searchkick.rb @@ -315,6 +315,18 @@ module Searchkick end # private + def self.scope(model) + # safety check to make sure used properly in code + raise Error, "Cannot scope relation" if relation?(model) + + if model.searchkick_options[:unscope] + model.unscoped + else + model + end + end + + # private def self.not_found_error?(e) (defined?(Elastic::Transport) && e.is_a?(Elastic::Transport::Transport::Errors::NotFound)) || (defined?(Elasticsearch::Transport) && e.is_a?(Elasticsearch::Transport::Transport::Errors::NotFound)) || diff --git a/lib/searchkick/bulk_reindex_job.rb b/lib/searchkick/bulk_reindex_job.rb index b7f1161..626d6d1 100644 --- a/lib/searchkick/bulk_reindex_job.rb +++ b/lib/searchkick/bulk_reindex_job.rb @@ -10,6 +10,7 @@ module Searchkick # legacy record_ids ||= min_id..max_id + klass = Searchkick.scope(klass) relation = Searchkick.load_records(klass, record_ids) relation = relation.search_import if relation.respond_to?(:search_import) diff --git a/lib/searchkick/model.rb b/lib/searchkick/model.rb index 1bcce08..d8b9d10 100644 --- a/lib/searchkick/model.rb +++ b/lib/searchkick/model.rb @@ -7,7 +7,7 @@ module Searchkick :filterable, :geo_shape, :highlight, :ignore_above, :index_name, :index_prefix, :inheritance, :language, :locations, :mappings, :match, :merge_mappings, :routing, :searchable, :search_synonyms, :settings, :similarity, :special_characters, :stem, :stemmer, :stem_conversions, :stem_exclusion, :stemmer_override, :suggest, :synonyms, :text_end, - :text_middle, :text_start, :word, :word_end, :word_middle, :word_start] + :text_middle, :text_start, :unscope, :word, :word_end, :word_middle, :word_start] raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any? raise "Only call searchkick once per model" if respond_to?(:searchkick_index) @@ -78,7 +78,7 @@ module Searchkick def searchkick_reindex(method_name = nil, **options) scoped = Searchkick.relation?(self) # call searchkick_klass for inheritance - relation = scoped ? all : searchkick_klass.all + relation = scoped ? all : Searchkick.scope(searchkick_klass).all # prevent scope from affecting search_data unscoped do searchkick_index.reindex(relation, method_name, scoped: scoped, **options) diff --git a/lib/searchkick/process_batch_job.rb b/lib/searchkick/process_batch_job.rb index b543158..1dc2e14 100644 --- a/lib/searchkick/process_batch_job.rb +++ b/lib/searchkick/process_batch_job.rb @@ -13,6 +13,7 @@ module Searchkick {id: parts[0], routing: parts[1]} end + klass = Searchkick.scope(klass) index.send(:record_indexer).reindex_items(klass, items, method_name: nil) end end diff --git a/lib/searchkick/reindex_v2_job.rb b/lib/searchkick/reindex_v2_job.rb index cde289a..65d098d 100644 --- a/lib/searchkick/reindex_v2_job.rb +++ b/lib/searchkick/reindex_v2_job.rb @@ -6,6 +6,8 @@ module Searchkick model = klass.constantize # use should_index? to decide whether to index (not default scope) # just like saving inline + # could use Searchkick.scope() in future + # but keep for now for backwards compatibility model = model.unscoped if model.respond_to?(:unscoped) items = [{id: id, routing: routing}] model.searchkick_index.send(:record_indexer).reindex_items(model, items, method_name: method_name, single: true) diff --git a/lib/searchkick/results.rb b/lib/searchkick/results.rb index 443b581..d602e9c 100644 --- a/lib/searchkick/results.rb +++ b/lib/searchkick/results.rb @@ -309,6 +309,8 @@ module Searchkick end def results_query(records, hits) + records = Searchkick.scope(records) + ids = hits.map { |hit| hit["_id"] } if options[:includes] || options[:model_includes] included_relations = [] diff --git a/test/models/artist.rb b/test/models/artist.rb new file mode 100644 index 0000000..d177458 --- /dev/null +++ b/test/models/artist.rb @@ -0,0 +1,7 @@ +class Artist + searchkick unscope: true + + def should_index? + should_index + end +end diff --git a/test/support/activerecord.rb b/test/support/activerecord.rb index be86540..e8e07e4 100644 --- a/test/support/activerecord.rb +++ b/test/support/activerecord.rb @@ -65,6 +65,12 @@ ActiveRecord::Schema.define do t.string :name t.boolean :active end + + create_table :artists do |t| + t.string :name + t.boolean :active + t.boolean :should_index + end end class Product < ActiveRecord::Base @@ -99,3 +105,7 @@ end class Band < ActiveRecord::Base default_scope { where(active: true).order(:name) } end + +class Artist < ActiveRecord::Base + default_scope { where(active: true).order(:name) } +end diff --git a/test/support/mongoid.rb b/test/support/mongoid.rb index aa1b2fd..9bcd6bf 100644 --- a/test/support/mongoid.rb +++ b/test/support/mongoid.rb @@ -75,3 +75,13 @@ class Band default_scope -> { where(active: true).order(name: 1) } end + +class Artist + include Mongoid::Document + + field :name + field :active, type: Mongoid::Boolean + field :should_index, type: Mongoid::Boolean + + default_scope -> { where(active: true).order(name: 1) } +end diff --git a/test/unscope_test.rb b/test/unscope_test.rb new file mode 100644 index 0000000..2ce8e2a --- /dev/null +++ b/test/unscope_test.rb @@ -0,0 +1,39 @@ +require_relative "test_helper" + +class UnscopeTest < ActiveSupport::TestCase + def setup + @@once ||= Artist.reindex + + Artist.unscoped.destroy_all + end + + def test_reindex + create_records + + Artist.reindex + assert_search "*", ["Test", "Test 2"] + assert_search "*", ["Test", "Test 2"], {load: false} + end + + def test_relation_async + create_records + + Artist.unscoped.reindex(mode: :async) + perform_enqueued_jobs + + Artist.search_index.refresh + assert_search "*", ["Test", "Test 2"] + end + + def create_records + store [ + {name: "Test", active: true, should_index: true}, + {name: "Test 2", active: false, should_index: true}, + {name: "Test 3", active: false, should_index: false}, + ], reindex: false + end + + def default_model + Artist + end +end -- libgit2 0.21.0