← Home About Archive Photos Projects Uses Also on Micro.blog
  • Weekly Round Up: June 13, 2025 👻

    It was a week of state machines. Two separate Rails projects, two separate state machine libraries (state_machines and aasm), both sending emails. One is a fairly straightforward project for a department of education, it’s an old codebase but Objective built it and has been working on it ever since. As such, it’s fairly clean and straightforward for it’s age. I think that the more contractors and firms a codebase passes through the more muddled it gets. I’ve been working on this codebase for about two years now. The entire time I’ve been working to convert an old paper process to a digital one, it’s not an overly ambitious project but the budgeting has necessitated a slower pace of development. With only a few months left in the yearly budget (in education I guess the fiscal year ends with the school year) I was asked to quickly implement a form that allows users to draft a custom email message and attach a PDF. It’s been a while since I’ve done this with Rails, my last experience doing so was in the Paperclip days and that was not too fun. I’ve been pleasantly surprised with ActiveStorage, it’s much more plug-and-play then I recall (I’ve also been developing a lot longer now).

    The other project is far more involved, my new full-time at gig at Built. It’s been exciting to work in tandem with another developer who has been handling the front-end work. Coming from a small agency I’ve always developed features full stack. Part of why I wanted to switch to a dedicated product team was to have experiences like this one where a greater degree of planning and coordination between developers was required. I started by creating a model last week and writing as many tests as I thought would be relevant. I’ve been through TDD phases in the past; but I think in small teams and projects TDD offers diminishing returns. It makes a lot of sense in a scenario like this, even on a fairly small team, since I’m developing features that I can’t be able to test in the browser until the other developer has her features in place. She in turn won’t be able to know if the front end works until my code is merged into her branch. This feature was the bulk of my week but it came together in time for some Friday afternoon QA of which I’m sure there will be several things to fix on Monday morning.

    → 8:00 PM, Jun 12
  • Weekly Roundup: May 2, 2025

    This week I formally transitioned from my fulltime consulting gig at Objective for a fulltime gig at Built For Teams 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 a Flutter repo I’m working on with a friend. I started having all kinds of issues trying to install Cocoapods. gem install cocoapods but then flutter run produced this error:

    Warning: CocoaPods is installed but broken. Skipping pod install.
    ...
    Error: CocoaPods not installed or not in valid state.
    

    Ok. So do some more research throw in a sudo, no luck. pod version produces this error:

    <internal:/Users/travis/.asdf/installs/ruby/3.3.5/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136:in `require': linked to incompatible /Users/travis/.asdf/installs/ruby/3.1.6/lib/libruby.3.1.dylib -
    

    Ah! I’ve seen this more than once! Ever since I shifted to a Ruby focused team at the start of the year I feel like Ruby version management has been an uphill slog. I’ve reshim’d multiple times, removed versions of Ruby, removed the Ruby plugin, and reinstalled ASDF. Things work for a time but eventually I run into errors like the above. My hunch, which may be ovbious, is that something was wrong with my setup that was placing versions of Ruby inside other versions (ruby/3.3.5/lib/ruby/3.3.0); I’m not sure if the path is supposed to look like that but it doesn’t make sensee to me. I’m willing to take responsability here, it may be that my $PATH was misconfigured (although I attempted multiple times to proide a concise path for ASDF) or that something in my system was messing with ASDF. I love ASDF, it’s served me very well for years. Being able to remove rvm and nvm and seamlessly manage Elixir versions between projects was a breath of fresh air. The docs are clear and concise, the tool provides enough functionality to get stuff done without getting in the way. However; for whatever reason, the slog to get Ruby working just took its toll. One of my coworkers mentioned Mise which is a drop in replacement for ASDF. I installed it in about 30 seconds and in 45 seconds my project was running with Mise. 👏

    → 8:00 PM, May 1
  • 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 last terms_and_conditions.inserted_at date matches the terms_version_accepted then the user is shown an active “proceed to checkout” button, if not the button is disabled and a note asking them to acccept the terms of service will display.
    Since most of the Elixir projects I work on are fullstack (Phoenix LiveView) I don’t often get to write API endpoints. The API work on this was admittidly very small, a simpl endpoint that takes the user’s ID and updates the terms_version_accepted timestamp when they click “accept” in the modal. It returns a URL which we then append to checkout link allowing the user to proceed. This feature is due May 5th but I’m hoping to get onto the staging server on Monday or Tuesday.

    Internal Tooling:

    I’ve been using fzf for a while but I’ve wanted to filter only unstaged files, ideally whenever I type git add I just want to see a list of unstaged files that I can add. Admittidly I got some help from AI to do write this up:

    function git_add_unstaged() {
        local files
        files=$(git diff --name-only --diff-filter=ACMR | fzf --multi --preview 'git diff --color=always -- {}')
        if [[ -n "$files" ]]; then
            BUFFER="git add $files"
            CURSOR=$#BUFFER
        fi
    }
    
    function git_add_unstaged_widget() {
        if [[ $BUFFER == 'git add' ]] && [[ $CURSOR -eq $#BUFFER ]]; then 
            git_add_unstaged 
            zle redisplay
        else 
            zle self-insert
        fi
    }
    
    zle -N git_add_unstaged_widget 
    bindkey ' ' git_add_unstaged_widget
    

    I’m wondering if I’ll find the automatic git add to be jarring or have situations such as a merge conflict where this may not work. If so I can always fiddle with the bindkey but for right now I’m enjoying my new found git add speeds.

    → 8:00 PM, Apr 24
  • 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 what worked for me and what didn’t work. It also doesn’t hurt to put this stuff into the world to show that yes I actually do work; I haven’t always had the most active GitHub but most of my client projects a private/propriety. I’m easing into this, all week I was looking forward to this post; now, however, I realize I should have been working on this not cramming it in from memory on a Friday night.

    This week was a balance between my ongoing Elixir projects and a newer (to me) Ruby project.

    • For the past five years I’ve either supported, or been the lead dev on a large B2B ecommerce platform which handles a few million in daily sales. Over the winter the company began consolidating their North American and European processes which includes using said platform for sales in the EU. Although the hope is that the European process will align with the North American there are some relevant differences. For example in North America the client’s product is technically considered a “raw material” which means there is no “Value Added Tax” (VAT); however in Europe, depending on the country of origin and the destination VAT may be charged, other relevant changes are shipping across borders, truck loading calculations and different invoicing procedures. At this point we are still in the research and discovery phase but I’ve been working with another developer to scope this project out and write some preliminary tests as research.
    • For another client I’ve been moving from a Quickbooks Online integration to Quickbooks Desktop, this is a multi-tenancy Elixir Phoenix app so I’ll be keeping the Online functionality and just adding a connection to Quickbooks Desktop. The API docs for QBOnline are fairly good, this is not the case with QB Desktop, it’s evident that Intuit either has the platform on life support or intentionally obfuscates the functionality to foster a consulting industry around the product. QB Desktop uses an SOAP XML type endpoint. Having wrangled fairly nasty endpoints with SAP I wanted to, if at all possible, avoid dealing directly with QB Desktop. I discovered a service called Conductor that does the bulk of the heavy lifting and allows you to hit a very concise REST endpoint.
    • Since the beginning of the year I’ve been transitioning from primarily Elixir projects at the agency to a single Ruby based product. On that front I’ve been involved in an ongoing integration with BambooHR; partnering with Bamboo to pull employee data from their endpoint.
    • On a personal front I finished the migration of this blog from Ghost back to markdown files. I still love Ghost but managing my own instance and integrating it with my Garden proved to be more management than I wanted.
    → 8:00 PM, Apr 17
  • The UW Encampment

    UW Sign covered in solidarity with the people of Gaza

    I’ve been watching with admiration and humility as students around the world have set up encampments demanding their schools disclose and divest from Israeli/defense industries. While the situation in Palestine has been gut-wrenching; it’s been heartening to see the reactions of these brave students. Media coverage, however; has been less than favorable. Even fairly pro-Palestinian outlets such as The Guardian use incendiary language such as, “protest erupted” and the emphasis is generally on the concerns of the administrators, police, and potential safety issues. My reading of this coverage portrays these student activists, at best, as dangerous anarchists looking for a fight, at worst entitled white kids shirking summer internships.

    An angle of the encampment **The encampment is covered in art and slogans! Advertising for the people by the people.** When the encampment went up at the local university, The University of Waterloo, I rode up with my dad to take a look. He brought a few books to donate to the encampment's library (I found it charming that amid the tents and living space the students had already set up a thriving library). The atmosphere was calm and cordial we were offered snacks and there appeared to be a lecture circle going on next to the library.

    I found the atmosphere so tranquil and invigorating (a mix of being back at school and a yoga retreat). It was so enticing I went back the next day with Viv and Ruby. The entire day was planned out (they communicate their donation needs and the daily program via Telegram), we went for kite making and poppy planting - kid friendly activities. Ruby got right to work painting her kite, as parents Viv and I relish any time Ruby spends on her own working on a project so we sat back and tried not to hover. The care and concern that was shown for our daughter was remarkable. Over the course of half an hour multiple people approached her offering her water (it was very hot), a woman came around with bite brownies and asked if Ruby wanted one and if she was allowed. As the sun moved I helped a volunteer move the tent to provide better shade for the kids. This was a scene from a community picnic not an anarchist commune sizzling to the point of boiling.

    Another angle of the encampment from the Grad House **A few from in front of the Grad House.** As I watched the care and compassion shown towards my daughter as well as everyone else who had come to the encampment that day I couldn't help but wonder why *this* wasn't reported? Why is the media so hell-bent on making these students, out to be a volatile and potentially dangerous element? It's a tired trope. Of course there have been violent incidents, counter protesters, police forcibly removing students there are many echos of the 1970 Vietnam protests but from my experience an average day in the encampment is calm, communal, even jovial at times. Everyone is gathered for a higher purpose, and it is a grave one, but even in the face of this genocide a community is being built and it is thriving. My hope is that their time is shortened only by divestment and not batons.
    → 8:00 PM, Jun 13
  • 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 years. As I’ve been reworking my site with SvelteKit I toyed with the idea of doing a Markdown blog. While I like this approach, in theory, I really missed the administration tools that a more full-fledged platform offers, drafts, the ability to post on the fly without having to run a deployment, etc. In the past I’ve solved those pain points with TinaCMS for clients but frankly it’s just more trouble than I’m willing to put in for a personal site.

    So with that I’ve chosen Ghost. I’ve always liked the Ghost ethos, small, remote-first, transparent non-profit. I used Ghost a few years back to document my year of consuming less . I’m not a huge fan of the Medium-like editor they use but their overall aesthetic is on point. I’m not 100% positive what I’m going to post here. I’m a developer by trade so I may write some technical articles; but for the most part this is going to be a collection of my public thoughts and ideas. Mostly short-form with some longer form stuff peppered in. Moving forward I’m going to tweak this template to handle single photos and short form micro posts. The goal being, this can be the central repository for all my online life.

    → 8:00 PM, May 26
  • RSS
  • JSON Feed
  • Micro.blog