Module: Amigo::Job::InstanceMethods
- Defined in:
- lib/amigo/job.rb
Instance Method Summary collapse
-
#changed(field, values = {}) ⇒ Object
Create a matcher against the ‘changed’ hash of an update event.
-
#changed_at(field, index, values = {}) ⇒ Object
Create a matcher against a changed Hash JSON column of an update event.
- #initialize ⇒ Object
- #logger ⇒ Object
-
#lookup_model(klass, payload_or_id) ⇒ Object
Return
klass[payload_or_id]
if it exists, or raise an error if it does not. -
#make_match_proc_for(field, values) ⇒ Object
Make a curried Proc for calling a match method with the given
field
andvalues
. -
#match_any_change(field, changes) ⇒ Object
Returns
true
if the givenfield
is listed at all in the specifiedchanges
. -
#match_change_at(field, index, values, changes) ⇒ Object
Return
true
if ‘field` has changed in the specifiedchanges
, configured byvalues
(containsfrom
,to
, or whatever supported kwargs). -
#match_change_from(field, from, changes) ⇒ Object
Returns
true
if the givenfield
is listed in the specifiedchanges
, and the value it changed from matchesfrom
. -
#match_change_from_to(field, from, to, changes) ⇒ Object
Returns
true
if the givenfield
is listed in the specifiedchanges
, and the value it changed from matchesfrom
and the value it changed to matchesto
. -
#match_change_to(field, to, changes) ⇒ Object
Returns
true
if the givenfield
is listed in the specifiedchanges
, and the value it changed to matchesto
. - #perform(*args) ⇒ Object
-
#unroll_hash_changes(old_hash, new_hash) ⇒ Object
Given two hashes that represent the before and after column hash values, return a hash in the usual “changes” format, where keys are the hash keys with changed values, and values are a tuple of the before and after values.
Instance Method Details
#changed(field, values = {}) ⇒ Object
Create a matcher against the ‘changed’ hash of an update event.
Example:
on 'myapp.customer.update' do |payload, _|
customerid, changes, _ = *payload
customer = MyApp::Customer[ customerid ] or return false
case changes
when changed( :password )
send_password_change_email( customer )
when changed( :activation_code, to: nil )
send_welcome_email( customer )
when changed( :type, from: 'seeder', to: 'eater' )
send_becoming_an_eater_email( customer )
end
end
76 77 78 79 80 81 82 83 |
# File 'lib/amigo/job.rb', line 76 def changed(field, values={}) unless @change_matchers[[field, values]] match_proc = self.make_match_proc_for(field, values) @change_matchers[[field, values]] = match_proc end return @change_matchers[[field, values]] end |
#changed_at(field, index, values = {}) ⇒ Object
Create a matcher against a changed Hash JSON column of an update event.
Example:
on 'myapp.customer.update' do |payload, _|
customerid, changes, _ = *payload
case changes
when changed_at( :flags, :trustworthy, to: true )
mark_customer_safe_in_external_service( customerid )
end
end
193 194 195 |
# File 'lib/amigo/job.rb', line 193 def changed_at(field, index, values={}) return self.method(:match_change_at).to_proc.curry[field, index, values] end |
#initialize ⇒ Object
18 19 20 21 |
# File 'lib/amigo/job.rb', line 18 def initialize(*) super @change_matchers = {} end |
#logger ⇒ Object
23 24 25 |
# File 'lib/amigo/job.rb', line 23 def logger return Sidekiq.logger end |
#lookup_model(klass, payload_or_id) ⇒ Object
Return klass[payload_or_id]
if it exists, or raise an error if it does not. payload_or_id
can be an integer, or the async job payload if the id is the first argument.
Examples:
-
‘customer = self.lookup_model( MyApp::Customer, event )`
-
‘customer = self.lookup_model( MyApp::Customer, event.payload )`
-
‘customer = self.lookup_model( MyApp::Customer, customer_id )`
46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/amigo/job.rb', line 46 def lookup_model(klass, payload_or_id) if payload_or_id.is_a?(Integer) id = payload_or_id elsif payload_or_id.respond_to?(:payload) id = payload_or_id.payload.first elsif payload_or_id.respond_to?(:first) id = payload_or_id.first else raise "Don't know how to handle #{payload_or_id}" end result = klass[id] or raise "%s[%p] does not exist" % [klass.name, id] return result end |
#make_match_proc_for(field, values) ⇒ Object
Make a curried Proc for calling a match method with the given field
and values
.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/amigo/job.rb', line 86 def make_match_proc_for(field, values) return self.method(:match_any_change).to_proc.curry[field] if values.empty? if values.key?(:from) if values.key?(:to) return self.method(:match_change_from_to).to_proc. curry[ field, values[:from], values[:to] ] else return self.method(:match_change_from).to_proc. curry[ field, values[:from] ] end elsif values.key?(:to) return self.method(:match_change_to).to_proc. curry[ field, values[:to] ] else raise ScriptError, "Unhandled change option/s: %p; expected :to and/or :from" % [values.keys] end end |
#match_any_change(field, changes) ⇒ Object
Returns true
if the given field
is listed at all in the specified changes
.
108 109 110 111 |
# File 'lib/amigo/job.rb', line 108 def match_any_change(field, changes) self.logger.debug "Checking for existance of field %p in %p" % [field, changes] return changes&.key?(field.to_s) end |
#match_change_at(field, index, values, changes) ⇒ Object
Return true
if ‘field` has changed in the specified changes
, configured by values
(contains from
, to
, or whatever supported kwargs). Unlike other matches, changes
is expected to be an entire Hash
and may contain a value at index
in either or both sets of changes. This method does not attempt to do the matching itself. Rather, it sets up the data to defer to the other matcher methods.
203 204 205 206 207 208 209 210 |
# File 'lib/amigo/job.rb', line 203 def match_change_at(field, index, values, changes) field = field.to_s return false unless changes&.key?(field) index = index.to_s old_values, new_values = changes[field] unrolled_changes = self.unroll_hash_changes(old_values, new_values) return self.changed(index, values)[unrolled_changes] end |
#match_change_from(field, from, changes) ⇒ Object
Returns true
if the given field
is listed in the specified changes
, and the value it changed from matches from
. The from
value can be:
- a Regexp
-
The old value is stringified, and matched against the
from
Regexp. - an immediate value (String, Numeric, NilClass, etc.)
-
The old value is matched using Object#==.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/amigo/job.rb', line 147 def match_change_from(field, from, changes) self.logger.debug "Checking for change from %p of field %p in %p" % [from, field, changes] return false unless changes&.key?(field.to_s) oldval = changes[field.to_s][0] case from when NilClass, Numeric, String, TrueClass, FalseClass return oldval == from when Regexp return from.match(oldval) when Proc return from[oldval] else raise TypeError, "Unhandled type of 'from' criteria %p (a %p)" % [from, from.class] end end |
#match_change_from_to(field, from, to, changes) ⇒ Object
Returns true
if the given field
is listed in the specified changes
, and the value it changed from matches from
and the value it changed to matches to
. The from
and to
values can be:
- a Regexp
-
The corresponding value is stringified, and matched against the Regexp.
- an immediate value (String, Numeric, NilClass, etc.)
-
The corresponding value is matched using Object#==.
174 175 176 177 178 179 180 |
# File 'lib/amigo/job.rb', line 174 def match_change_from_to(field, from, to, changes) self.logger.debug "Checking for change from %p to %p of field %p in %p" % [from, to, field, changes] return false unless changes&.key?(field.to_s) return self.match_change_to(field, to, changes) && self.match_change_from(field, from, changes) end |
#match_change_to(field, to, changes) ⇒ Object
Returns true
if the given field
is listed in the specified changes
, and the value it changed to matches to
. The to
value can be:
- a Regexp
-
The new value is stringified, and matched against the
to
Regexp. - an immediate value (String, Numeric, NilClass, etc.)
-
The new value is matched using Object#==.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/amigo/job.rb', line 121 def match_change_to(field, to, changes) self.logger.debug "Checking for change to %p of field %p in %p" % [to, field, changes] return false unless changes&.key?(field.to_s) newval = changes[field.to_s][1] case to when NilClass, Numeric, String, TrueClass, FalseClass return newval == to when Regexp return to.match(newval) when Proc return to[newval] else raise TypeError, "Unhandled type of 'to' criteria %p (a %p)" % [to, to.class] end end |
#perform(*args) ⇒ Object
27 28 29 30 31 32 33 34 35 36 |
# File 'lib/amigo/job.rb', line 27 def perform(*args) if args.empty? event = nil elsif args.size == 1 event = Amigo::Event.from_json(args[0]) else raise "perform should always be called with no args or [Amigo::Event#as_json], got %p" % [args] end self._perform(event) end |
#unroll_hash_changes(old_hash, new_hash) ⇒ Object
Given two hashes that represent the before and after column hash values, return a hash in the usual “changes” format, where keys are the hash keys with changed values, and values are a tuple of the before and after values.
216 217 218 219 220 221 222 223 224 |
# File 'lib/amigo/job.rb', line 216 def unroll_hash_changes(old_hash, new_hash) old_hash ||= {} new_hash ||= {} return old_hash.keys.concat(new_hash.keys).uniq.each_with_object({}) do |key, h| old_val = old_hash[key] new_val = new_hash[key] h[key] = [old_val, new_val] if old_val != new_val end end |