class Card::Action

An action is a group of {Card::Change changes} to a single {Card card} that is recorded during an {Card::Act act}. 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 a given card, that would be recorded as one {Action action} with two {Change changes}. If there are multiple cards changed, each card would have its own {Action action}, but the whole submission would still comprise just one single {Act act}.

An {Action} records:

Constants

TYPE_OPTIONS

these are the three possible values for action_type

Public Class Methods

all_viewable() click to toggle source
# File lib/card/action.rb, line 64
def all_viewable
  all_with_cards.where Query::CardQuery.viewable_sql
end
all_with_cards() click to toggle source
# File lib/card/action.rb, line 60
def all_with_cards
  joins :ar_card
end
cache() click to toggle source

cache object for actions @return [Card::Cache]

# File lib/card/action.rb, line 56
def cache
  Card::Cache[Action]
end
fetch(id) click to toggle source

retrieve action from cache if available @param id [id of Action] @return [Action, nil]

# File lib/card/action.rb, line 48
def fetch id
  cache.fetch id.to_s do
    where(id: id.to_i).take
  end
end

Public Instance Methods

action_type() click to toggle source

retrieve action_type (create, update, or delete) @return [Symbol]

# File lib/card/action.rb, line 106
def action_type
  return :draft if draft

  TYPE_OPTIONS[read_attribute(:action_type)]
end
action_type=(value) click to toggle source

assign action_type (create, update, or delete) @param value [Symbol] @return [Integer]

# File lib/card/action.rb, line 100
def action_type= value
  write_attribute :action_type, TYPE_OPTIONS.index(value)
end
all_changes() click to toggle source
# File lib/card/action.rb, line 157
def all_changes
  self.class.cache.fetch("#{id}-changes") do
    # using card_changes causes caching problem
    Card::Change.where(card_action_id: id).to_a
  end
end
card() click to toggle source

each action is associated with on and only one card @return [Card]

# File lib/card/action.rb, line 71
def card
  Card.fetch card_id, look_in_trash: true

  # I'm not sure what the rationale for the following was/is, but it was causing
  # problems in cases where slot attributes are overridden (eg see #wrap_data in
  # sources on wikirate).  The problem is the format object had the set modules but
  # the card didn't.
  #
  # My guess is that the need for the following had something to do with errors
  # associated with changed types. If so, the solution probably needs to handle
  # including the set modules associated with the type at the time of the action
  # rather than including no set modules at all.
  #
  # What's more, we _definitely_ don't want to hard code special behavior for
  # specific types in here!

  # , skip_modules: true
  # return res unless res && res.type_id.in?([Card::FileID, Card::ImageID])
  # res.include_set_modules
end
change(field) click to toggle source

action's {Change} object for given field @see interpret_field interpret_field for field param @return [Change]

# File lib/card/action.rb, line 138
def change field
  changes[interpret_field field]
end
changed_values() click to toggle source

all changed values in hash form. { field1: new_value }

# File lib/card/action.rb, line 178
def changed_values
  @changed_values ||= changes.transform_values(&:value)
end
changes() click to toggle source

all action {Change changes} in hash form. { field1: Change1 } @return [Hash]

# File lib/card/action.rb, line 166
def changes
  @changes ||=
    if sole?
      current_changes
    else
      all_changes.each_with_object({}) do |change, hash|
        hash[change.field.to_sym] = change
      end
    end
end
current_changes() click to toggle source

@return [Hash]

# File lib/card/action.rb, line 183
def current_changes
  return {} unless card

  @current_changes ||=
    Card::Change::TRACKED_FIELDS.each_with_object({}) do |field, hash|
      hash[field.to_sym] = Card::Change.new field: field,
                                            value: card.send(field),
                                            card_action_id: id
    end
end
expire() click to toggle source

remove action from action cache

# File lib/card/action.rb, line 93
def expire
  self.class.cache.delete id.to_s
end
interpret_field(field) click to toggle source

translate field into fieldname as referred to in database @see Change::TRACKED_FIELDS @param field [Symbol] can be :type_id, :cardtype, :db_content, :content,

:name, :trash

@return [Symbol]

# File lib/card/action.rb, line 199
def interpret_field field
  case field
  when :content then :db_content
  when :cardtype then :type_id
  else field.to_sym
  end
end
interpret_value(field, value) click to toggle source

value in form prescribed for specific field name @param value [value of {Change}] @return [Integer] for :type_id @return [String] for :name, :db_content, :content, :cardtype @return [True/False] for :trash

# File lib/card/action.rb, line 212
def interpret_value field, value
  case field.to_sym
  when :type_id
    value&.to_i
  when :cardtype
    Card.fetch_name(value&.to_i)
  else value
  end
end
previous_action() click to toggle source
# File lib/card/action.rb, line 112
def previous_action
  Card::Action.where("id < ? AND card_id = ?", id, card_id).last
end
previous_change(field) click to toggle source

most recent change to given field before this one @see interpret_field interpret_field for field param @return [Change]

# File lib/card/action.rb, line 145
def previous_change field
  return nil if action_type == :create

  field = interpret_field field
  if @previous_changes&.key?(field)
    @previous_changes[field]
  else
    @previous_changes ||= {}
    @previous_changes[field] = card.last_change_on field, before: self
  end
end
previous_value(field) click to toggle source

value of field set by most recent {Change} before this one @see interpret_field interpret_field for field param @see interpret_field interpret_field for field param

# File lib/card/action.rb, line 128
def previous_value field
  return if action_type == :create
  return unless (previous_change = previous_change field)

  interpret_value field, previous_change.value
end
sole?() click to toggle source
# File lib/card/action.rb, line 222
def sole?
  all_changes.empty? &&
    (action_type == :create || Card::Action.where(card_id: card_id).count == 1)
end
value(field) click to toggle source

value set by action's {Change} to given field @see interpret_field interpret_field for field param @see interpret_value interpret_value for return values

# File lib/card/action.rb, line 119
def value field
  return unless (change = change field)

  interpret_value field, change.value
end