-
Notifications
You must be signed in to change notification settings - Fork 34
Merging
Let's say you have a Person
object with a Name
. Maybe you are in the marketing domain, and info comes in through various lists (say csv or Excel files). Some of these may contain missing, incomplete, or incorrect information. When new info comes in referring to the same person, you'd like to take the most correct parts of both the existing and incoming data.
The well-known #patchRelativeToBase:
, which we borrow from Monticello. newObject patchRelativeToBase: existingObject
returns an MAPatchMacro
which contains a MAPatchOperation
for each description of interest. "Interesting" here means that the description:
- The field has not been excluded from merging
- The new value is interesting
Just do anElementDescription shouldMerge: false
. Why would you want to do this? Continuing our Person
example, let's say we have a virtual #fullName
field which concatenates #firstName
, #lastName
, etc into a pretty printed string. The real data lies not in the generated string, but in the components and will be merged there. NB: maybe a simpler way would be to exclude #readonly fields?
The default rules are:
- The value has changed - duh!
- The new value is not nil
-
The new value is not the Magritte default value(This should be implemented. See Issue #19)
These can be changed by overriding #is:anInterestingReplacementFor:
, currently on the domain object level e.g. Name
. For example, aName
might want to merge a new value which is a full first name like "James", when the previous value was an abbreviation e.g. "J.". Obviously, overriding once per domain object only works when its fields which are all similar. Probably in the future when the need arises, this should be moved to the element description.
By default, field values are replaced with the new values. If instead you want to keep the existing field value object and recursively update its fields, in your field type (Name
in our example), override as follows:
patchRelativeToBase: oldValue as: description of: receiver
"Edit me in place instead of full replacement like a value object"
^ self patchRelativeToBase: oldValue
This would allow us to consider each update to aPerson
's name individually and not as an atomic operation. We may want to accept the new first name, but reject the new middle name.
There is a very-barebones spike called MAPatchBrowser