mod/history/lib/card/change.rb
# -*- encoding : utf-8 -*-
require "activerecord-import"
class Card
# A _change_ is an alteration to a card's name, type, content, or trash state.
# Together, {Act acts}, {Action actions}, and {Change changes} comprise a
# comprehensive {Card card} history tracking system.
#
# For example, if a given web submission changes both the name and type of
# card, that would be recorded as one {Action action} with two
# {Change changes}.
#
# A {Change} records:
#
# * the _field_ changed
# * the new _value_ of that field
# * the {Action action} of which the change is part
#
class Change < Cardio::Record
belongs_to :action, foreign_key: :card_action_id,
inverse_of: :card_changes
# lists the database fields for which changes are recorded
TRACKED_FIELDS = %w[name type_id db_content trash left_id right_id].freeze
class << self
# delete all {Change changes} not associated with an {Action action}
# (janitorial)
def delete_actionless
joins(
"LEFT JOIN card_actions "\
"ON card_changes.card_action_id = card_actions.id "
).where(
"card_actions.id is null"
).pluck_in_batches(:id) do |group_ids|
# used to be .delete_all here, but that was failing on large dbs
Rails.logger.info "deleting batch of changes"
where("id in (#{group_ids.join ','})").delete_all
end
end
# Change fields are recorded as integers. #field_index looks up the
# integer associated with a given field name.
# @param value [String, Symbol]
# @return [Integer]
def field_index value
value.is_a?(Integer) ? value : TRACKED_FIELDS.index(value.to_s)
end
# look up changes based on field name
# @param value [String, Symbol]
# @return [Change]
def find_by_field_name value
find_by_field field_index(value)
end
end
# set field value (integer)
# @param value [String, Symbol]
def field= value
write_attribute(:field, TRACKED_FIELDS.index(value.to_s))
end
# retrieve field name
# @return [String]
def field
TRACKED_FIELDS[read_attribute(:field)]
end
end
end