-
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_paginate
and 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 * x
Perhaps 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#children
which returns an array of…FromProductNode
: a node representing a single top-level product with itsparent
set to theFromRoot
, itsidentity
as aProductIdentity
, itsvalue
as aProductValue
and itschildren
as an array of…FromCategoryNode
: a node representing a category which can have itsparent
set to either aFromProductNode
or anotherFromCategoryNode
, itsidentity
as aCategoryIdentity
, itsvalue
as aCategoryValue
and itschildren
as either otherFromCategoryNode
s or a…FromDocumentNode
: a node representing a document and its file upload, itsparent
is aFromCategoryNode
, itsidentity
is aDocumentIdentity
and itsvalue
is aDocumentValue
with 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
Value
objects (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
,CategoryOperation
andDocumentOperation
classes to wrap Tree Delta’s own. These each implement a single publicapply
method responsible for translating an operation such as “create a node with thisidentity
,parent
andvalue
” into a database operation in my application. This means my top-levelImporter#import
method 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