class ActiveRecord::Associations::Builder::Association

Public Class Methods

define_callbacks(model, reflection) click to toggle source

This method monkeypatches ActiveRecord define_callbacks to add reindex callbacks if corresponding option specified if reindex; true - add syncronous callback to reindex associated records if reindex: :async - add asyncronous callback to reindex associated records

# File lib/activerecord_reindex/association.rb, line 38
def define_callbacks(model, reflection)
  original_define_callbacks(model, reflection)
  if reflection.reindex_sync?
    add_reindex_callback(model, reflection, async: false)
    model.sync_reindexable_reflections += [reflection]
  elsif reflection.reindex_async?
    add_reindex_callback(model, reflection, async: true)
    model.async_reindexable_reflections += [reflection]
  end
end
Also aliased as: original_define_callbacks
original_define_callbacks(model, reflection)
Alias for: define_callbacks
original_valid_options_ar_reindex(*args)
Alias for: valid_options
valid_options(*args) click to toggle source

This method monkey patches ActiveRecord valid_options to add one more valid option :reindex Examples:

belongs_to :tag, reindex: true
belongs_to :tagging, reindex: :async
has_many :tags, reindex: async
has_many :tags, through: :taggings, reindex: true
# File lib/activerecord_reindex/association.rb, line 28
def valid_options(*args)
  original_valid_options_ar_reindex(*args) + [:reindex]
end

Private Class Methods

add_destroy_reindex_callback(model, reflection, async:) click to toggle source

add callback to reindex associated records on destroy if association has dependent: :destroy or dependent: :delete_all we skip this callback since destroyed records should reindex themselves

# File lib/activerecord_reindex/association.rb, line 61
def add_destroy_reindex_callback(model, reflection, async:)
  return if [:destroy, :delete_all].include? reflection.options[:dependent]

  destroy_callback = callback(async, reflection)

  model.after_commit(on: :destroy) do
    destroy_callback.call(self)
  end
end
add_reindex_callback(model, reflection, async:) click to toggle source

manages adding of callbacks considering async option

# File lib/activerecord_reindex/association.rb, line 52
def add_reindex_callback(model, reflection, async:)
  add_destroy_reindex_callback(model, reflection, async: async)

  add_update_reindex_callback(model, reflection, async: async)
end
add_update_reindex_callback(model, reflection, async:) click to toggle source

add callback to reindex associations on update if model inherited from Elasticsearch::Model it means it have own index in elasticsearch and therefore should reindex itself on update those triggering update_document hook to prevent double reindex we're not adding update callback on such models

# File lib/activerecord_reindex/association.rb, line 75
def add_update_reindex_callback(model, reflection, async:)
  return if model < Elasticsearch::Model

  # for why it is needed see reindex_hook.rb
  model.include ActiverecordReindex::ReindexHook

  update_callback = callback(async, reflection)

  model.after_commit(on: :update) do
    next unless changed_index_relevant_attributes?
    update_callback.call(self)
  end
end
callback(async, reflection) click to toggle source

callback methods defined in ActiveRecord::Base monkeypatch

# File lib/activerecord_reindex/association.rb, line 90
def callback(async, reflection)
  async ? ->(record) { record.reindex_async(reflection) } : ->(record) { record.reindex_sync(reflection) }
end