How to run a command via AWS SSM with live output

This little technique is a great example of how simple *nix utilities can be (mis)used to accomplish some interesting things: (echo "./deploy.sh" && cat && exit && exit) | \ aws ssm start-session --target $INSTANCE_ID This: Echos the command into the shell session once started (echo "./deploy.sh" - obviously whatever command you want to run goes here) Runs cat to...

A Stimulus controller to auto-submit authentication codes

I think this is neat - very succinct. This controller expects an input that calls formatOnSubmit on input, which removes invalid chracters, strips the input (e.g. of spaces), and then automatically submits it. Works great with pasting, manually typing, and provides fast feedback to users. import { Controller } from "@hotwired/stimulus"; export default class extends Controller { static targets =...

Open-sourcing a reference implementation of native iOS Google sign-in flow with Hotwire

I’ve just open sourced a reference implementation of native iOS Google sign-in using Hotwire Native. I developed this flow when building Virtualtrails, where I wanted to support both web and native authentication flows for Google Sign-in. Using Hotwire for this worked great - when native support is available, it’s automatically used. When not, it falls back to a web-based OAuth...

About Trove Project

I’ve been working this week on Trove (Github, Docs). Trove is meant to be a self-hosted system that can store arbitrary (but schema validated) JSON data, files, and relationships between events. By events I mean things like: Bookmarks Photos I like Colours/patterns I’ve seen out and about that I like Storypark updates (from daycare/school) etc. Basically all the digital miscellanery...

OpenNext on Cloudflare

I’m trying out OpenNext with Cloudflare. One kind of annoying thing already I’ve run into is that libraries that use cross-fetch end up running into errors, because OpenNext patches the deployment package enough that cross-fetch tries to use Node libraries, when actually it can just use native fetch. In the case I ran into, I could work around this by...

Hutt Forks/Eastern Hutt Hut

I tried to get to Eastern Hutt Hut on Friday. Didn’t quite make it, just because I’d committed to a half day rather than full day trip, but it seemed doable. I turned around here with 2km to go, it took me 2 hours to get there after biking over from Kaitoke on the 4WD road - 1 hour biking,...

Restart rails quickly with bin/rails restart

Just a quick tip! If you’re like me, you start with just one or two tabs (or tmux panes), and things get more and more disorganised as the day goes on. If you need to restart your Rails server quickly, and don’t feel like hunting out your Rail server terminal, no worries! Just running bin/rails restart will signal the server...

Check that an enumerable satisfies matchers with args in RSpec

Note: I discovered this API based on a suggestion from an AI editor assistant, just to disclaim that. When creating an RSpec test against an enumerable, rubocop-rspec will enforce that the all matcher be used instead: it "only returns odd numbers" do odd = [1 3 5] expect(odd).all(be_odd) end This is fine for a matcher that doesn’t require any args...

Detecting the origin of an ActiveRecord record's destruction

In a before|after_destroy callback, you can use the destroyed_by_association method to access the association (therefore the parent record or parent record type) that is causing this record to be destroyed. This is also a handy way to tell the difference betwee a ‘direct’ destruction (widget.destroy), and a ‘dependent’ destruction has_many :widgets, dependent: :destroy`). I had a use case for this...

How to use assigns() in a Rails request spec without a dependency

Several years ago, the Rails core team advised that controller tests/specs were being discouraged, in favour of request specs. The basis for this was that controller tests had more visibility into the internals of the controller, and were not purely testing the HTTP interaction as request specs were. This is valid, but one method I end up missing a lot...