lib/meilisearch-rails.rb in meilisearch-rails-0.2.3 vs lib/meilisearch-rails.rb in meilisearch-rails-0.3.0
- old
+ new
@@ -1,9 +1,10 @@
require 'meilisearch'
require 'meilisearch/version'
require 'meilisearch/utilities'
+require 'meilisearch/errors'
if defined? Rails
begin
require 'meilisearch/railtie'
rescue LoadError
@@ -17,15 +18,10 @@
end
require 'logger'
module MeiliSearch
-
- class NotConfigured < StandardError; end
- class BadConfiguration < StandardError; end
- class NoBlockGiven < StandardError; end
-
autoload :Configuration, 'meilisearch/configuration'
extend Configuration
autoload :Pagination, 'meilisearch/pagination'
@@ -40,31 +36,30 @@
klass.class_eval do
extend ClassMethods
include InstanceMethods
end
end
-
end
class IndexSettings
DEFAULT_BATCH_SIZE = 1000
- DEFAULT_PRIMARY_KEY = 'id'
+ DEFAULT_PRIMARY_KEY = 'id'.freeze
# MeiliSearch settings
- OPTIONS = [
- :searchableAttributes,
- :filterableAttributes,
- :displayedAttributes,
- :distinctAttribute,
- :synonyms,
- :stopWords,
- :rankingRules,
- :attributesToHighlight,
- :attributesToCrop,
- :cropLength,
- ]
+ OPTIONS = %i[
+ searchableAttributes
+ filterableAttributes
+ displayedAttributes
+ distinctAttribute
+ synonyms
+ stopWords
+ rankingRules
+ attributesToHighlight
+ attributesToCrop
+ cropLength
+ ].freeze
OPTIONS.each do |option|
define_method option do |value|
instance_variable_set("@#{option}", value)
end
@@ -82,44 +77,46 @@
@serializer = serializer
# instance_variable_set("@serializer", serializer)
end
def attribute(*names, &block)
- raise ArgumentError.new('Cannot pass multiple attribute names if block given') if block_given? and names.length > 1
+ raise ArgumentError, 'Cannot pass multiple attribute names if block given' if block_given? && (names.length > 1)
+
@attributes ||= {}
names.flatten.each do |name|
- @attributes[name.to_s] = block_given? ? Proc.new { |d| d.instance_eval(&block) } : Proc.new { |d| d.send(name) }
+ @attributes[name.to_s] = block_given? ? proc { |d| d.instance_eval(&block) } : proc { |d| d.send(name) }
end
end
- alias :attributes :attribute
+ alias attributes attribute
def add_attribute(*names, &block)
- raise ArgumentError.new('Cannot pass multiple attribute names if block given') if block_given? and names.length > 1
+ raise ArgumentError, 'Cannot pass multiple attribute names if block given' if block_given? && (names.length > 1)
+
@additional_attributes ||= {}
names.each do |name|
- @additional_attributes[name.to_s] = block_given? ? Proc.new { |d| d.instance_eval(&block) } : Proc.new { |d| d.send(name) }
+ @additional_attributes[name.to_s] = block_given? ? proc { |d| d.instance_eval(&block) } : proc { |d| d.send(name) }
end
end
- alias :add_attributes :add_attribute
+ alias add_attributes add_attribute
- def is_mongoid?(document)
+ def mongoid?(document)
defined?(::Mongoid::Document) && document.class.include?(::Mongoid::Document)
end
- def is_sequel?(document)
+ def sequel?(document)
defined?(::Sequel) && document.class < ::Sequel::Model
end
- def is_active_record?(document)
- !is_mongoid?(document) && !is_sequel?(document)
+ def active_record?(document)
+ !mongoid?(document) && !sequel?(document)
end
def get_default_attributes(document)
- if is_mongoid?(document)
+ if mongoid?(document)
# work-around mongoid 2.4's unscoped method, not accepting a block
document.attributes
- elsif is_sequel?(document)
+ elsif sequel?(document)
document.to_hash
else
document.class.unscoped do
document.attributes
end
@@ -130,35 +127,31 @@
get_attributes(document).keys
end
def attributes_to_hash(attributes, document)
if attributes
- Hash[attributes.map { |name, value| [name.to_s, value.call(document) ] }]
+ attributes.map { |name, value| [name.to_s, value.call(document)] }.to_h
else
{}
end
end
def get_attributes(document)
# If a serializer is set, we ignore attributes
# everything should be done via the serializer
- if not @serializer.nil?
+ if !@serializer.nil?
attributes = @serializer.new(document).attributes
- else
- if @attributes.nil? || @attributes.length == 0
+ elsif @attributes.blank?
+ attributes = get_default_attributes(document)
# no `attribute ...` have been configured, use the default attributes of the model
- attributes = get_default_attributes(document)
- else
+ elsif active_record?(document)
# at least 1 `attribute ...` has been configured, therefore use ONLY the one configured
- if is_active_record?(document)
- document.class.unscoped do
- attributes = attributes_to_hash(@attributes, document)
- end
- else
+ document.class.unscoped do
attributes = attributes_to_hash(@attributes, document)
end
- end
+ else
+ attributes = attributes_to_hash(@attributes, document)
end
attributes.merge!(attributes_to_hash(@additional_attributes, document)) if @additional_attributes
if @options[:sanitize]
@@ -169,40 +162,38 @@
::Rails::Html::FullSanitizer.new
end
attributes = sanitize_attributes(attributes, sanitizer)
end
- if @options[:force_utf8_encoding]
- attributes = encode_attributes(attributes)
- end
+ attributes = encode_attributes(attributes) if @options[:force_utf8_encoding]
attributes
end
- def sanitize_attributes(v, sanitizer)
- case v
+ def sanitize_attributes(value, sanitizer)
+ case value
when String
- sanitizer.sanitize(v)
+ sanitizer.sanitize(value)
when Hash
- v.each { |key, value| v[key] = sanitize_attributes(value, sanitizer) }
+ value.each { |key, val| value[key] = sanitize_attributes(val, sanitizer) }
when Array
- v.map { |x| sanitize_attributes(x, sanitizer) }
+ value.map { |item| sanitize_attributes(item, sanitizer) }
else
- v
+ value
end
end
- def encode_attributes(v)
- case v
+ def encode_attributes(value)
+ case value
when String
- v.force_encoding('utf-8')
+ value.force_encoding('utf-8')
when Hash
- v.each { |key, value| v[key] = encode_attributes(value) }
+ value.each { |key, val| value[key] = encode_attributes(val) }
when Array
- v.map { |x| encode_attributes(x) }
+ value.map { |x| encode_attributes(x) }
else
- v
+ value
end
end
def get_setting(name)
instance_variable_get("@#{name}")
@@ -210,18 +201,21 @@
def to_settings
settings = {}
OPTIONS.each do |k|
v = get_setting(k)
- settings[k] = v if !v.nil?
+ settings[k] = v unless v.nil?
end
settings
end
def add_index(index_uid, options = {}, &block)
- raise ArgumentError.new('No block given') if !block_given?
- raise ArgumentError.new('Options auto_index and auto_remove cannot be set on nested indexes') if options[:auto_index] || options[:auto_remove]
+ raise ArgumentError, 'No block given' unless block_given?
+ if options[:auto_index] || options[:auto_remove]
+ raise ArgumentError, 'Options auto_index and auto_remove cannot be set on nested indexes'
+ end
+
@additional_indexes ||= {}
options[:index_uid] = index_uid
@additional_indexes[options] = IndexSettings.new(options, &block)
end
@@ -240,74 +234,71 @@
# this class wraps an MeiliSearch::Index document ensuring all raised exceptions
# are correctly logged or thrown depending on the `raise_on_failure` option
class SafeIndex
def initialize(index_uid, raise_on_failure, options)
client = MeiliSearch.client
- primary_key = options[:primary_key] || MeiliSearch::IndexSettings::DEFAULT_PRIMARY_KEY
+ primary_key = options[:primary_key] || MeiliSearch::IndexSettings::DEFAULT_PRIMARY_KEY
@index = client.get_or_create_index(index_uid, { primaryKey: primary_key })
@raise_on_failure = raise_on_failure.nil? || raise_on_failure
end
::MeiliSearch::Index.instance_methods(false).each do |m|
- define_method(m) do |*args, &block|
- if (m == :update_settings)
- args[0].delete(:attributesToHighlight) if args[0][:attributesToHighlight]
- args[0].delete(:attributesToCrop) if args[0][:attributesToCrop]
- args[0].delete(:cropLength) if args[0][:cropLength]
- end
- SafeIndex.log_or_throw(m, @raise_on_failure) do
- @index.send(m, *args, &block)
- end
+ define_method(m) do |*args, &block|
+ if m == :update_settings
+ args[0].delete(:attributesToHighlight) if args[0][:attributesToHighlight]
+ args[0].delete(:attributesToCrop) if args[0][:attributesToCrop]
+ args[0].delete(:cropLength) if args[0][:cropLength]
end
+ SafeIndex.log_or_throw(m, @raise_on_failure) do
+ @index.send(m, *args, &block)
+ end
+ end
end
# special handling of wait_for_pending_update to handle null task_id
def wait_for_pending_update(update_id)
return if update_id.nil? && !@raise_on_failure # ok
+
SafeIndex.log_or_throw(:wait_for_pending_update, @raise_on_failure) do
@index.wait_for_pending_update(update_id)
end
end
# special handling of settings to avoid raising errors on 404
def settings(*args)
SafeIndex.log_or_throw(:settings, @raise_on_failure) do
- begin
- @index.settings(*args)
- rescue ::MeiliSearch::ApiError => e
- return {} if e.code == 404 # not fatal
- raise e
- end
+ @index.settings(*args)
+ rescue ::MeiliSearch::ApiError => e
+ return {} if e.code == 404 # not fatal
+
+ raise e
end
end
- private
def self.log_or_throw(method, raise_on_failure, &block)
- begin
- yield
- rescue ::MeiliSearch::ApiError => e
- raise e if raise_on_failure
- # log the error
- (Rails.logger || Logger.new(STDOUT)).error("[meilisearch-rails] #{e.message}")
- # return something
- case method.to_s
- when 'search'
- # some attributes are required
- { 'hits' => [], 'hitsPerPage' => 0, 'page' => 0, 'facetsDistribution' => {}, 'error' => e }
- else
- # empty answer
- { 'error' => e }
- end
+ yield
+ rescue ::MeiliSearch::ApiError => e
+ raise e if raise_on_failure
+
+ # log the error
+ (Rails.logger || Logger.new($stdout)).error("[meilisearch-rails] #{e.message}")
+ # return something
+ case method.to_s
+ when 'search'
+ # some attributes are required
+ { 'hits' => [], 'hitsPerPage' => 0, 'page' => 0, 'facetsDistribution' => {}, 'error' => e }
+ else
+ # empty answer
+ { 'error' => e }
end
end
end
# these are the class methods added when MeiliSearch is included
module ClassMethods
-
def self.extended(base)
- class <<base
+ class << base
alias_method :without_auto_index, :ms_without_auto_index unless method_defined? :without_auto_index
alias_method :reindex!, :ms_reindex! unless method_defined? :reindex!
alias_method :index_documents, :ms_index_documents unless method_defined? :index_documents
alias_method :index!, :ms_index! unless method_defined? :index!
alias_method :remove_from_index!, :ms_remove_from_index! unless method_defined? :remove_from_index!
@@ -322,11 +313,14 @@
base.cattr_accessor :meilisearch_options, :meilisearch_settings
end
def meilisearch(options = {}, &block)
self.meilisearch_settings = IndexSettings.new(options, &block)
- self.meilisearch_options = { type: ms_full_const_get(model_name.to_s), per_page: meilisearch_settings.get_setting(:hitsPerPage) || 20, page: 1 }.merge(options)
+ self.meilisearch_options = {
+ type: ms_full_const_get(model_name.to_s),
+ per_page: meilisearch_settings.get_setting(:hitsPerPage) || 20, page: 1
+ }.merge(options)
attr_accessor :formatted
if options[:synchronous] == true
if defined?(::Sequel) && self < Sequel::Model
@@ -336,28 +330,29 @@
super(*args)
copy_after_validation.bind(self).call
ms_mark_synchronous
end
end
- else
- after_validation :ms_mark_synchronous if respond_to?(:after_validation)
+ elsif respond_to?(:after_validation)
+ after_validation :ms_mark_synchronous
end
end
if options[:enqueue]
- raise ArgumentError.new("Cannot use a enqueue if the `synchronous` option if set") if options[:synchronous]
+ raise ArgumentError, 'Cannot use a enqueue if the `synchronous` option if set' if options[:synchronous]
+
proc = if options[:enqueue] == true
- Proc.new do |record, remove|
- MSJob.perform_later(record, remove ? 'ms_remove_from_index!' : 'ms_index!')
- end
- elsif options[:enqueue].respond_to?(:call)
- options[:enqueue]
- elsif options[:enqueue].is_a?(Symbol)
- Proc.new { |record, remove| self.send(options[:enqueue], record, remove) }
- else
- raise ArgumentError.new("Invalid `enqueue` option: #{options[:enqueue]}")
- end
- meilisearch_options[:enqueue] = Proc.new do |record, remove|
+ proc do |record, remove|
+ MSJob.perform_later(record, remove ? 'ms_remove_from_index!' : 'ms_index!')
+ end
+ elsif options[:enqueue].respond_to?(:call)
+ options[:enqueue]
+ elsif options[:enqueue].is_a?(Symbol)
+ proc { |record, remove| send(options[:enqueue], record, remove) }
+ else
+ raise ArgumentError, "Invalid `enqueue` option: #{options[:enqueue]}"
+ end
+ meilisearch_options[:enqueue] = proc do |record, remove|
proc.call(record, remove) unless ms_without_auto_index_scope
end
end
unless options[:auto_index] == false
if defined?(::Sequel) && self < Sequel::Model
@@ -388,11 +383,11 @@
else
copy_after_save = instance_method(:after_save)
define_method(:after_save) do |*args|
super(*args)
copy_after_save.bind(self).call
- self.db.after_commit do
+ db.after_commit do
ms_perform_index_tasks
end
end
end
end
@@ -415,12 +410,12 @@
copy_after_destroy.bind(self).call
ms_enqueue_remove_from_index!(ms_synchronous?)
super(*args)
end
end
- else
- after_destroy { |searchable| searchable.ms_enqueue_remove_from_index!(ms_synchronous?) } if respond_to?(:after_destroy)
+ elsif respond_to?(:after_destroy)
+ after_destroy { |searchable| searchable.ms_enqueue_remove_from_index!(ms_synchronous?) }
end
end
end
def ms_without_auto_index(&block)
@@ -431,42 +426,42 @@
self.ms_without_auto_index_scope = false
end
end
def ms_without_auto_index_scope=(value)
- Thread.current["ms_without_auto_index_scope_for_#{self.model_name}"] = value
+ Thread.current["ms_without_auto_index_scope_for_#{model_name}"] = value
end
def ms_without_auto_index_scope
- Thread.current["ms_without_auto_index_scope_for_#{self.model_name}"]
+ Thread.current["ms_without_auto_index_scope_for_#{model_name}"]
end
def ms_reindex!(batch_size = MeiliSearch::IndexSettings::DEFAULT_BATCH_SIZE, synchronous = false)
return if ms_without_auto_index_scope
+
ms_configurations.each do |options, settings|
next if ms_indexing_disabled?(options)
+
index = ms_ensure_init(options, settings)
last_update = nil
ms_find_in_batches(batch_size) do |group|
if ms_conditional_index?(options)
# delete non-indexable documents
ids = group.select { |d| !ms_indexable?(d, options) }.map { |d| ms_primary_key_of(d, options) }
- index.delete_documents(ids.select { |id| !id.blank? })
+ index.delete_documents(ids.select(&:present?))
# select only indexable documents
group = group.select { |d| ms_indexable?(d, options) }
end
documents = group.map do |d|
attributes = settings.get_attributes(d)
- unless attributes.class == Hash
- attributes = attributes.to_hash
- end
- attributes.merge ms_pk(options) => ms_primary_key_of(d, options)
+ attributes = attributes.to_hash unless attributes.instance_of?(Hash)
+ attributes.merge ms_pk(options) => ms_primary_key_of(d, options)
end
last_update= index.add_documents(documents)
end
- index.wait_for_pending_update(last_update["updateId"]) if last_update and (synchronous || options[:synchronous])
+ index.wait_for_pending_update(last_update['updateId']) if last_update && (synchronous || options[:synchronous])
end
nil
end
def ms_set_settings(synchronous = false)
@@ -478,41 +473,44 @@
final_settings = settings.to_settings
end
index = SafeIndex.new(ms_index_uid(options), true, options)
update = index.update_settings(final_settings)
- index.wait_for_pending_update(update["updateId"]) if synchronous
+ index.wait_for_pending_update(update['updateId']) if synchronous
end
end
def ms_index_documents(documents, synchronous = false)
ms_configurations.each do |options, settings|
next if ms_indexing_disabled?(options)
+
index = ms_ensure_init(options, settings)
update = index.add_documents(documents.map { |d| settings.get_attributes(d).merge ms_pk(options) => ms_primary_key_of(d, options) })
- index.wait_for_pending_update(update["updateId"]) if synchronous || options[:synchronous]
+ index.wait_for_pending_update(update['updateId']) if synchronous || options[:synchronous]
end
end
def ms_index!(document, synchronous = false)
return if ms_without_auto_index_scope
+
ms_configurations.each do |options, settings|
next if ms_indexing_disabled?(options)
+
primary_key = ms_primary_key_of(document, options)
index = ms_ensure_init(options, settings)
if ms_indexable?(document, options)
- raise ArgumentError.new("Cannot index a record without a primary key") if primary_key.blank?
+ raise ArgumentError, 'Cannot index a record without a primary key' if primary_key.blank?
+
+ doc = settings.get_attributes(document)
+ doc = doc.merge ms_pk(options) => primary_key
+
if synchronous || options[:synchronous]
- doc = settings.get_attributes(document)
- doc = doc.merge ms_pk(options) => primary_key
index.add_documents!(doc)
else
- doc = settings.get_attributes(document)
- doc = doc.merge ms_pk(options) => primary_key
index.add_documents(doc)
end
- elsif ms_conditional_index?(options) && !primary_key.blank?
+ elsif ms_conditional_index?(options) && primary_key.present?
# remove non-indexable documents
if synchronous || options[:synchronous]
index.delete_document!(primary_key)
else
index.delete_document(primary_key)
@@ -522,14 +520,17 @@
nil
end
def ms_remove_from_index!(document, synchronous = false)
return if ms_without_auto_index_scope
+
primary_key = ms_primary_key_of(document)
- raise ArgumentError.new("Cannot index a record without a primary key") if primary_key.blank?
+ raise ArgumentError, 'Cannot index a record without a primary key' if primary_key.blank?
+
ms_configurations.each do |options, settings|
next if ms_indexing_disabled?(options)
+
index = ms_ensure_init(options, settings)
if synchronous || options[:synchronous]
index.delete_document!(primary_key)
else
index.delete_document(primary_key)
@@ -539,36 +540,40 @@
end
def ms_clear_index!(synchronous = false)
ms_configurations.each do |options, settings|
next if ms_indexing_disabled?(options)
+
index = ms_ensure_init(options, settings)
synchronous || options[:synchronous] ? index.delete_all_documents! : index.delete_all_documents
@ms_indexes[settings] = nil
end
nil
end
def ms_raw_search(q, params = {})
- index_uid = params.delete(:index) ||
- params.delete('index')
+ index_uid = params.delete(:index) || params.delete('index')
- if !meilisearch_settings.get_setting(:attributesToHighlight).nil?
+ unless meilisearch_settings.get_setting(:attributesToHighlight).nil?
params[:attributesToHighlight] = meilisearch_settings.get_setting(:attributesToHighlight)
end
- if !meilisearch_settings.get_setting(:attributesToCrop).nil?
+ unless meilisearch_settings.get_setting(:attributesToCrop).nil?
params[:attributesToCrop] = meilisearch_settings.get_setting(:attributesToCrop)
- params[:cropLength] = meilisearch_settings.get_setting(:cropLength) if !meilisearch_settings.get_setting(:cropLength).nil?
+
+ unless meilisearch_settings.get_setting(:cropLength).nil?
+ params[:cropLength] = meilisearch_settings.get_setting(:cropLength)
+ end
end
+
index = ms_index(index_uid)
- index.search(q, Hash[params.map { |k,v| [k, v] }])
+ index.search(q, params.map { |k, v| [k, v] }.to_h)
end
module AdditionalMethods
def self.extended(base)
- class <<base
+ class << base
alias_method :raw_answer, :ms_raw_answer unless method_defined? :raw_answer
alias_method :facets_distribution, :ms_facets_distribution unless method_defined? :facets_distribution
end
end
@@ -579,16 +584,17 @@
def ms_facets_distribution
@ms_json['facetsDistribution']
end
private
+
def ms_init_raw_answer(json)
@ms_json = json
end
end
- def ms_search(q, params = {})
+ def ms_search(query, params = {})
if MeiliSearch.configuration[:pagination_backend]
page = params[:page].nil? ? params[:page] : params[:page].to_i
hits_per_page = params[:hitsPerPage].nil? ? params[:hitsPerPage] : params[:hitsPerPage].to_i
@@ -596,32 +602,33 @@
params.delete(:hitsPerPage)
params[:limit] = 200
end
# Returns raw json hits as follows:
- # {"hits"=>[{"id"=>"13", "href"=>"apple", "name"=>"iphone"}], "offset"=>0, "limit"=>|| 20, "nbHits"=>1, "exhaustiveNbHits"=>false, "processingTimeMs"=>0, "query"=>"iphone"}
- json = ms_raw_search(q, params)
+ # {"hits"=>[{"id"=>"13", "href"=>"apple", "name"=>"iphone"}], "offset"=>0, "limit"=>|| 20, "nbHits"=>1,
+ # "exhaustiveNbHits"=>false, "processingTimeMs"=>0, "query"=>"iphone"}
+ json = ms_raw_search(query, params)
# Returns the ids of the hits: 13
hit_ids = json['hits'].map { |hit| hit[ms_pk(meilisearch_options).to_s] }
# condition_key gets the primary key of the document; looks for "id" on the options
- if defined?(::Mongoid::Document) && self.include?(::Mongoid::Document)
- condition_key = ms_primary_key_method.in
- else
- condition_key = ms_primary_key_method
- end
+ condition_key = if defined?(::Mongoid::Document) && include?(::Mongoid::Document)
+ ms_primary_key_method.in
+ else
+ ms_primary_key_method
+ end
# meilisearch_options[:type] refers to the Model name (e.g. Product)
- # results_by_id creates a hash with the primaryKey of the document (id) as the key and the document itself as the value
- # {"13"=>#<Product id: 13, name: "iphone", href: "apple", tags: nil, type: nil, description: "Puts even more features at your fingertips", release_date: nil>}
+ # results_by_id creates a hash with the primaryKey of the document (id) as the key and doc itself as the value
+ # {"13"=>#<Product id: 13, name: "iphone", href: "apple", tags: nil, type: nil,
+ # description: "Puts even more features at your fingertips", release_date: nil>}
results_by_id = meilisearch_options[:type].where(condition_key => hit_ids).index_by do |hit|
ms_primary_key_of(hit)
end
results = json['hits'].map do |hit|
-
o = results_by_id[hit[ms_pk(meilisearch_options).to_s].to_s]
if o
o.formatted = hit['_formatted']
o
end
@@ -629,40 +636,42 @@
total_hits = json['hits'].length
hits_per_page ||= 20
page ||= 1
- res = MeiliSearch::Pagination.create(results, total_hits, meilisearch_options.merge({ page: page , per_page: hits_per_page }))
+ res = MeiliSearch::Pagination.create(results, total_hits, meilisearch_options.merge(page: page, per_page: hits_per_page))
res.extend(AdditionalMethods)
res.send(:ms_init_raw_answer, json)
res
end
def ms_index(name = nil)
if name
ms_configurations.each do |o, s|
return ms_ensure_init(o, s) if o[:index_uid].to_s == name.to_s
end
- raise ArgumentError.new("Invalid index name: #{name}")
+ raise ArgumentError, "Invalid index name: #{name}"
end
ms_ensure_init
end
def ms_index_uid(options = nil)
options ||= meilisearch_options
name = options[:index_uid] || model_name.to_s.gsub('::', '_')
- name = "#{name}_#{Rails.env.to_s}" if options[:per_environment]
+ name = "#{name}_#{Rails.env}" if options[:per_environment]
name
end
def ms_must_reindex?(document)
# use +ms_dirty?+ method if implemented
- return document.send(:ms_dirty?) if (document.respond_to?(:ms_dirty?))
+ return document.send(:ms_dirty?) if document.respond_to?(:ms_dirty?)
+
# Loop over each index to see if a attribute used in records has changed
ms_configurations.each do |options, settings|
next if ms_indexing_disabled?(options)
return true if ms_primary_key_changed?(document, options)
+
settings.get_attribute_names(document).each do |k|
return true if ms_attribute_changed?(document, k)
# return true if !document.respond_to?(changed_method) || document.send(changed_method)
end
[options[:if], options[:unless]].each do |condition|
@@ -676,29 +685,30 @@
# let's always reindex then
return true
end
end
end
+
# By default, we don't reindex
- return false
+ false
end
protected
def ms_ensure_init(options = nil, settings = nil, index_settings = nil)
- raise ArgumentError.new('No `meilisearch` block found in your model.') if meilisearch_settings.nil?
+ raise ArgumentError, 'No `meilisearch` block found in your model.' if meilisearch_settings.nil?
@ms_indexes ||= {}
options ||= meilisearch_options
settings ||= meilisearch_settings
return @ms_indexes[settings] if @ms_indexes[settings]
@ms_indexes[settings] = SafeIndex.new(ms_index_uid(options), meilisearch_options[:raise_on_failure], meilisearch_options)
- current_settings = @ms_indexes[settings].settings(:getVersion => 1) rescue nil # if the index doesn't exist
+ current_settings = @ms_indexes[settings].settings(getVersion: 1) rescue nil # if the index doesn't exist
index_settings ||= settings.to_settings
index_settings = options[:primary_settings].to_settings.merge(index_settings) if options[:inherit]
options[:check_settings] = true if options[:check_settings].nil?
@@ -711,21 +721,22 @@
end
private
def ms_configurations
- raise ArgumentError.new('No `meilisearch` block found in your model.') if meilisearch_settings.nil?
+ raise ArgumentError, 'No `meilisearch` block found in your model.' if meilisearch_settings.nil?
+
if @configurations.nil?
@configurations = {}
@configurations[meilisearch_options] = meilisearch_settings
- meilisearch_settings.additional_indexes.each do |k,v|
+ meilisearch_settings.additional_indexes.each do |k, v|
@configurations[k] = v
- if v.additional_indexes.any?
- v.additional_indexes.each do |options, index|
- @configurations[options] = index
- end
+ next unless v.additional_indexes.any?
+
+ v.additional_indexes.each do |options, index|
+ @configurations[options] = index
end
end
end
@configurations
end
@@ -748,17 +759,18 @@
options[:primary_key] || MeiliSearch::IndexSettings::DEFAULT_PRIMARY_KEY
end
def meilisearch_settings_changed?(prev, current)
return true if prev.nil?
+
current.each do |k, v|
prev_v = prev[k.to_s]
- if v.is_a?(Array) and prev_v.is_a?(Array)
+ if v.is_a?(Array) && prev_v.is_a?(Array)
# compare array of strings, avoiding symbols VS strings comparison
- return true if v.map { |x| x.to_s } != prev_v.map { |x| x.to_s }
- else
- return true if prev_v != v
+ return true if v.map(&:to_s) != prev_v.map(&:to_s)
+ elsif prev_v != v
+ return true
end
end
false
end
@@ -794,15 +806,15 @@
document.send(constraint.to_sym)
when Enumerable
# All constraints must pass
constraint.all? { |inner_constraint| ms_constraint_passes?(document, inner_constraint) }
else
- if constraint.respond_to?(:call) # Proc
- constraint.call(document)
- else
+ unless constraint.respond_to?(:call)
raise ArgumentError, "Unknown constraint type: #{constraint} (#{constraint.class})"
end
+
+ constraint.call(document)
end
end
def ms_indexing_disabled?(options = nil)
options ||= meilisearch_options
@@ -828,11 +840,11 @@
else
# don't worry, mongoid has its own underlying cursor/streaming mechanism
items = []
all.each do |item|
items << item
- if items.length % batch_size == 0
+ if (items.length % batch_size).zero?
yield items
items = []
end
end
yield items unless items.empty?
@@ -867,51 +879,56 @@
self.class.ms_remove_from_index!(self, synchronous || ms_synchronous?)
end
def ms_enqueue_remove_from_index!(synchronous)
if meilisearch_options[:enqueue]
- meilisearch_options[:enqueue].call(self, true) unless self.class.send(:ms_indexing_disabled?, meilisearch_options)
+ unless self.class.send(:ms_indexing_disabled?, meilisearch_options)
+ meilisearch_options[:enqueue].call(self, true)
+ end
else
ms_remove_from_index!(synchronous || ms_synchronous?)
end
end
def ms_enqueue_index!(synchronous)
if meilisearch_options[:enqueue]
- meilisearch_options[:enqueue].call(self, false) unless self.class.send(:ms_indexing_disabled?, meilisearch_options)
+ unless self.class.send(:ms_indexing_disabled?, meilisearch_options)
+ meilisearch_options[:enqueue].call(self, false)
+ end
else
ms_index!(synchronous)
end
end
- private
-
def ms_synchronous?
- @ms_synchronous == true
+ @ms_synchronous
end
+ private
+
def ms_mark_synchronous
@ms_synchronous = true
end
def ms_mark_for_auto_indexing
@ms_auto_indexing = true
end
def ms_mark_must_reindex
# ms_must_reindex flag is reset after every commit as part. If we must reindex at any point in
- # a stransaction, keep flag set until it is explicitly unset
+ # a transaction, keep flag set until it is explicitly unset
@ms_must_reindex ||=
- if defined?(::Sequel) && is_a?(Sequel::Model)
- new? || self.class.ms_must_reindex?(self)
- else
- new_record? || self.class.ms_must_reindex?(self)
- end
+ if defined?(::Sequel) && is_a?(Sequel::Model)
+ new? || self.class.ms_must_reindex?(self)
+ else
+ new_record? || self.class.ms_must_reindex?(self)
+ end
true
end
def ms_perform_index_tasks
return if !@ms_auto_indexing || @ms_must_reindex == false
+
ms_enqueue_index!(ms_synchronous?)
remove_instance_variable(:@ms_auto_indexing) if instance_variable_defined?(:@ms_auto_indexing)
remove_instance_variable(:@ms_synchronous) if instance_variable_defined?(:@ms_synchronous)
remove_instance_variable(:@ms_must_reindex) if instance_variable_defined?(:@ms_must_reindex)
end