-
Last year, my dad found a large wasps’ nest in the attic. To my astonishment, with the aid of a beekeeper hat and various toxic powders, he removed it.
One night this week while preparing C’s room for his night-time routine, I found a large, dozy wasp clinging to a window blind and sent E in to dispatch it. Sufficiently suspicious, I sent my dad back into the attic with a torch to see if they had returned.
They haven’t.
-
Working on a new Rails application, I wondered what the current popular choice for handling pagination with Active Record is (only being familiar with the venerable
will_paginateand Kaminari). Scott mentioned Pagy and I gave it a try.Given how I can be about compatibility in my gems, I was surprised to see that Pagy 4 requires Ruby 3.0. This is because it uses Ruby 3.0’s “endless method” definition syntax which was initially proposed on April Fool’s Day 2020, e.g.
def square(x) = x * xPerhaps next year we’ll see libraries using downward assignment.
-
We had a barbecue with E’s family in their back garden on Saturday and we baked Felicity Cloake’s bakewell tart for the occasion.
It has been a long time since I have seen them and C delighted in exploring a box of old toy cars that E’s dad and his brothers played with when they were young. We attempted to explain the difference between cars, vans and lorries as he inspected each one.
This joy was dwarfed by the discovery that real, honest-to-goodness buses could be spotted at the junction at the end of the road. Seeing three double-deckers at once caused C to breathlessly shout “BU!” at the top of his voice.
-
I finished implementing last week’s Tree Delta-based synchronisation system ending up with the following classes:
FromRoot: the root of the tree of nodes that represent the current state of the database, the key method beingFromRoot#childrenwhich returns an array of…FromProductNode: a node representing a single top-level product with itsparentset to theFromRoot, itsidentityas aProductIdentity, itsvalueas aProductValueand itschildrenas an array of…FromCategoryNode: a node representing a category which can have itsparentset to either aFromProductNodeor anotherFromCategoryNode, itsidentityas aCategoryIdentity, itsvalueas aCategoryValueand itschildrenas either otherFromCategoryNodes or a…FromDocumentNode: a node representing a document and its file upload, itsparentis aFromCategoryNode, itsidentityis aDocumentIdentityand itsvalueis aDocumentValuewith nochildren.
There is also a set of corresponding
ToRoot,ToProductNode,ToCategoryNode, etc. classes that also useProductIdentity,CategoryValue, etc. so they can be compared by Tree Delta.By returning dedicated type-specific
Valueobjects (e.g.DocumentValue,CategoryValue), I’m able to define how Tree Delta compares them but also expose extra methods to the importer, e.g. so two documents can be compared without re-downloading the full uploaded file but there is a way to get the full file if needed.The final piece of the puzzle was to implement my own
ProductOperation,CategoryOperationandDocumentOperationclasses to wrap Tree Delta’s own. These each implement a single publicapplymethod responsible for translating an operation such as “create a node with thisidentity,parentandvalue” into a database operation in my application. This means my top-levelImporter#importmethod boils down to:def import TreeDelta .new(from: FromRoot.new, to: ToRoot.new(client)) .map { |operation| Operation.from(operation) } .each(&:apply) end -
Due to a sequence of events that is difficult to explain, C now asks me to sing 2 Unlimited’s 1993 hit “No Limit” while putting him to bed.
Weeknotes 75
By Paul Mucur,
on