Class: Card::Action
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Card::Action
- Extended by:
- Admin
- Includes:
- Differ
- Defined in:
- mod/history/lib/card/action.rb,
mod/history/lib/card/action/admin.rb,
mod/history/lib/card/action/differ.rb,
mod/history/lib/card/action/action_renderer.rb
Overview
An action is a group of changes to a single card that is recorded during an act. Together, acts, actions, and changes comprise a comprehensive 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 with two changes. If there are multiple cards changed, each card would have its own action, but the whole submission would still comprise just one single act.
An Action records:
Defined Under Namespace
Modules: Admin, Differ Classes: ActionRenderer
Constant Summary collapse
- TYPE_OPTIONS =
these are the three possible values for action_type
%i[create update delete].freeze
Class Method Summary collapse
- .all_viewable ⇒ Object
- .all_with_cards ⇒ Object
-
.cache ⇒ Card::Cache
cache object for actions.
-
.fetch(id) ⇒ Action?
retrieve action from cache if available.
Instance Method Summary collapse
-
#action_type ⇒ Symbol
retrieve action_type (create, update, or delete).
-
#action_type=(value) ⇒ Integer
assign action_type (create, update, or delete).
- #all_changes ⇒ Object
-
#card ⇒ Card
each action is associated with on and only one card.
-
#change(field) ⇒ Change
action's Change object for given field.
-
#changed_values ⇒ Object
all changed values in hash form.
-
#changes ⇒ Hash
all action changes in hash form.
- #current_changes ⇒ Hash
-
#expire ⇒ Object
remove action from action cache.
-
#interpret_field(field) ⇒ Symbol
translate field into fieldname as referred to in database.
-
#interpret_value(field, value) ⇒ Integer, ...
value in form prescribed for specific field name.
- #previous_action ⇒ Object
-
#previous_change(field) ⇒ Change
most recent change to given field before this one.
-
#previous_value(field) ⇒ Object
value of field set by most recent Change before this one.
- #sole? ⇒ Boolean
-
#value(field) ⇒ Object
value set by action's Change to given field.
Methods included from Admin
delete_cardless, delete_old, make_current_state_the_initial_state
Methods included from Differ
#cardtype_diff, #content_diff, #green?, #name_diff, #new_content?, #new_name?, #new_type?, #raw_view, #red?, #summary_diff_omits_content?
Class Method Details
.all_viewable ⇒ Object
65 66 67 |
# File 'mod/history/lib/card/action.rb', line 65 def all_viewable all_with_cards.where Query::CardQuery.viewable_sql end |
.all_with_cards ⇒ Object
61 62 63 |
# File 'mod/history/lib/card/action.rb', line 61 def all_with_cards joins :ar_card end |
.cache ⇒ Card::Cache
cache object for actions
57 58 59 |
# File 'mod/history/lib/card/action.rb', line 57 def cache Card::Cache[Action] end |
.fetch(id) ⇒ Action?
retrieve action from cache if available
49 50 51 52 53 |
# File 'mod/history/lib/card/action.rb', line 49 def fetch id cache.fetch id.to_s do find id.to_i end end |
Instance Method Details
#action_type ⇒ Symbol
retrieve action_type (create, update, or delete)
107 108 109 110 111 |
# File 'mod/history/lib/card/action.rb', line 107 def action_type return :draft if draft TYPE_OPTIONS[read_attribute(:action_type)] end |
#action_type=(value) ⇒ Integer
assign action_type (create, update, or delete)
101 102 103 |
# File 'mod/history/lib/card/action.rb', line 101 def action_type= value write_attribute :action_type, TYPE_OPTIONS.index(value) end |
#all_changes ⇒ Object
158 159 160 161 162 163 |
# File 'mod/history/lib/card/action.rb', line 158 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 ⇒ Card
each action is associated with on and only one card
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'mod/history/lib/card/action.rb', line 72 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) ⇒ Change
action's Change object for given field
139 140 141 |
# File 'mod/history/lib/card/action.rb', line 139 def change field changes[interpret_field field] end |
#changed_values ⇒ Object
all changed values in hash form. { field1: new_value }
179 180 181 182 183 |
# File 'mod/history/lib/card/action.rb', line 179 def changed_values @changed_values ||= changes.each_with_object({}) do |(key, change), h| h[key] = change.value end end |
#changes ⇒ Hash
all action changes in hash form. { field1: Change1 }
167 168 169 170 171 172 173 174 175 176 |
# File 'mod/history/lib/card/action.rb', line 167 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 ⇒ Hash
186 187 188 189 190 191 192 193 194 195 |
# File 'mod/history/lib/card/action.rb', line 186 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 ⇒ Object
remove action from action cache
94 95 96 |
# File 'mod/history/lib/card/action.rb', line 94 def expire self.class.cache.delete id.to_s end |
#interpret_field(field) ⇒ Symbol
translate field into fieldname as referred to in database
202 203 204 205 206 207 208 |
# File 'mod/history/lib/card/action.rb', line 202 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) ⇒ Integer, ...
value in form prescribed for specific field name
215 216 217 218 219 220 221 222 223 |
# File 'mod/history/lib/card/action.rb', line 215 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 ⇒ Object
113 114 115 |
# File 'mod/history/lib/card/action.rb', line 113 def previous_action Card::Action.where("id < ? AND card_id = ?", id, card_id).last end |
#previous_change(field) ⇒ Change
most recent change to given field before this one
146 147 148 149 150 151 152 153 154 155 156 |
# File 'mod/history/lib/card/action.rb', line 146 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) ⇒ Object
value of field set by most recent Change before this one
129 130 131 132 133 134 |
# File 'mod/history/lib/card/action.rb', line 129 def previous_value field return if action_type == :create return unless (previous_change = previous_change field) interpret_value field, previous_change.value end |
#sole? ⇒ Boolean
225 226 227 228 |
# File 'mod/history/lib/card/action.rb', line 225 def sole? all_changes.empty? && (action_type == :create || Card::Action.where(card_id: card_id).count == 1) end |
#value(field) ⇒ Object
value set by action's Change to given field
120 121 122 123 124 |
# File 'mod/history/lib/card/action.rb', line 120 def value field return unless (change = change field) interpret_value field, change.value end |