On being right
If you want to be right, don't be right about someone else's shit. Be right about your own shit.- Day9
A collection of notes that I jot down occasionally for personal use. I find that writing things down helps me remember, or so that's the idea. Thoughts are my own, and not fully formed 🧠
If you want to be right, don't be right about someone else's shit. Be right about your own shit.- Day9
I really resonate with the following quote from an interview with Joeyray Hall (Thor’s Dad).
There’s times where I’m not good at explaining what I do, but if I do it they’ll get it.
As a bit of a people pleaser, I struggle to negotiate or convince someone that a solution I have is going to be good. I find it a lot easier to build the thing, and show them it that it works. The proof is always in the pudding :)
Rails devs - dislike using types, but use a SQL database.
Typescript devs - must use types everywhere, but then use firebase.
Ironic no?Today I stumbled upon Rails delegated types, a feature added in Rails 7. The paradigm can be used as an alternative to single table inheritance and purely abstract ActiveRecord
classes. Keeping this one in my back pocket to use next time I come across a problem where I want the superclass view to be separately "queryable" in its own table without having to store all of unrelated subclass attributes in that same table.
With this approach, the “superclass” is a concrete class that is represented by its own table, where all the superclass attributes that are shared amongst all the “subclasses” are stored. And then each of the subclasses have their own individual tables for additional attributes that are particular to their implementation.
Snood was awesome, was it not? And what the heck, it's still being sold and it's $19.99 for the original version!
I've seen the faraday ruby gem used in a number of ruby projects over the years, but I hadn't used it directly myself until recently.
There are a LOT of HTTP clients in ruby land, but faraday is consistently on the top of the list as being the most popular. I decided to try it out for a project I was leading at work. I needed to build a generalized HTTP client that could be used to interact with a number of different websites that accepted and responded with different content types. I also wanted to add some defaults such as a proxy uri, basic error handling, and a timeout. I really liked faraday's approach to mixing in ad-hoc request/response middleware to handle making requests, so I decided to give it a go. I built a little utility that wraps a faraday connection and its response. Nothing too fancy, but it made working with the connection and response objects more flexible for my specific use case. The example below is simplified, but it looked something like the following:
require "faraday"
require "http-cookie"
# Wraps a Faraday::Connection
#
# - Uses default configuration options for a proxy uri, timeout, and error handling
# - Accepts all configuration options for a faraday connection
# - Accepts a block to configure additional middleware
# - Returns a custom custom Response object
class HTTPConnection
attr_reader :connection
def initialize(url:, **kwargs, &block)
@connection = Faraday.new(
url:,
proxy: { uri: "https://someproxy.com" },
request: { timeout: 15 }, # seconds
**kwargs
) do |builder|
builder.response(:raise_error)
block&.call(builder)
end
end
%w[get post put delete patch].each do |request_method|
define_method(request_method) do |path, *args|
Response.new(connection.public_send(request_method, path, *args))
end
end
# Wraps a Faraday::Response
#
# - Adds helper to get the request_method
# - Adds helper to get the url
# - Adds helper to easily retrieve cookies from the response
class Response
extend Forwardable
attr_reader :response, :env
def_delegators :response, :status, :body, :headers
def_delegators :env, :request_body, :request_headers
def url
env.url.to_s
end
def request_method
env.method.to_s
end
def cookies
Cookies.new(
cookie_header: headers['Set-Cookie'],
url:
)
end
def initialize(response)
@response = response
@env = response.env
end
end
class Cookies
def initialize(cookie_header:, url:)
@jar = HTTP::CookieJar.new
@url = url
@jar.parse(cookie_header.to_s, @url)
end
def to_a
@jar.cookies(@url)
end
def to_header
{ 'Cookie' => HTTP::Cookie.cookie_value(to_a) }
end
end
end
conn = HTTPConnection.new(
url: "https://example.com",
headers: { "Content-Type" => "application/json" }
) do |builder|
# Can add any additional middleware here, depending on the requirements of the endpoint
builder.request(:url_encoded)
builder.response(:json)
end
# Works just like a normal faraday request
response = conn.post('/endpoint', { 'name' => 'Jason' })
My previous note was about stack overflow so I continued the trend by answering another couple questions:
jsonb
columns in postgres if I don't have to, I've overall had a pretty good experience using the jsonb_accessor gem. Despite some of its quirks, it does make using jsonb
columns in Rails more user friendly. And at the end of the day that's a good thing.While working on this site, I encountered an issue where content displayed using the the flash (a special tool used in conjunction with rails sessions to display temporary content between requests) was lingering for a brief second when revisiting a page that had previously displayed something from the flash. After searching through some documentation, I found that the underlying cause was due to the way turbo caches content between page reloads. A few minutes later, I happened to stumble upon this stack overflow thread related to the issue. I thought that I could provide a useful answer, and so I responded 🎉
In the age of LLMs and notably ChatGPT, stack overflow is becoming less relevant for day to day usage, but I am happy that fiddling around with this site inspired me to contribute a response 🖥️Gall’s law has greatly influenced the way I’ve operated as a software developer over the last decade. It is as follows:
A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over with a working simple system
Today I remembered that it's not possible to traditionally log out of a website if HTTP basic authentication is used to login.
Basic auth credentials are transmitted with each and every request by the browser. Hence why you cannot traditionally log out without closing the browserAs soon as the browser prompts for credentials and the user logs in, those credentials are cached sent with every subsequent request until the browser is closed or restarted. The more you know ✨
I reminded someone of a quote I've heard today, which I still take to heart
Good strategy is nothing without good execution
Running rubocop in lsp mode is pretty sweet 🍬
Before this, my neovim setup synchronously called the rubocop command to auto format the file upon every save. While this was sped up a bit by using the--server
flag, it is nowhere near as fast as running rubcop in lsp mode using the --lsp
flag. Taking advantage of neovim’s support of the language server protocol, I was able to integrate this seamlessly into my setup. It’s been great for diagnostics too 🤓
Added some touches to this site that allow notes to come alive a little bit more, including the ability to easily highlight code using Highlight JS 💅
# Let's test the syntax highlighting with a simple factorial function
def fact(n)
if n == 0
1
else
n * fact(n-1)
end
end
I’ve always been motivated and had a lot of fun writing software for a company, and I’ve managed to maintain a stable level of productivity at work throughout the last decade. But I’ve always wanted to work on a fun software related project on the side 🤔
The trouble I’ve had with working on side projects is that it can be difficult for me to build momentum with any particular idea. This is especially true if I’m finding the software I’m writing at work to be fulfilling. Software companies already have customers using their product and the feedback loop of shipping is immediately satisfying.
I’ve dabbled with contributing to open source and have landed some cool contributions over the years, but I have yet to build something for me. Something that let’s me express my own personality on the web. So this year I’ve decided to take the pressure off of building something unique and cool, and instead start with something simple that I’ve always wanted to do. Create and host my own website from scratch. I want this to be the catalyst for tinkering a little bit more in my free time 🚀