Class: Primer::Worker::ActiveRecordAgent

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

Class Method Summary collapse

Class Method Details

.bind_to_busObject



5
6
7
8
9
10
11
12
13
14
# File 'lib/primer/worker/active_record_agent.rb', line 5

def self.bind_to_bus
  Primer.bus.subscribe :active_record do |event, class_name, attributes, changes|
    model = class_name.constantize.new(attributes)
    model.instance_eval do
      @attributes = attributes
      @changed_attributes = changes if changes
    end
    __send__("on_#{event}", model)
  end
end

.macrosObject



16
17
18
# File 'lib/primer/worker/active_record_agent.rb', line 16

def self.macros
  Watcher::ActiveRecordMacros
end

.mirror_association(object_class, related_class, macro) ⇒ Object



110
111
112
113
114
115
# File 'lib/primer/worker/active_record_agent.rb', line 110

def self.mirror_association(object_class, related_class, macro)
  related_class.reflect_on_all_associations.find do |mirror_assoc|
    mirror_assoc.macro == macro and
    mirror_assoc.class_name == object_class.name
  end
end

.notify_attributes(model, fields) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/primer/worker/active_record_agent.rb', line 33

def self.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



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

def self.notify_belongs_to_association(model, assoc_name, change = nil)
  assoc = model.class.reflect_on_association(assoc_name)
  owner_class = assoc.class_name.constantize
  
  mirror = mirror_association(model.class, owner_class, :has_many)
  
  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?
  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

.notify_belongs_to_associations(model) ⇒ Object



45
46
47
48
49
50
# File 'lib/primer/worker/active_record_agent.rb', line 45

def self.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



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/primer/worker/active_record_agent.rb', line 72

def self.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)
    klass    = assoc.class_name.constantize
    related  = klass.find(:all, :conditions => {assoc.primary_key_name => model_id})
    
    related.each do |object|
      mirror = mirror_association(model.class, object.class, :belongs_to)
      next unless mirror
      
      Primer.bus.publish(:changes, object.primer_identifier + [mirror.name.to_s])
    end
  end
end

.notify_has_many_through_association(model, through_name) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/primer/worker/active_record_agent.rb', line 90

def self.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.class_name.constantize.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_create(model) ⇒ Object



20
21
22
# File 'lib/primer/worker/active_record_agent.rb', line 20

def self.on_create(model)
  notify_belongs_to_associations(model)
end

.on_destroy(model) ⇒ Object



28
29
30
31
# File 'lib/primer/worker/active_record_agent.rb', line 28

def self.on_destroy(model)
  notify_attributes(model, model.attributes)
  notify_has_many_associations(model)
end

.on_update(model) ⇒ Object



24
25
26
# File 'lib/primer/worker/active_record_agent.rb', line 24

def self.on_update(model)
  notify_attributes(model, model.changes)
end