Module: Jason::Publisher

Extended by:
ActiveSupport::Concern
Defined in:
lib/jason/publisher.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.cache_allObject

Warning: Could be expensive. Mainly useful for rebuilding cache after changing Jason config or on deploy



5
6
7
8
9
10
11
# File 'lib/jason/publisher.rb', line 5

def self.cache_all
  Rails.application.eager_load!
  ActiveRecord::Base.descendants.each do |klass|
    $redis_jason.del("jason:cache:#{klass.name.underscore}")
    klass.cache_all if klass.respond_to?(:cache_all)
  end
end

Instance Method Details

#cache_jsonObject



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/jason/publisher.rb', line 13

def cache_json
  as_json_config = api_model.as_json_config
  scope = api_model.scope

  # Exists
  if self.persisted? && (scope.blank? || self.class.unscoped.send(scope).exists?(self.id))
    payload = self.as_json(as_json_config)
    gidx = Jason::LuaGenerator.new.cache_json(self.class.name.underscore, self.id, payload)
    return [payload, gidx]
  # Has been destroyed
  else
    $redis_jason.hdel("jason:cache:#{self.class.name.underscore}", self.id)
    return []
  end
end

#force_publish_jsonObject



29
30
31
32
# File 'lib/jason/publisher.rb', line 29

def force_publish_json
  # As-if newly created
  publish_json(self.attributes.map { |k,v| [k, [nil, v]] }.to_h)
end

#jason_cached_valueObject



126
127
128
# File 'lib/jason/publisher.rb', line 126

def jason_cached_value
  JSON.parse($redis_jason.get("jason:cache:#{self.class.name.underscore}:#{id}") || '{}')
end

#jason_conditionsObject



122
123
124
# File 'lib/jason/publisher.rb', line 122

def jason_conditions
  Jason::Subscription.conditions_for_model(self.class.name.underscore)
end

#jason_subscriptionsObject



118
119
120
# File 'lib/jason/publisher.rb', line 118

def jason_subscriptions
  Jason::Subscription.for_instance(self.class.name.underscore, id)
end

#publish_json(previous_changes = {}) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/jason/publisher.rb', line 34

def publish_json(previous_changes = {})
  payload, gidx = cache_json

  return if skip_publish_json
  subs = jason_subscriptions # Get this first, because could be changed

  # Situations where IDs may need to change and this can't be immediately determined
  # - An instance is created where it belongs_to an instance under a subscription
  # - An instance belongs_to association changes - e.g. comment.post_id changes to/from one with a subscription
  # - TODO: The value of an instance changes so that it enters/leaves a subscription

  # TODO: Optimize this, by caching associations rather than checking each time instance is saved
  jason_assocs = self.class.reflect_on_all_associations(:belongs_to)
    .reject { |assoc| assoc.polymorphic? } # Can't get the class name of a polymorphic association, by
    .select { |assoc| assoc.klass.respond_to?(:has_jason?) }
  jason_assocs.each do |assoc|
    if previous_changes[assoc.foreign_key].present?
      Jason::Subscription.update_ids(
        self.class.name.underscore,
        id,
        assoc.name.to_s.singularize,
        previous_changes[assoc.foreign_key][0],
        previous_changes[assoc.foreign_key][1]
      )
    elsif (persisted? && @was_a_new_record && send(assoc.foreign_key).present?)
      Jason::Subscription.update_ids(
        self.class.name.underscore,
        id,
        assoc.name.to_s.singularize,
        nil,
        send(assoc.foreign_key)
      )
    end
  end

  if !persisted? # Deleted
    Jason::Subscription.remove_ids(
      self.class.name.underscore,
      [id]
     )
  end

  if persisted?
    applied_sub_ids = []

    jason_conditions.each do |row|
      matches = row['conditions'].map do |key, rules|
        Jason::ConditionsMatcher.new(self.class).test_match(key, rules, previous_changes)
      end
      next if matches.all? { |m| m.nil? } # None of the keys were in previous changes - therefore this condition does not apply
      in_sub = matches.all? { |m| m }

      if in_sub
        row['subscription_ids'].each do |sub_id|
          Jason::Subscription.find_by_id(sub_id).add_id(self.class.name.underscore, self.id)
          applied_sub_ids.push(sub_id)
        end
      else
        row['subscription_ids'].each do |sub_id|
          jason_subscriptions.each do |already_sub_id|
            # If this sub ID already has this instance, remove it
            if already_sub_id == sub_id
              sub = Jason::Subscription.find_by_id(already_sub_id)
              sub.remove_id(self.class.name.underscore, self.id)
              applied_sub_ids.push(already_sub_id)
            end
          end
        end
      end
    end

    jason_subscriptions.each do |sub_id|
      next if applied_sub_ids.include?(sub_id)

      Jason::Subscription.new(id: sub_id).update(self.class.name.underscore, id, payload, gidx)
    end
  end
end

#publish_json_if_changedObject



113
114
115
116
# File 'lib/jason/publisher.rb', line 113

def publish_json_if_changed
  subscribed_fields = api_model.subscribed_fields
  publish_json(self.previous_changes) if (self.previous_changes.keys.map(&:to_sym) & subscribed_fields).present? || !self.persisted?
end