module Ddr module Events class Event < ActiveRecord::Base # ActiveSupport::Notifications::Instrumenter sets payload[:exception] # to an array of [, ] # and we want to store this data in a string field. serialize :exception, JSON # Event date time - for PREMIS and Solr DATE_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%LZ" # set default ordering DEFAULT_SORT_ORDER = "event_date_time ASC" default_scope { order(DEFAULT_SORT_ORDER) } # Outcomes SUCCESS = "success" FAILURE = "failure" OUTCOMES = [SUCCESS, FAILURE] # Validation constants VALID = "VALID" INVALID = "INVALID" # For rendering "performed by" when no associated user SYSTEM = "SYSTEM" DDR_SOFTWARE = "ddr-models #{Ddr::Models::VERSION}" class_attribute :description validates_presence_of :event_date_time, :pid validates :outcome, inclusion: {in: OUTCOMES, message: "\"%{value}\" is not a valid event outcome"} after_initialize :set_defaults before_save { failure! if exception.present? } # Receive message sent by ActiveSupport::Notifications def self.call(*args) notification = ActiveSupport::Notifications::Event.new(*args) payload = notification.payload.dup payload[:event_date_time] ||= notification.time create do |event| event.attributes = payload.select { |k, v| event.has_attribute?(k) } yield [event, notification] if block_given? end end # Repository software version -- e.g., "Fedora Repository 3.7.0" def self.repository_software @@repository_software ||= ActiveFedora::Base.connection_for_pid(0).repository_profile .values_at(:repositoryName, :repositoryVersion) .join(" ") end def self.for_object(obj) for_pid(obj.pid) end def self.for_pid(pid) where(pid: pid) end def display_type # Ddr::Events::UpdateEvent => "Update" @display_type ||= self.class.to_s.split("::").last.sub("Event", "").titleize end def performed_by user_key || SYSTEM end def comment_or_summary comment.present? ? comment : summary end def success! self.outcome = SUCCESS end def success? outcome == SUCCESS end def failure! self.outcome = FAILURE end def failure? outcome == FAILURE end def object @object ||= ActiveFedora::Base.find(pid) if pid end def object=(obj) raise ArgumentError, "Can't set to new object" if obj.new_record? self.pid = obj.pid @object = obj end # Override pid setter to clear cached object instance variable def pid=(pid) @object = nil super end # Return a date/time formatted as a string suitable for use as a PREMIS eventDateTime. # Format also works for Solr. # Force to UTC. def event_date_time_s event_date_time.utc.strftime DATE_TIME_FORMAT end def user=(user) self.user_key = user.user_key end protected def set_defaults self.attributes = defaults.reject { |attr, val| attribute_present?(attr) } end def defaults { event_date_time: default_event_date_time, summary: default_summary, software: default_software, outcome: default_outcome } end def default_software DDR_SOFTWARE end def default_outcome SUCCESS end def default_summary description end def default_event_date_time Time.now.utc end end end end