Move Slowly and Make Things
The current “vibe code an MVP in a day” trend is toxic bullshit. Good software takes time, but it’s worth the effort.
The current “vibe code an MVP in a day” trend is toxic bullshit. Good software takes time, but it’s worth the effort.
Selecting random records from grouped data isn’t as simple as it seems. Here’s how to do it in Laravel, using Eloquent subqueries.
Notes to self about the unexpected quirks of the otherwise excellent PhoenixTest library.
The post-covid slump is real. On the plus side I became a thought leader, and shipped the best thing I will ever work on.
After working on a complex problem, I tend to over-complicate the next one. I call this “The Complexity Halo”.
After three years of cheating death, I finally caught Covid. That said, the week hasn’t been a complete write-off.
This week has been a balance of working on Hap, and making a start on finding a new Elixir contract.
Placing schemas inside contexts makes it difficult to distinguish between data and actions. Let’s fix that.
In a Phoenix context we frequently need to create and update resources, using changesets. Each operation requires a function to get the changeset, and a function to perform the operation.
If the operation in question is “create”, the standard approach is to name the changeset function create_changeset, but that’s just confusing; am I getting a changeset for the “create” operation, or am I creating a generic changeset?
I prefer the following conventions.
Git’s pre-push hooks are a great way to enforce code quality. They’re also a pain when you just want to push some in-progress work to a branch.
Going into this project, I assumed the biggest problem would be how to retrieve the status of each product. As ever, the real problem was naming things.
The plan has always been to launch Happy Stack with email notifications; that’s it. I have lots of other notification channels planned of course, but email is still the most universal.
Your TypeScript application uses relative imports. Every time you move a file, the imports break. You’ve configured path mapping, and now things break in an entirely new way.
You need to check a date using Chai. You also need to account for the test execution time.
You need to validate the checksum of a file. Rather than Googling it for the hundredth time, you decide to write a note to self, in the hope it will stick this time.
Every ObjectId includes an embedded timestamp. No need for a separate “created at” property.
Tailwind 1.3 added the ability to specify a line-height for each font-size in your config file.
Gatsby supports TypeScript out-the-box. Unfortunately, the official solution has several shortcomings which limit its usefulness. There is a better way.
You can use JavaScript’s optional chaining operator multiple times within a statement. That is useful if you need to access nested properties which may not exist.
You’re using Decap CMS to manage the content of your Gatsby-powered website. The default Decap CMS preview displays every field, including metadata. That probably isn’t what you want.
JSON Schema includes the multipleOf keyword. This is very useful for checking that a number is rounded to a specific number of decimal places.
You can apply a “highlighter” effect to text using background gradients.
Your site uses Gatsby and Netlify CMS. Tailwind and PostCSS take care of the styling. You run gatsby develop, and encounter a cryptic error message.
Migrate is a very useful migration framework for Node. Unfortunately, its documentation is lacking in places. Here are a couple of handy options not covered by the README.
sudo -u <user> <command> doesn’t inherit the user’s environment. Here’s how to fix that.
Type guards let you provide TypeScript with more information about a variable’s type. Type guards are especially useful when working with a variable which may be undefined.
Chai lets you assert that some code throws an error. The key is to pass the test subject to expect, not the test result.
You can disable ESLint for a single line, a block of code, or an entire file. Wherever possible, specify the rule or rules you wish to disable.
Don’t use “deep equals” when comparing arrays with Chai; it depends on element order. Examine the array members instead.
How to find documents according to the size of an array field.
TypeScript’s strict type checking can cause problems when working with numeric environment variables. Here’s a solution.
VS Code has the concept of code actions. When a code action is available, VS Code displays a small lightbulb icon nearby 💡. Clicking on the lightbulb displays a list of available actions.
Assume we have two JavaScript arrays, alpha and bravo. We need to determine which items appear in alpha, but not in bravo.
By default, a Node.js stream expects to operate on a Buffer or a Uint8Array. We can override this by telling the stream to use “object mode”.
When working on a codebase with a lot of unstaged or untracked changes, the default git status output is unhelpful.
Typing clear at a command prompt clears the screen. Simple enough. Unfortunately, it’s no help if you’re inside a REPL, or a long-running process.
If you’re accustomed to PHP’s logical operators, JavaScript’s implementation can be confusing.
Avoid Array.prototype.push. It modifies the array in place, which is asking for trouble. It also returns the array length, not the modified array, which is plain confusing.
Using the Vim extension for Visual Studio Code? Here’s how to quickly find files and folders in the Explorer.
JSON Schema is a very useful tool for validating API requests. Sadly it’s not immune to the quagmire of pedantry that is URL validation.
The default “recurse depth” of console.dir is 2. This is rarely what I want.
Faker is a useful JavaScript library for generating dummy data. For example, faker.random.words(3) generates a string containing three random words. But what if you want to generate an array of random words?
There are countless blog posts detailing how to split a JavaScript array into chunks. However, many of these solutions fail with arrays containing hundreds of thousands of items.
You can generate a pseudo-random boolean in JavaScript or PHP using a single line of code. No, you do not need to install yet another idiotic JavaScript package.
Statecharts are a very useful tool for modelling complex workflows in your application.
TypeScript doesn’t always play nicely with object bracket notation.
The Node CLI supports a “require” flag, which allows you to preload a module when running Node.
Node isn’t managed by npm. As such, there’s no guarantee that running npm install -D @types/node will install the correct type definitions for your version of Node.
Use ‘generics’ when writing a TypeScript function which works with a variety of types.
Many PHP module names include the PHP version. This makes it difficult to write portable bash scripts. Here’s a fix.
Nova uses Laravel policies to manage resource authorisation. This can be problematic when it comes to resource actions.
The Composer documentation provides instructions for using a private GitHub or BitBucket repository as a dependency. This note covers GitLab.
GitLab’s opinion of what constitutes valid YAML differs from the official spec. Booleans, in particular, are problematic.
How to conditionally apply Laravel validation rules, even when you don’t have access to a validator instance.
When you define a resource, Laravel Nova makes an educated guess regarding its URL slug. You can override the default slug by implementing the uriKey method. Here’s how.
A quick and easy way to ensure your tests don’t have any unwanted side-effects is to randomise the order in which they run. PHPUnit makes this easy.
Laravel makes heavy use of the Macroable trait throughout its codebase, but the official docs only mention it in passing. Let’s dig in.
Route model binding is a very useful Laravel feature. But what happens if you have an endpoint which needs to support multiple, comma-delimited IDs? Route collection binding to the rescue.
The standard method for removing a global scope from an Eloquent model is a little clunky. We can do better.
I recently found myself with the need to add a custom method to the LengthAwarePaginator class. Not a problem, I thought, I’ll write a quick macro. A fine solution, but for the fact the LengthAwarePaginator isn’t “macroable”. Or so it would seem at first glance.
A simple, performant solution for eager-loading Eloquent relationships, when you’re only interested in one or two specific properties on the related model.
Eloquent makes it easy to respond to certain key points in the lifecycle of a model instance, by exposing events such as creating, updating, and deleted.
There’s an important gotcha to remember when working with Eloquent and default database values: if you create a new model instance, without overriding a default value, the attribute will not be set.