Module: Webhookdb::Postgres::ModelUtilities::InstanceMethods
- Defined in:
- lib/webhookdb/postgres/model_utilities.rb
Instance Method Summary collapse
-
#after_create ⇒ Object
Sequel hook – send an asynchronous event after the model is saved.
-
#after_destroy ⇒ Object
Sequel hook – send an event after a transaction that destroys the object is committed.
-
#after_update ⇒ Object
Sequel hook – send an asynchronous event after the save is committed.
-
#error_messages ⇒ Object
Return the objects validation errors as full messages joined with commas.
-
#event_prefix ⇒ Object
Return the string used as a topic for events sent from the receiving object.
-
#inspect ⇒ Object
Return a human-readable representation of the object as a String suitable for debugging.
- #inspect_time(t) ⇒ Object
-
#lock? ⇒ Boolean
Run a SELECT FOR UPDATE SKIP LOCKED.
-
#publish_deferred(type, *payload) ⇒ Object
Publish an event in the current db’s/transaction’s
after_commit
hook. -
#publish_immediate(type, *payload) ⇒ Object
Publish an event from the receiving object of the specified
type
and with the givenpayload
. -
#resource_lock! ⇒ Object
Take an exclusive lock on the receiver, ensuring nothing else has updated the object in the meantime.
Instance Method Details
#after_create ⇒ Object
Sequel hook – send an asynchronous event after the model is saved.
333 334 335 336 |
# File 'lib/webhookdb/postgres/model_utilities.rb', line 333 def after_create super self.publish_deferred("created", self.id, prep_amigo_payload(self.values)) end |
#after_destroy ⇒ Object
Sequel hook – send an event after a transaction that destroys the object is committed.
345 346 347 348 |
# File 'lib/webhookdb/postgres/model_utilities.rb', line 345 def after_destroy super self.publish_deferred("destroyed", self.id, prep_amigo_payload(self.values)) end |
#after_update ⇒ Object
Sequel hook – send an asynchronous event after the save is committed.
339 340 341 342 |
# File 'lib/webhookdb/postgres/model_utilities.rb', line 339 def after_update super self.publish_deferred("updated", self.id, prep_amigo_payload(self.previous_changes)) end |
#error_messages ⇒ Object
Return the objects validation errors as full messages joined with commas.
252 253 254 |
# File 'lib/webhookdb/postgres/model_utilities.rb', line 252 def return self.errors..join(", ") end |
#event_prefix ⇒ Object
Return the string used as a topic for events sent from the receiving object.
257 258 259 260 |
# File 'lib/webhookdb/postgres/model_utilities.rb', line 257 def event_prefix prefix = self.class.name or return # No events for anonymous classes return prefix.gsub("::", ".").downcase end |
#inspect ⇒ Object
Return a human-readable representation of the object as a String suitable for debugging.
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/webhookdb/postgres/model_utilities.rb', line 202 def inspect values = self.values.reject do |k, v| v.blank? || k.to_s.end_with?("_currency") end begin encrypted = self.class.send(:column_encryption_metadata).to_set { |(col, _)| col.to_s } rescue NoMethodError encrypted = Set.new end values = values.map do |(k, v)| k = k.to_s v = if v.is_a?(Time) self.inspect_time(v) elsif v.respond_to?(:db_type) && v.db_type.to_s == "tstzrange" "%s%s...%s%s" % [ v.exclude_begin? ? "(" : "[", v.begin ? self.inspect_time(v.begin) : "nil", v.end ? self.inspect_time(v.end) : "nil", v.exclude_end? ? ")" : "]", ] elsif k.end_with?("_cents") accessor = k.match(/^([a-z_]+)_cents/)[1] k = accessor self.send(accessor).format elsif encrypted.include?(k) # Render encrypted fields as xyz...abc, or if a URL, hide the user/password. unenc = self.send(k) if unenc.length < 10 "\"...\"" elsif unenc.include?("://") uri = URI(unenc) uri.user = "*" uri.password = "*" uri.to_s.inspect else "\"#{unenc[..2]}...#{unenc[-3..]}\"" end else v.inspect end "#{k}: #{v}" end return "#<%p %s>" % [self.class, values.join(", ")] end |
#inspect_time(t) ⇒ Object
247 248 249 |
# File 'lib/webhookdb/postgres/model_utilities.rb', line 247 def inspect_time(t) return t.in_time_zone(Time.zone).strftime("%Y-%m-%d %H:%M:%S") end |
#lock? ⇒ Boolean
Run a SELECT FOR UPDATE SKIP LOCKED. If the model row is already locked, return false. Otherwise, acquire the lock and return true.
If the lock is acquired, callers may want to refresh the receiver to make sure it has the newest values.
300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/webhookdb/postgres/model_utilities.rb', line 300 def lock? raise Webhookdb::LockFailed, "must be in a transaction" unless self.db.in_transaction? pk = self[self.class.primary_key] got_lock = self.class.dataset. select(1). where(self.class.primary_key => pk). for_update. skip_locked. first return !got_lock.nil? end |
#publish_deferred(type, *payload) ⇒ Object
Publish an event in the current db’s/transaction’s after_commit
hook.
271 272 273 274 275 |
# File 'lib/webhookdb/postgres/model_utilities.rb', line 271 def publish_deferred(type, *payload) Webhookdb::Postgres.defer_after_commit(self.db) do self.publish_immediate(type, *payload) end end |
#publish_immediate(type, *payload) ⇒ Object
Publish an event from the receiving object of the specified type
and with the given payload
. This does not wait for the transaction to complete, so subscribers may not be able to observe any model changes in the database. You probably want to use published_deferred.
265 266 267 268 |
# File 'lib/webhookdb/postgres/model_utilities.rb', line 265 def publish_immediate(type, *payload) prefix = self.event_prefix or return Amigo.publish(prefix + "." + type.to_s, *payload) end |
#resource_lock! ⇒ Object
Take an exclusive lock on the receiver, ensuring nothing else has updated the object in the meantime. If the updated_at changed from what’s on the receiver, to after it acquired the lock, raise LockFailed. Save changes and touch updated_at after calling the given block.
280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/webhookdb/postgres/model_utilities.rb', line 280 def resource_lock! self.db.transaction do old_updated = self.round_time(self.updated_at) self.lock! new_updated = self.round_time(self.updated_at) raise Webhookdb::LockFailed if old_updated != new_updated result = yield(self) self.updated_at = Time.now self.save_changes return result end end |