Something akin to a blog. Thoughts, photos, and relevant updates are collected here, click a tag to narrow by interest.
Today I Learned ~D[2025-05-14]
I recently switched jobs, which means new BitBucket credentials. However; I remain an occasional consultant with my last agency so I need to keep my public key associated with their BitBucket account...
### The first thing I learned today
BitBucket won't let you use the same public key for multiple accounts. I find this a little odd; like how AWS won't let you name a S3 bucket if the name alrea...
Class Configs with Lambdas in Ruby
I've been getting reacquainted with Ruby, diving into a well established project which has been blessed by numerous smart developers over the course of the past 10 years. I discovered an interesting pattern for gathering models (`ApplicationRecord` classes) that may or may not be eligible for some feature:
You start with a mixin that creates a method for your classes to pass options to; as well as...
Weekly Roundup: May 2, 2025
This week I formally transitioned from my fulltime consulting gig at [Objective](https://objective.dev) for a fulltime gig at [Built For Teams](https://www.builtapp.com/) more details on that in a future post. However; broadly speaking it means that I'm dusting off my Ruby skills, diving deeper into the realm of OO programing then I ever have before.
### Farewell ASDF
Last Friday night I pulled...
Weekly Roundup: Apr 25, 2025
At the agency, we have a customer who has asked that customers accept terms of service *before* checking out. This is for an Elixir project; mostly fullstack Elixir however the frontend has an odd assortment of sprinkles: StimulusJS and React. I created a `terms_and_conditions` versions table and an accompanying view helper which will check a `terms_version_accepted` on the `user` record if the l...
Cloud Atlas
Review of Cloud Atlas
Weekly Roundup: Apr 18, 2025
Working for a small agency I am fortunate to work on a number of fast moving projects simultaneously. For years I've failed to document what I do during the week but I'm going a little recap of my week. One part historical record, one part general interest. I'm posting it on my blog in the off chance that somebody reads it and, facing a similar problem will reach out I'm always happy to discuss wh...
Experience has shown that if you put out a bug bounty your server will be hit repeatedly with requests to `/wp_admin` for the rest of eternity....
Personal Heuristic: Make it Readable
I wrote this post back in January, just dusted it off to post today as I attempt to get back on the blogging horse.
***
Today I was refactoring a small module that makes calls to an SAP endpoint. The compiler got hung up because it couldn't find the value `item`. It was an easy fix, my code looked like this:
```elixir
for itm <- data do
%{"MATNR" => material, "PSTYV" => category, "VBELN" => ...
Wintering: The Power of Rest and Retreat in Difficult Time
Reading 80% of this book was an exercise in torture. I'm always a little wary of personal memoirs cum self-help books but a few have been transformative for me (ie. Pamela Druckerman's *Bringing Up Bébé).* Katherine May hooked me early with this book, the prose was sharp and the anecdotes interesting however it very quickly devolved into anecdote after anecdote from a brief period in her life wher...
Today I Learned ~D[2025-01-10]
Today's TIL has a twist ending... so stick around.
Elixir has a shortcut for creating anonymous functions. I've always written:
```elixir
greet = fn name -> "Hello, #{name}!" end
# which can be invoked
greet.("Travis")
# returns
"Hello, Travis!"
```
However; I came across some tricky code with a case statement:
```elixir
docs = case type do
:billing -> &[billing_act: &1]
:shipping ...
Morning walk
Interesting things I passed on the way to the library with my daughter here in Guelph.
Merry Christmas everyone!...
OptConnect Marketing Site
- Timeline: July 2020 - December 2021
- Status: the client switched to WordPress in May 2024
- Technologies: CraftCMS, Bootstrap
I built OptConnect’s Marketing site with CraftCMS, an elegant and opinionated alternative to WordPress. Over the years I’ve been able to work on several different Craft projects. The ecosystem is noticeably smaller than WordPress (as to be expected), but in my experien...
Canada Post Strike
For the past few weeks postal workers in Canada have been on strike....
Not to rush Christmas, but I think I'll try my hand at Advent of Code this year. It will be a good chance to play around with Rust....
Adding a `soft_delete` to Ecto Multi pipelines
I'm a big fan of `Ecto,` Elixir's database wrapper. The `Multi` library lets you build up a series of operations that happen in order, if one fails the entire operation rolls back. Multi comes with the a lot of standard CRUD built in, `insert/4` , `update/4` , `delete/4` and their bulk counterparts `insert_all/5` , `update_all/5` and `delete_all/5` for acting on multiple records.
I've been work...
(Untitled)
Went walking with my daughter and we picked some autumnal bouquets....
TIL Struct matching in Guards
Not so much a TIL but I always get confused with the proper syntax. You can pattern match on a struct and use it in a guard to only let through the structs you want:
```elixir
@spec address_formater(BillAddress.t() | ShipAddress.t()) :: String.t()
def address_formatter(%struct{} = address) when struct in [BillAddress, ShipAddress] do
...
end
def address_formatter(_), do: raise "AddressError :...
I'm 33 years old and I only learned how to spell "doesn't" this year. Getting enough practice where I almost spell it right the first time. (I think I used to default to dosen't)....
TIL UUIDv4 vs UUIDv7
I've always run with UUID v4 because it's the default for the `Ecto.UUID` library in Elixir. However a coworker recommended UUID v7. Having never really looked into UUID other than to implement as a primary key the distinction was news to me.
Effectively;
- UUID v4 is a totally random hash that is generated and extremely unlikely to ever conflict with any other generated UUID.
- UUID v7 also ...
TIL INSERT INTO with SELECT constraints
In the past month I've had to write a lot of SQL to migrate a system and split existing "locations" into tenants ie. migrating data from a `public` schema to a tenant's schema is gets messy due to foreign key constraints. Order of operations is important but sometimes you still find yourself in a corner.
In instances where I already have data in the tenant schema, for example `customers` and I ...
July 2024 Music Recap
One of the things I miss most about Spotify is Wrapped. I always feel a pang of envy at the end of the year when people are sharing their Wrapped stats, to the point where I've thought about trying to hook into Tidal's underdeveloped API and create something similar for myself. Alas, maybe someday, it's about #5 on the project backlog.
In the meantime I make due with Tidal's monthly email of my...
Why Cybertruck when you could [Cyberduck](https://cyberduck.io/) ! I think I've been using Cyberduck for 100% of my FTP needs for at least 15 years. Such a rock solid piece of software....
SQL is the way, SQL is always the way! I killed myself for hours this morning trying to query/clean some data in Rails, started writing raw SQL and had it sorted in 30 minutes!...
Apparently I destroyed my fingerprint while climbing over the weekend- my MBP fingerprint no longer seems to work. It's a small feature but very missed when it doesn't work....
Morning Jog in Guelph. Rainy days like yesterday are perfect!
(Untitled)
I just modified the Journal theme to allow for microblogging....
The UW Encampment
I havve been watching with admiration and humility as students around the world have set up encampments demanding
On “Rewilding The Internet”
<script>
import Image from '../../lib/components/content/Image.svelte'
</script>
<Image path="/images/blog/2024/wild.webp" alt="A wild place my daughter and I discoverd in West Vancover"/>
I’ve been hearing this term a lot lately and, frankly, I think it is a fairly myopic view. If you live in a walled garden such as Facebook, Instagram, TikTok, The Artist Formally Known as Twitter, etc. the...
Back up and blogging? Sort of.
In conjunction with me finally overhauling my website I've decided to get on the blogging train. I've had a personal blog on and off since at least 2005. I started when I was 12 or 13 just adding text to a an HTML file and copying it into Geocities then Tripod then Dreamhost. Sometime around 2006 or 2007 I did the "Famous Five Minute Install" of WordPress and stayed the course there for a few ye...
Multi-tenancy with Phoenix and Elixir
There are lots of good places to start with multi-tenancy in Elixir (although I'd recommend Ecto's own docs for either [foreign keys](https://hexdocs.pm/ecto/multi-tenancy-with-foreign-keys.html) or [postgres schemas](https://hexdocs.pm/ecto/multi-tenancy-with-query-prefixes.html) ). Most of the write-ups and tutorials start the same way "generate a new Phoenix application with `mix phx.new` ". Wh...
Today I Learned ~D[2024-01-03]
You can use Erlang's `tc` function to see how many microseconds a function takes. For example, say you were curious if `Enum.filter/2` or `Kernel.--/2` took longer:
Example:
```elixir
$iex> vals = [1, 2, 3, 4, 5]
$iex> :timer.tc(Enum, :filter, [vals, &rem(&1, 2) == 1])
{20, [1, 3, 5]}
$iex> :timer.tc(Kernel, :--, [vals, [2, 4]])
{3, [1, 3, 5]}
```
`Kernel.--` or `vals -- [2, 4]` took 3 micro ...