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
75 76 77 78 79 80 81 82 |
# File 'lib/amigo/job.rb', line 75 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
192 193 194 |
# File 'lib/amigo/job.rb', line 192 def changed_at(field, index, values={}) return self.method(:match_change_at).to_proc.curry[field, index, values] end |
#initialize ⇒ Object
17 18 19 20 |
# File 'lib/amigo/job.rb', line 17 def initialize(*) super @change_matchers = {} end |
#logger ⇒ Object
22 23 24 |
# File 'lib/amigo/job.rb', line 22 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 )`
45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/amigo/job.rb', line 45 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
.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/amigo/job.rb', line 85 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
.
107 108 109 110 |
# File 'lib/amigo/job.rb', line 107 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.
202 203 204 205 206 207 208 209 |
# File 'lib/amigo/job.rb', line 202 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#==.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/amigo/job.rb', line 146 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#==.
173 174 175 176 177 178 179 |
# File 'lib/amigo/job.rb', line 173 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#==.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/amigo/job.rb', line 120 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
26 27 28 29 30 31 32 33 34 35 |
# File 'lib/amigo/job.rb', line 26 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.
215 216 217 218 219 220 221 222 223 |
# File 'lib/amigo/job.rb', line 215 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 |