Class: Card::Act

Inherits:
ApplicationRecord show all
Defined in:
mod/history/lib/card/act.rb,
mod/history/lib/card/act/act_renderer.rb,
mod/history/lib/card/act/act_renderer/bridge_act_renderer.rb,
mod/history/lib/card/act/act_renderer/absolute_act_renderer.rb,
mod/history/lib/card/act/act_renderer/relative_act_renderer.rb

Overview

An "act" is a group of recorded actions on cards. Together, acts, actions, and changes comprise a comprehensive card history tracking system.

For example, if a given web form submissions updates the contents of three cards, then the submission will result in the recording of three actions, each of which is tied to one act.

Each act records:

  • the actor_id (an id associated with the account responsible)
  • the card_id of the act's primary card
  • acted_at, a timestamp of the action
  • the ip_address of the actor where applicable.

Defined Under Namespace

Classes: ActRenderer

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.all_viewable(action_where = nil) ⇒ ActiveRecord Relation

all acts with actions that current user has permission to view

Returns:

  • (ActiveRecord Relation)


54
55
56
57
58
# File 'mod/history/lib/card/act.rb', line 54

def all_viewable action_where=nil
  relation = joins(ar_actions: :ar_card)
  relation = relation.where(action_where) if action_where
  relation.where(Query::CardQuery.viewable_sql).where.not(card_id: nil).distinct
end

.all_with_actions_on(card_ids, with_drafts = false) ⇒ Array of Acts

all acts with actions on a given list of cards

Parameters:

  • card_ids (Array of Integers)
  • with_drafts (true, false) (defaults to: false)

    (only shows drafts of current user)

Returns:

  • (Array of Acts)


46
47
48
49
50
# File 'mod/history/lib/card/act.rb', line 46

def all_with_actions_on card_ids, with_drafts=false
  sql = "card_actions.card_id IN (:card_ids) AND (draft is not true"
  sql << (with_drafts ? " OR actor_id = :user_id)" : ")")
  all_viewable([sql, { card_ids: card_ids, user_id: Card::Auth.current_id }])
end

.cacheObject



60
61
62
# File 'mod/history/lib/card/act.rb', line 60

def cache
  Card::Cache[Card::Act]
end

.delete_actionlessObject

remove all acts that have no action. (janitorial)



34
35
36
37
38
39
40
# File 'mod/history/lib/card/act.rb', line 34

def delete_actionless
  joins(
    "LEFT JOIN card_actions ON card_acts.id = card_act_id"
  ).where(
    "card_actions.id is null"
  ).delete_all
end

.delete_cardlessObject

remove all acts that have no card. (janitorial)

CAREFUL - could still have actions even if act card is gone...



28
29
30
31
# File 'mod/history/lib/card/act.rb', line 28

def delete_cardless
  left_join = "LEFT JOIN cards ON card_acts.card_id = cards.id"
  joins(left_join).where("cards.id IS NULL").delete_all
end

.timestamp_attributes_for_createObject

used by rails time_ago timestamp is set by rails on create



66
67
68
# File 'mod/history/lib/card/act.rb', line 66

def timestamp_attributes_for_create
  super << "acted_at"
end

Instance Method Details

#action_on(card_id) ⇒ Card::Action

act's action on the card in question

Parameters:

  • card_id (Integer)

Returns:



98
99
100
101
102
# File 'mod/history/lib/card/act.rb', line 98

def action_on card_id
  actions.find do |action|
    action.card_id == card_id && !action.draft
  end
end

#actions(cached = true) ⇒ Array

list of all actions that are part of the act

Returns:

  • (Array)


89
90
91
92
93
# File 'mod/history/lib/card/act.rb', line 89

def actions cached=true
  return ar_actions unless cached

  self.class.cache.fetch("#{id}-actions") { ar_actions.find_all.to_a }
end

#actions_affecting(card) ⇒ Array of Actions

act's actions on either the card itself or another card that includes it

Parameters:

Returns:

  • (Array of Actions)


123
124
125
126
127
128
# File 'mod/history/lib/card/act.rb', line 123

def actions_affecting card
  actions.select do |action|
    (card.id == action.card_id) ||
      card.nestee_ids.include?(action.card_id)
  end
end

#actorObject



71
72
73
# File 'mod/history/lib/card/act.rb', line 71

def actor
  Card.fetch actor_id
end

#cardCard

the act's primary card

Returns:



77
78
79
80
81
82
83
84
85
# File 'mod/history/lib/card/act.rb', line 77

def card
  Card.fetch card_id, look_in_trash: true # , skip_modules: true

  # FIXME: if the following is necessary, we need to document why.
  # generally it's a very bad idea to have type-specific code here.

  # return res unless res&.type_id&.in?([Card::FileID, Card::ImageID])
  # res.include_set_modules
end

#draft?Boolean

Returns:

  • (Boolean)


110
111
112
# File 'mod/history/lib/card/act.rb', line 110

def draft?
  main_action.draft
end

#elapsed_timeString

time (in words) since act took place

Returns:

  • (String)


116
117
118
# File 'mod/history/lib/card/act.rb', line 116

def elapsed_time
  DateTime.new(acted_at).distance_of_time_in_words_to_now
end

#main_actionCard::Action

act's action on primary card if it exists. otherwise act's first action

Returns:



106
107
108
# File 'mod/history/lib/card/act.rb', line 106

def main_action
  action_on(card_id) || actions.first
end