Editing and deleting in parent and child relationships

Introduction

LiteFarm has many parent and child relationships. A parent and child relationship is one in which there are zero to many children and at least one parent, and the children cannot exist without the parent. A concrete example of this pattern is a chosen crop and varietals (see Crops V2.0 for more details) - that is for any given crop (e.g. apple) you can have any number of varietals (e.g. Gala, Red delicious, Fuji, etc.). Another is a varietal and crop management plans for that varietal. In the general case, children will inherit a certain number of attributes from their parent when they are created. For example every varietal created from the “Apple” crop type will inherit attributes such as genus (Malus) and species (domestica), crop group (fruit and nuts), and max rooting depth (2m). While in some cases the child may overwrite when or after they are instantiated, there is still huge value in being able to draw on the parent “template”.

Editing

However, we run into some complexity when editing a parent. For example, say we start with a Gala variety of apple that we’ve identified as a perennial (e.g. it lives for more than one season) and then we create several different crop management plans that are born from this variety template. If we then change the variety to be an annual (a crop that lives for one season and then dies), which has completely different attributes from a perennial - what happens to those children? In computer science terms, do we pass by reference or by value?

In the general case (which means unless otherwise noted in the specific story), we pass by value. That is, existing crop management plans are NOT changed due to the attributes of the parent variety changing - even if they were shared when the crop management plan was instantiated. However, any new crop management plans that are created from that variety do use the new attributes as their template.

Soft deleting

A similar case to editing is soft deleting. As a brief aside: LiteFarm, in general, does not support hard deletes. In the case of a soft delete, a “deleted” flag is set to true on the record which causes the record not to display in the UI and for endpoints to ignore that record while still persisting a historical log of that record in the database. There are a bunch of reasons this is good practice, but the most relevant to this guidance is that soft deletion removes unwanted records from the users view while also maintaining any relationships that record had with other records in the system. The general case for when a user attempts to soft delete a parent record follows this logic:

Does this record have any active* children or any active* incoming references?

If yes, display some sort of a dependency error (see https://lite-farm.atlassian.net/browse/LF-1024 for an example) and do not soft delete the record. Otherwise, soft delete it.

* In this case active is a general term for non-stale data. This will be defined on a relationship by relationship basis. For example, when attempting to soft delete a location we check for shifts or logs that are in the future or crops in that location whose management plan is not completed or abandoned. Since soft deleting the location won’t destroy or corrupt the already completed logs, shifts, and crops (they can still be accessed through their respective homepages) it’s safe to proceed.

There are no restrictions on soft deleting a child, unless that child is a parent as well (as is the case for varietals) or has active incoming references.

A note on general cases

For every rule, there’s a good reason out there to break it. These are general guidelines and they should be followed unless a specific story provides guidance otherwise. If you’re unsure, ask! If you think the story calls for a departure from these norms, raise it to the team!