track name and type changes
Ticket
+status
+priority
+tag
+commit
+issues
- lots of information lost
- can't fully revert to previous states
+solution
this is going to involve a substantial overhaul of revisions system. Here are the proposed changes:
cards:
add "db_content" field
stop using current_revision_id field
# note: updated_at and updater_id should be updated when (and only when) there is a new transaction involving either the card or one of its "field descendants", meaning that if someone updates A+B, that is registered as an update to A but not to B. So if only fields other than name, type_id, db_content, or trash are updated (eg codename), this change should not alter these fields.
card_revisions table:
gone, replaced by card_transactions, card_actions, and card_changes
card_acts
id
card_id # all acts are associated with one root card
actor_id # card id of user)
acted_at # datetime)
ip_address
card_actions
id
card_id
card_act_id
action_type # create, update, and delete (could do mapped numbers)
card_changes
id
card_action_id
field # name, type_id, db_content..trash? something for files? (could do mapped numbers here,too)
value
Q&A.
Why add content to cards table?
- consistency: this makes it so that all the main fields are stored the cards table, which becomes a complete representation of the current state of the deck. You can reproduce the entire deck (without any history) with this table alone.
- performance: WQL no longer needs to do a join (which would now be a much more complicated join) to get this info
- code simplicity: there is currently a bunch of special handling for content because of its special status. with this representation we'll be able to get rid of all the attribute tracking code.
Why call it "db_content"?
- Following rails convention (and using rails code!), each database field is associated with card methods, like @card.db_content. To avoid errors, it is best if database content is distinguished from other content values, which may be overridden by *structure rules for example. In general, the db_content should not be manipulated directly by the API as frequently as the post-structural processing content, so we want to make it less tempting to make this mistake.
What's the difference between card_act and card_actions?
- Every card_act will involve one or more card_actions. When someone creates a Claim, for example, this will involve creating several other cards (like the +source card). There is just one act, but each subcard has a separate action.
Is the card_actions table really necessary?
- Not strictly. You could stick the card_id in card_changes, treat "trash" as another field, and then either infer the action (eg, if trash is set to true, it's a deletion) or add an action field there. It's worth discussing the merits of the two approaches in greater depth, but this seems very precise, clean, and robust.
migrating old data from card_revisions
id -> card_changes.id
created_at -> card_acts.acted_at
creator_id -> card_acts.actor_id
card_id -> card_actions.card_id
content -> card_changes.value
# migration notes:
- card_changes.field will always be content for the stuff coming from card_revisions, but we may also add name/type changes with create actions for all cards (?).
- if the card isn't in the trash, the card_actions.action_type will always be create or update (easy to infer - first one is create)
- if the card is in the trash, there should also be a delete action
- the hard part will be grouping card_actions into card_acts. We can probably infer this too based on timestamps