Chrome Command Palette in Dev Tools
I was today years old when I learned about Cmd + Shift + p command palette in Google Chrome.
Why you might need it?
To enable dark mode emulation!
Adding PDF previews to ActionText with ActiveStorage
Rails is a great framework, once you stop thinking in Java patterns and embraice DHH way of writing web apps.
Interestingly, Basecamp uses exactly the same ActiveStorage implementation, but shows full-size and download links alone with the PDF attachment. But if you only follow the guide, it’s hard to implement by your own without some gotchas.
These gotchas I want to capture here in this how-to article. It assumes reader followed official guide and stuck with PDF thumbnails preview implementation.
Stop writing data migrations
As many of us, I was writing data migrations as a part of database schema migrations.
Why that’s a bad practice, and what’s the better way to do this.
- Your data migration typically comes along with changes to schema. Do you have the data migration together with schema migration?
- If your data processing fails in the middle of migration, what’s the way to resume it?
- Do you ever need it again? I.e. does it make sense to keep this migration in migrations history?
If you tick at least two checks, congrats, you don’t have to keep data migrations with schema migrations. Just write a script, execute it and throw away!
Vanilla Rails is Enough
Argh, some things I should have learned earlier!
One of these is this brilliant blog post Vanilla Rails is plenty couldn’t have bigger influence on me. Believe me or not, I wrote Rails wrong since 2007 🤦♂️.
Here is the list of gems i’m ditching out of my Rails projects.
- knockout-rails
- paloma
- simple-form
- rails-timeago
- carrierwave
- resque
- resque-web
- resque-scheduler
-- we are here --
- devise
- haml
- factory-bot
- rspec
- bower-rails
- sprockets
- google-visualr
- recurring-select
- select2-rails
- pundit
adding a few
Get GitHub Teams CLI Snippet
GitHub CLI is a nice way to query GitHub API locally
gh api orgs/<org>/teams | jq '.[] | {name,slug}'
Travel Time and Date in Rails Console
Usage
include ActiveSupport::Testing::TimeHelpers
travel_to 2.days.ago
Legacy Rails project and modern Assets Pipeline
One of the projects I’ve started a long-long time ago still powers the business. It was quite a journey starting from Rails 2, than Rails 3 and so on up until currently Rails 7 with plans to bump to Rails 8.
The project has live updates with Server Sent Events and a sidecar microservice to keep the connections and push updates. Quite similar to what DHH have done with ActiveCable, but based on different stack.
Hosting for Static Assets
I lived on GitHub Pages for static hosting for a long time. For example, this blog been hosted as https://mprokopov.github.io for years, just with the custom domain https://prokopov.me
But last week I finally moved everything to CloudFlare Pages and quite happy about it!
The major driver for the change was a hassle of management github-pages. It’s either your have to keep everything in a separate branch, with the name like github-pages
, or have to use completly different repository.
I chose the latter, and for a long time kept using two repositories, one with Hugo sources, second with rendered HTML. It was a bit painful to manage two git repositories in the same working tree, hugo build
renders the website to the public
folder. In addition, the repository with HTML should be public.
Ghostty Remap Cmd to Control under macOS
We all love the fast software. Ghostty is crazy fast.
What I use with my macos keyboard comes from Emacs. Namely, Cmd + <modifier> instead of Control + <modifier> for navigation in shell. Jump to a beginning of line, Cmd + a , to the end of line Cmd + e
Why?
- Because my macOS keyboard doesn’t have TWO Ctrl keys on both sides.
- Try to compare ctrl-a vs cmd-a yourself 😀
Here is an example of a config extracted from this discussion.
Trigger Jenkins job on EC2 termination event
Example of the Python code to catch EC2 termination signal and ping Jenkins to run termination job. Useful to execute graceful shutdown if you’re using EC2 spot instaces.
You will need Jenkins Generic Webhook plugin.
import json
import boto3
import urllib3
import os
JENKINS_JOB_TOKEN = os.environ.get('JENKINS_TOKEN')
JENKINS_URL = os.environ.get('JENKINS_URL')
def invoke_jenkins(target):
http = urllib3.PoolManager()
return http.request('POST', f"{JENKINS_URL}/generic-webhook-trigger/invoke?instance={target}", headers={'Authorization': f"Bearer {JENKINS_JOB_TOKEN}"})
def find_target(instance_id):
ec2 = boto3.client("ec2")
tags = ec2.describe_tags(Filters=[{'Name': 'resource-id', 'Values': [instance_id]}])
for tag in tags['Tags']:
if tag['Key'] == "Name":
return tag['Value']
def lambda_handler(event, context):
instance_id = event["detail"]["instance-id"]
target = find_target(instance_id)
if not target:
return {
'statusCode': 422,
'body': f"target for {instance_id} not found"
}
print(f"Jenkins termination job called for instance: {instance_id} target {target}")
resp = invoke_jenkins(target)
print(f"Jenkins response status {resp.status}")
print(f"Jenkins decoded response")
print(resp.data.decode('utf-8'))
return {
'statusCode': resp.status,
'body': json.dumps(resp.data.decode('utf-8'))
}