Class: Primer::Worker::ActiveRecordAgent

Inherits:
Agent
  • Object
show all
Defined in:
lib/primer/worker/active_record_agent.rb

Instance Method Summary collapse

Methods inherited from Agent

run!, #run!, topic

Instance Method Details

#mirror_associations(model, association, macro) ⇒ Object



104
105
106
107
108
109
# File 'lib/primer/worker/active_record_agent.rb', line 104

def mirror_associations(model, association, macro)
  association.klass.reflect_on_all_associations.each do |mirror|
    yield(mirror) if mirror.klass == model.class and
                     mirror.macro == macro
  end
end

#notify_attributes(model, fields) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/primer/worker/active_record_agent.rb', line 27

def notify_attributes(model, fields)
  foreign_keys = model.class.primer_foreign_key_mappings
  
  fields.each do |attribute, value|
    Primer.bus.publish(:changes, model.primer_identifier + [attribute.to_s])
    
    next unless assoc = foreign_keys[attribute.to_s]
    Primer.bus.publish(:changes, model.primer_identifier + [assoc.to_s])
    notify_belongs_to_association(model, assoc, value)
  end
end

#notify_belongs_to_association(model, assoc_name, change = nil) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/primer/worker/active_record_agent.rb', line 46

def notify_belongs_to_association(model, assoc_name, change = nil)
  assoc = model.class.reflect_on_association(assoc_name)
  
  mirror_associations(model, assoc, :has_many) do |mirror|
    if owner = model.__send__(assoc_name)
      Primer.bus.publish(:changes, owner.primer_identifier + [mirror.name.to_s])
      notify_has_many_through_association(owner, mirror.name)
    end
    
    return unless Array === change and change.first.any?
    
    owner_class = assoc.klass
    old_id      = change.first.first
    previous    = owner_class.find(:first, :conditions => {owner_class.primary_key => old_id})
    
    return unless previous
    
    Primer.bus.publish(:changes, previous.primer_identifier + [mirror.name.to_s])
    notify_has_many_through_association(previous, mirror.name)
  end
end

#notify_belongs_to_associations(model) ⇒ Object



39
40
41
42
43
44
# File 'lib/primer/worker/active_record_agent.rb', line 39

def notify_belongs_to_associations(model)
  model.class.reflect_on_all_associations.each do |assoc|
    next unless assoc.macro == :belongs_to
    notify_belongs_to_association(model, assoc.name)
  end
end

#notify_has_many_associations(model) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/primer/worker/active_record_agent.rb', line 68

def notify_has_many_associations(model)
  model.class.reflect_on_all_associations.each do |assoc|
    next unless assoc.macro == :has_many
    next if assoc.options[:dependent] == :destroy
    
    model_id = model.__send__(model.class.primary_key)
    related  = assoc.klass.find(:all, :conditions => {assoc.primary_key_name => model_id})
    
    related.each do |object|
      mirror_associations(model, assoc, :belongs_to) do |mirror|
        Primer.bus.publish(:changes, object.primer_identifier + [mirror.name.to_s])
      end
    end
  end
end

#notify_has_many_through_association(model, through_name) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/primer/worker/active_record_agent.rb', line 84

def notify_has_many_through_association(model, through_name)
  model.class.reflect_on_all_associations.each do |assoc|
    next unless assoc.macro == :has_many
    
    if assoc.options[:through] == through_name
      Primer.bus.publish(:changes, model.primer_identifier + [assoc.name.to_s])
    end
    
    assoc.klass.reflect_on_all_associations.each do |secondary|
      next unless secondary.macro == :has_many and secondary.options[:through] and
                  secondary.source_reflection.active_record == model.class and
                  secondary.source_reflection.name == through_name
      
      model.__send__(assoc.name).each do |related|
        Primer.bus.publish(:changes, related.primer_identifier + [secondary.name.to_s])
      end
    end
  end
end

#on_message(message) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/primer/worker/active_record_agent.rb', line 7

def on_message(message)
  event, class_name, attributes, changes = *message
  model = class_name.constantize.new(attributes)
  
  model.instance_eval do
    @attributes = attributes
    @changed_attributes = changes if changes
  end
  
  case event
    when 'create'
      notify_belongs_to_associations(model)
    when 'update'
      notify_attributes(model, model.changes)
    when 'destroy'
      notify_attributes(model, model.attributes)
      notify_has_many_associations(model)
  end
end