Class: Tantot::Extensions::Chewy::ChewyWatcher

Inherits:
Object
  • Object
show all
Includes:
Watcher
Defined in:
lib/tantot/extensions/chewy.rb

Instance Method Summary collapse

Instance Method Details

#get_chewy_type(type_name) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/tantot/extensions/chewy.rb', line 72

def get_chewy_type(type_name)
  if type_name.is_a?(Proc)
    if type_name.arity.zero?
      instance_exec(&type_name)
    else
      type_name.call(self)
    end
  else
    type_name
  end
end

#get_ids_to_update(model, changes_by_id, method, options, block) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/tantot/extensions/chewy.rb', line 84

def get_ids_to_update(model, changes_by_id, method, options, block)
  if options.key?(:association)
    resolve_association(model, options[:association], changes_by_id)
  else
    if (method && method.to_sym == :self) || (!method && !block)
      # Simply extract keys from changes
      changes_by_id.keys
    elsif method
      # We need to call `method`.
      # Try to find it on the class. If so, call it once with all changes.
      # There is no API to call per-instance since objects can be already destroyed
      # when using the sidekiq performer
      model.send(method, changes_by_id)
    elsif block
      # Since we can be post-destruction of the model, we can't load models here
      # Thus, the signature of the block callback is |changes| which are all
      # the changes to all the models
      model.instance_exec(changes_by_id, &block)
    end
  end
end

#perform(changes_by_model) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/tantot/extensions/chewy.rb', line 51

def perform(changes_by_model)
  changes_by_model.each do |model, changes_by_id|
    model_watches = model._tantot_chewy_callbacks
    model_watches.each do |type_name, watches|
      # Find type
      reference = get_chewy_type(type_name)

      backreference = watches.flat_map {|method, options, block| get_ids_to_update(model, changes_by_id, method, options, block)}.compact
      if backreference
        # Make sure there are any backreferences
        if backreference.any?
          Tantot.logger.debug { "[Tantot] [Chewy] [update_index] #{reference} (#{backreference.count} objects): #{backreference.inspect}" }
          ::Chewy.derive_type(reference).update_index(backreference, {})
        end
      else
        # nothing to update
      end
    end
  end
end

#resolve_association(model, association, changes_by_id) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/tantot/extensions/chewy.rb', line 106

def resolve_association(model, association, changes_by_id)
  reflection = model.reflect_on_association(association)
  reflection.check_validity!
  case reflection.macro
  when :belongs_to
    changes_by_id.for_attribute(reflection.foreign_key)
  when :has_one, :has_many
    if reflection.options[:through]
      through_query =
        case reflection.through_reflection.macro
        when :belongs_to
          reflection.through_reflection.klass.where(reflection.through_reflection.klass.primary_key => changes_by_id.for_attribute(reflection.through_reflection.foreign_key))
        when :has_many, :has_one
          reflection.through_reflection.klass.where(reflection.through_reflection.foreign_key => changes_by_id.ids)
        end
      case reflection.source_reflection.macro
      when :belongs_to
        through_query.pluck(reflection.source_reflection.foreign_key)
      when :has_many
        reflection.source_reflection.klass.where(reflection.source_reflection.foreign_key => (through_query.ids)).ids
      end
    else
      reflection.klass.where(reflection.foreign_key => changes_by_id.ids).ids
    end
  end
end