Module: FullSearch::Callbacks

Extended by:
Quoting
Defined in:
lib/full_search/callbacks.rb

Class Method Summary collapse

Class Method Details

.associated_class(model, association_name) ⇒ Object



110
111
112
113
# File 'lib/full_search/callbacks.rb', line 110

def self.associated_class(model, association_name)
  reflection = model.reflect_on_association(association_name.to_sym)
  reflection&.klass
end

.association_key(model, association_name) ⇒ Object



115
116
117
118
# File 'lib/full_search/callbacks.rb', line 115

def self.association_key(model, association_name)
  reflection = model.reflect_on_association(association_name.to_sym)
  reflection&.foreign_key&.to_s || "#{association_name}_id"
end

.connectionObject



106
107
108
# File 'lib/full_search/callbacks.rb', line 106

def self.connection
  ActiveRecord::Base.connection
end

.connection_for(klass) ⇒ Object



120
121
122
123
124
# File 'lib/full_search/callbacks.rb', line 120

def self.connection_for(klass)
  klass.connection
rescue NoMethodError
  ActiveRecord::Base.connection
end

.install!(model) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/full_search/callbacks.rb', line 7

def self.install!(model)
  return if model.instance_variable_get(:@__full_search_callbacks_installed)

  dsl = model.full_search_dsl

  source_fields = dsl.fields.select(&:source)
  return if source_fields.empty?

  model.after_save_commit do
    next if FullSearch.bulk_importing?(self.class)
    FullSearch::Callbacks.reindex_record!(self)
  end

  model.after_destroy_commit do
    next if FullSearch.bulk_importing?(self.class)
    FullSearch::Callbacks.remove_record!(self)
  end

  dsl.fields.each do |field|
    next unless field.reindex_on

    assoc_class = associated_class(model, field.reindex_on)
    assoc_class&.after_save_commit do |record|
      next if FullSearch.bulk_importing?(record.class)
      FullSearch::Callbacks.reindex_dependents!(record, model, field)
    end
    assoc_class&.after_destroy_commit do |record|
      next if FullSearch.bulk_importing?(record.class)
      FullSearch::Callbacks.reindex_dependents!(record, model, field)
    end
  end

  model.instance_variable_set(:@__full_search_callbacks_installed, true)
end

.reindex_dependents!(parent_record, dependent_model, field) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/full_search/callbacks.rb', line 85

def self.reindex_dependents!(parent_record, dependent_model, field)
  fk = association_key(dependent_model, field.reindex_on)
  conn = connection_for(dependent_model)
  sql = "SELECT id FROM #{qt(dependent_model.table_name)} WHERE #{qc(fk)} = #{q(parent_record.id)}"
  dependent_ids = conn.execute(sql).map { |r| r["id"] }

  return if dependent_ids.empty?

  if field.async
    dependent_ids.each { |id| FullSearch::ReindexJob.perform_later(dependent_model.name, id, field.name) }
  else
    dependent_model.where(id: dependent_ids).find_each(batch_size: 500) do |record|
      reindex_field!(record, field.name)
    end
  end
end

.reindex_field!(record, field_name) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/full_search/callbacks.rb', line 62

def self.reindex_field!(record, field_name)
  dsl = record.class.full_search_dsl
  field = dsl.fields.find { |f| f.name == field_name }
  return unless field&.source

  value = FullSearch::Model.evaluate_source(record, field)
  table = qt(FullSearch::Index.fts_table_name(record.class))
  conn = connection_for(record.class)
  conn.execute(
    "UPDATE #{table} SET #{qc(field.as || field.name)} = #{q(value.to_s)} WHERE rowid = #{q(record.id)}"
  )
rescue ActiveRecord::StatementInvalid => e
  raise_missing_table_or_original(e, record.class)
end

.reindex_record!(record) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/full_search/callbacks.rb', line 46

def self.reindex_record!(record)
  dsl = record.class.full_search_dsl
  return unless dsl

  model_name = record.class.name
  dsl.fields.each do |field|
    next unless field.source

    if model_name && field.async_source
      FullSearch::ReindexJob.perform_later(model_name, record.id, field.name)
    else
      reindex_field!(record, field.name)
    end
  end
end

.remove_record!(record) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/full_search/callbacks.rb', line 77

def self.remove_record!(record)
  table = qt(FullSearch::Index.fts_table_name(record.class))
  conn = connection_for(record.class)
  conn.execute("DELETE FROM #{table} WHERE rowid = #{q(record.id)}")
rescue ActiveRecord::StatementInvalid => e
  raise_missing_table_or_original(e, record.class)
end

.reset_installed_flag!(model) ⇒ Object



42
43
44
# File 'lib/full_search/callbacks.rb', line 42

def self.reset_installed_flag!(model)
  model.instance_variable_set(:@__full_search_callbacks_installed, false)
end