mirror of
https://github.com/jbranchaud/til
synced 2026-01-18 14:38:01 +00:00
Compare commits
19 Commits
6e3d2f63cc
...
c5db038daa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5db038daa | ||
|
|
01c9c0d19b | ||
|
|
c06bb2ea7b | ||
|
|
7dad6508d0 | ||
|
|
5bcdbbb3c7 | ||
|
|
41f5b526d2 | ||
|
|
e974a184c6 | ||
|
|
c832b9a70d | ||
|
|
42854fdc38 | ||
|
|
eff2c548cd | ||
|
|
1b229b39f1 | ||
|
|
2543651ec0 | ||
|
|
f3d7cf8a06 | ||
|
|
72089e11db | ||
|
|
b766f20012 | ||
|
|
505220d9de | ||
|
|
9684c6a6db | ||
|
|
3b0d76e805 | ||
|
|
5365e75267 |
22
README.md
22
README.md
@@ -10,7 +10,7 @@ pairing with smart people at Hashrocket.
|
||||
|
||||
For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186).
|
||||
|
||||
_1408 TILs and counting..._
|
||||
_1424 TILs and counting..._
|
||||
|
||||
---
|
||||
|
||||
@@ -41,6 +41,7 @@ _1408 TILs and counting..._
|
||||
* [jq](#jq)
|
||||
* [Kitty](#kitty)
|
||||
* [Linux](#linux)
|
||||
* [LLM](#llm)
|
||||
* [Mac](#mac)
|
||||
* [MongoDB](#mongodb)
|
||||
* [MySQL](#mysql)
|
||||
@@ -98,6 +99,7 @@ _1408 TILs and counting..._
|
||||
### Brew
|
||||
|
||||
- [Configure Brew Environment Variables](brew/configure-brew-environment-variables.md)
|
||||
- [List All Services Managed By Brew](brew/list-all-services-managed-by-brew.md)
|
||||
|
||||
### Chrome
|
||||
|
||||
@@ -259,6 +261,7 @@ _1408 TILs and counting..._
|
||||
|
||||
- [Accessing a Lost Commit](git/accessing-a-lost-commit.md)
|
||||
- [Add A Range Of Filename To gitignore](git/add-a-range-of-filenames-to-gitignore.md)
|
||||
- [Add Only Tracked Files From A Directory](git/add-only-tracked-files-from-a-directory.md)
|
||||
- [Amend Author Of Previous Commit](git/amend-author-of-previous-commit.md)
|
||||
- [Auto-Squash Those Fixup Commits](git/auto-squash-those-fixup-commits.md)
|
||||
- [Caching Credentials](git/caching-credentials.md)
|
||||
@@ -408,6 +411,7 @@ _1408 TILs and counting..._
|
||||
|
||||
### Inngest
|
||||
|
||||
- [Ensure Lookup Can Be Retried](inngest/ensure-lookup-can-be-retried.md)
|
||||
- [Exit Function Early Without Retries](inngest/exit-function-early-without-retries.md)
|
||||
|
||||
### Internet
|
||||
@@ -437,6 +441,7 @@ _1408 TILs and counting..._
|
||||
- [Computed Property Names In ES6](javascript/computed-property-names-in-es6.md)
|
||||
- [Conditionally Include Pairs In An Object](javascript/conditionally-include-pairs-in-an-object.md)
|
||||
- [Configure Jest To Run A Test Setup File](javascript/configure-jest-to-run-a-test-setup-file.md)
|
||||
- [Convert Seconds To Date Object](javascript/convert-seconds-to-date-object.md)
|
||||
- [Create A Cancelable Promise With PCancelable](javascript/create-a-cancelable-promise-with-pcancelable.md)
|
||||
- [Create An Array Containing 1 To N](javascript/create-an-array-containing-1-to-n.md)
|
||||
- [Create An Object With No Properties](javascript/create-an-object-with-no-properties.md)
|
||||
@@ -553,6 +558,11 @@ _1408 TILs and counting..._
|
||||
- [Show Used And Available System Memory](linux/show-used-and-available-system-memory.md)
|
||||
- [Upgrading Ubuntu](linux/upgrading-ubuntu.md)
|
||||
|
||||
### LLM
|
||||
|
||||
- [Send cURL To Claude Text Completion API](llm/send-curl-to-claude-text-completion-api.md)
|
||||
- [Use The llm CLI With Claude Models](llm/use-the-llm-cli-with-claude-models.md)
|
||||
|
||||
### Mac
|
||||
|
||||
- [Access All Screen And Video Capture Options](mac/access-all-screen-and-video-capture-options.md)
|
||||
@@ -664,6 +674,7 @@ _1408 TILs and counting..._
|
||||
- [Capitalize All The Words](postgres/capitalize-all-the-words.md)
|
||||
- [Change The Current Directory For psql](postgres/change-the-current-directory-for-psql.md)
|
||||
- [Change The Owner Of A Sequence](postgres/change-the-owner-of-a-sequence.md)
|
||||
- [Check If Clusters Are Upgrade Compatible](postgres/check-if-clusters-are-upgrade-compatible.md)
|
||||
- [Check If The Local Server Is Running](postgres/check-if-the-local-server-is-running.md)
|
||||
- [Check If User Role Exists For Database](postgres/check-if-user-role-exists-for-database.md)
|
||||
- [Check Table For Any Oprhaned Records](postgres/check-table-for-any-orphaned-records.md)
|
||||
@@ -680,6 +691,7 @@ _1408 TILs and counting..._
|
||||
- [Count How Many Records There Are Of Each Type](postgres/count-how-many-records-there-are-of-each-type.md)
|
||||
- [Count Records By Type](postgres/count-records-by-type.md)
|
||||
- [Count The Number Of Trues In An Aggregate Query](postgres/count-the-number-of-trues-in-an-aggregate-query.md)
|
||||
- [Create A Cluster In A Specific Data Directory](postgres/create-a-cluster-in-a-specific-data-directory.md)
|
||||
- [Create A Composite Primary Key](postgres/create-a-composite-primary-key.md)
|
||||
- [Create A Table From The Structure Of Another](postgres/create-a-table-from-the-structure-of-another.md)
|
||||
- [Create An Index Across Two Columns](postgres/create-an-index-across-two-columns.md)
|
||||
@@ -727,6 +739,7 @@ _1408 TILs and counting..._
|
||||
- [Group By The Result Of A Function Call](postgres/group-by-the-result-of-a-function-call.md)
|
||||
- [Idempotent Inserts](postgres/idempotent-inserts.md)
|
||||
- [Include All Queries In The Log File](postgres/include-all-queries-in-the-log-file.md)
|
||||
- [Include Columns In A Covering Index](postgres/include-columns-in-a-covering-index.md)
|
||||
- [Include Multiple Tables In A pg_dump](postgres/include-multiple-tables-in-a-pg-dump.md)
|
||||
- [Insert A Bunch Of Records With Generate Series](postgres/insert-a-bunch-of-records-with-generate-series.md)
|
||||
- [Insert Just The Defaults](postgres/insert-just-the-defaults.md)
|
||||
@@ -819,6 +832,7 @@ _1408 TILs and counting..._
|
||||
- [Access Instance Variables](python/access-instance-variables.md)
|
||||
- [Create A Dummy DataFrame In Pandas](python/create-a-dummy-dataframe-in-pandas.md)
|
||||
- [Test A Function With Pytest](python/test-a-function-with-pytest.md)
|
||||
- [Use pipx To Install End User Apps](python/use-pipx-to-install-end-user-apps.md)
|
||||
|
||||
### Rails
|
||||
|
||||
@@ -879,6 +893,7 @@ _1408 TILs and counting..._
|
||||
- [Get ActiveRecord Attribute Directly From Database](rails/get-active-record-attribute-directly-from-database.md)
|
||||
- [Get An Array Of Values From The Database](rails/get-an-array-of-values-from-the-database.md)
|
||||
- [Get An Empty ActiveRecord Relation](rails/get-an-empty-activerecord-relation.md)
|
||||
- [Get Formatted UTC Offset Value](rails/get-formatted-utc-offset-value.md)
|
||||
- [Get Help With A Rails App Update](rails/get-help-with-a-rails-app-update.md)
|
||||
- [Get The Column Names For A Model](rails/get-the-column-names-for-a-model.md)
|
||||
- [Get The Current Time](rails/get-the-current-time.md)
|
||||
@@ -894,6 +909,7 @@ _1408 TILs and counting..._
|
||||
- [Load A File When Starting Rails Console](rails/load-a-file-when-starting-rails-console.md)
|
||||
- [Load Records In Batches With find_each](rails/load-records-in-batches-with-find-each.md)
|
||||
- [Log SQL Queries Executed By ActiveRecord](rails/log-sql-queries-executed-by-activerecord.md)
|
||||
- [Look Up Time Zone Info For Identifier](rails/look-up-time-zone-info-for-identifier.md)
|
||||
- [Mark A Migration As Irreversible](rails/mark-a-migration-as-irreversible.md)
|
||||
- [Make A String Attribute Easy To Inquire About](rails/make-a-string-attribute-easy-to-inquire-about.md)
|
||||
- [Make ActionMailer Synchronous In Test](rails/make-action-mailer-synchronous-in-test.md)
|
||||
@@ -1114,6 +1130,7 @@ _1408 TILs and counting..._
|
||||
- [Defaulting To Frozen String Literals](ruby/defaulting-to-frozen-string-literals.md)
|
||||
- [Define A Custom RSpec Matcher](ruby/define-a-custom-rspec-matcher.md)
|
||||
- [Define A Method On A Struct](ruby/define-a-method-on-a-struct.md)
|
||||
- [Define Multiline Strings With Heredocs](ruby/define-multiline-strings-with-heredocs.md)
|
||||
- [Destructure The First Item From An Array](ruby/destructure-the-first-item-from-an-array.md)
|
||||
- [Destructuring Arrays In Blocks](ruby/destructuring-arrays-in-blocks.md)
|
||||
- [Disassemble Some Codes](ruby/disassemble-some-codes.md)
|
||||
@@ -1137,6 +1154,7 @@ _1408 TILs and counting..._
|
||||
- [Generate Ruby Version And Gemset Files With RVM](ruby/generate-ruby-version-and-gemset-files-with-rvm.md)
|
||||
- [Get Info About Your RubyGems Environment](ruby/get-info-about-your-ruby-gems-environment.md)
|
||||
- [Get The Output Of Running A System Program](ruby/get-the-output-of-running-a-system-program.md)
|
||||
- [Get UTC Offset For Different Time Zones](ruby/get-utc-offset-for-different-time-zones.md)
|
||||
- [Identify Outdated Gems](ruby/identify-outdated-gems.md)
|
||||
- [If You Detect None](ruby/if-you-detect-none.md)
|
||||
- [Iterate With An Offset Index](ruby/iterate-with-an-offset-index.md)
|
||||
@@ -1612,6 +1630,7 @@ _1408 TILs and counting..._
|
||||
- [Add The VSCode CLI To Your Path](vscode/add-the-vscode-cli-to-your-path.md)
|
||||
- [Advance Through Search Results](vscode/advance-through-search-results.md)
|
||||
- [Enable Breadcrumbs For Version 1.26 Release](vscode/enable-breadcrumbs-for-version-126-release.md)
|
||||
- [Find The Location Of User Settings JSON File](vscode/find-the-location-of-user-settings-json-file.md)
|
||||
- [Open An Integrated Terminal Window](vscode/open-an-integrated-terminal-window.md)
|
||||
- [Pop Open The Quick Fix Window](vscode/pop-open-the-quick-fix-window.md)
|
||||
- [Step Through Project-Wide Search Results](vscode/step-through-project-wide-search-results.md)
|
||||
@@ -1629,6 +1648,7 @@ _1408 TILs and counting..._
|
||||
### Workflow
|
||||
|
||||
- [Add Subtitles To Existing Mux Video Asset](workflow/add-subtitles-to-existing-mux-video-asset.md)
|
||||
- [Access 1Password Credential From CLI](workflow/access-1password-credential-from-cli.md)
|
||||
- [Change Window Name In iTerm](workflow/change-window-name-in-iterm.md)
|
||||
- [Convert An ePub Document To PDF On Mac](workflow/convert-an-epub-document-to-pdf-on-mac.md)
|
||||
- [Create A Local Sanity Dataset Backup](workflow/create-a-local-sanity-dataset-backup.md)
|
||||
|
||||
28
brew/list-all-services-managed-by-brew.md
Normal file
28
brew/list-all-services-managed-by-brew.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# List All Services Managed By Brew
|
||||
|
||||
Daemonized services, such as PostgreSQL, can be installed and managed with
|
||||
Homebrew. Under the hood `brew` uses `launchctl` on Mac to manage these
|
||||
services — i.e. starting, restarting, and stopping them.
|
||||
|
||||
Assuming you've already installed some services, you can run `brew services
|
||||
list` to see what services there are and what their current status is.
|
||||
|
||||
```bash
|
||||
$ brew services list
|
||||
Name Status User File
|
||||
mailhog none
|
||||
mysql none
|
||||
postgresql@11 started jbranchaud ~/Library/LaunchAgents/homebrew.mxcl.postgresql@11.plist
|
||||
postgresql@13 none
|
||||
postgresql@16 none
|
||||
unbound none
|
||||
```
|
||||
|
||||
This is the default behavior if you just run `brew services` without a subcommand.
|
||||
|
||||
This is helpful if you are, for instance, trying to see which PostgreSQL server
|
||||
version you are currently running and which other ones are available to run. I
|
||||
might then issue a `stop` to `postgresql@11` so that I can then `start` the
|
||||
`postgresql@16` service.
|
||||
|
||||
See `brew services --help` for more details.
|
||||
26
git/add-only-tracked-files-from-a-directory.md
Normal file
26
git/add-only-tracked-files-from-a-directory.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Add Only Tracked Files From A Directory
|
||||
|
||||
The two extremes of staging files in a git repo are to either selectively pick
|
||||
each individual chunk of changes with `git add --patch` (my preference!) or to
|
||||
run `git add -A` to add everything.
|
||||
|
||||
Now let's say I have large directory full of files that get generated during
|
||||
test runs. Most of these files are tracked (already checked in to the
|
||||
repository). There are also many new files generated as part of the most recent
|
||||
test run.
|
||||
|
||||
I want to staging the changes to files that are already tracked, but hold off
|
||||
on doing anything with the new files.
|
||||
|
||||
Running `git add spec/cassettes` won't do the track because that will pull in
|
||||
everything. Running `git add --patch spec/cassettes` will take long and be
|
||||
tedious. Instead what I want is the `-u` flag. It's short for _update_ which
|
||||
means it will only stage already tracked files.
|
||||
|
||||
```bash
|
||||
$ git add -u spec/cassettes
|
||||
```
|
||||
|
||||
That will stage every change to any already known files in `spec/cassettes`.
|
||||
|
||||
See `man git-add` for more details.
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
Sometimes you want to view a file on another branch (without switching
|
||||
branches). That is, you want to view the version of that file as it exists
|
||||
on that branch. `git show` can help. If your branch is named `my_feature` and
|
||||
on that branch. `git show` can help. If the other branch is named `some_branch` and
|
||||
the file you want to see is `app/models/users.rb`, then your command should
|
||||
look like this:
|
||||
|
||||
```
|
||||
$ git show my_feature:app/models/users.rb
|
||||
$ git show some_branch:app/models/users.rb
|
||||
```
|
||||
|
||||
You can even tab-complete the filename as you type it out.
|
||||
|
||||
See `man git-show` for more details.
|
||||
|
||||
[source](http://stackoverflow.com/questions/7856416/view-a-file-in-a-different-git-branch-without-changing-branches)
|
||||
[source](https://stackoverflow.com/questions/7856416/view-a-file-in-a-different-git-branch-without-changing-branches)
|
||||
|
||||
57
inngest/ensure-lookup-can-be-retried.md
Normal file
57
inngest/ensure-lookup-can-be-retried.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Ensure Lookup Can Be Retried
|
||||
|
||||
A common thing to do in a workflow step is to look up a record. This might be a
|
||||
record that was created or updated around the time that the workflow was
|
||||
triggered.
|
||||
|
||||
You need to be sure the record was found before proceeding. That might end up
|
||||
looking like this:
|
||||
|
||||
```typescript
|
||||
export default inngest.createFunction(
|
||||
{ id: "record-user-purchase" },
|
||||
{ event: "app/record.purchase" },
|
||||
async ({ event, step }) => {
|
||||
const checkoutSession =
|
||||
await step.run("find checkout session", async () => {
|
||||
const cs = provider.lookupSession(event.checkoutSessionId)
|
||||
|
||||
return cs;
|
||||
});
|
||||
|
||||
if(!checkoutSession) {
|
||||
throw new Error('Checkout session not found')
|
||||
}
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
This approach has a subtle problem which is that the error for a missing
|
||||
checkout session is raised _outside_ the step that sets `checkoutSession`. As
|
||||
inngest does a series of retries, the memorized `checkoutSession` step won't be
|
||||
rerun and the error will continue to be thrown.
|
||||
|
||||
It is better to raise the error _within_ the lookup step:
|
||||
|
||||
```typescript
|
||||
export default inngest.createFunction(
|
||||
{ id: "record-user-purchase" },
|
||||
{ event: "app/record.purchase" },
|
||||
async ({ event, step }) => {
|
||||
const checkoutSession =
|
||||
await step.run("find checkout session", async () => {
|
||||
const cs = provider.lookupSession(event.checkoutSessionId)
|
||||
|
||||
if(!cs) {
|
||||
throw new Error('Checkout session not found')
|
||||
}
|
||||
|
||||
return cs;
|
||||
});
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
If the checkout session is missing on the first couple tries, the step will
|
||||
have a chance to retry the lookup and maybe eventually find what it is looking
|
||||
for.
|
||||
32
javascript/convert-seconds-to-date-object.md
Normal file
32
javascript/convert-seconds-to-date-object.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Convert Seconds To Date Object
|
||||
|
||||
Let's say you have an integer that represents the number of seconds since the
|
||||
unix epoch. This is a reasonably common way for systems to represent a date.
|
||||
|
||||
For example, `1713350171` is an _Expiration Date_ I just got from an API.
|
||||
|
||||
But how do we know what date that actually represents and how can we get a
|
||||
JavaScript `Date` object from that value?
|
||||
|
||||
The `new Date()` constructor can produce a date object given an integer. That
|
||||
integer is not supposed to be seconds since the unix epoch though. See what we
|
||||
get here:
|
||||
|
||||
```javascript
|
||||
> new Date(1713350171)
|
||||
1970-01-20T19:55:50.171Z
|
||||
```
|
||||
|
||||
Something is off. The integer that you pass to `new Date()` needs to be the
|
||||
_number of milliseconds_ since the unix epoch. We can get there by multiplying
|
||||
our _seconds_ value by `1000`.
|
||||
|
||||
```javascript
|
||||
> new Date(1713350171 * 1000)
|
||||
2024-04-17T10:36:11.000Z
|
||||
```
|
||||
|
||||
Not only can we, as humans, read that date, but we have a `Date` object that we
|
||||
can use within our program.
|
||||
|
||||
Note: if you execute `Date.now()`, the value you get is in milliseconds.
|
||||
40
llm/send-curl-to-claude-text-completion-api.md
Normal file
40
llm/send-curl-to-claude-text-completion-api.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Send cURL To Claude Text Completion API
|
||||
|
||||
Here is how we can make a `cURL` (`POST`) request to the Claude text completion
|
||||
API. It requires already having a Claude API account with (paid) credits. At
|
||||
this time, you can get $5 in free credits to try it out.
|
||||
|
||||
Assuming all that, we can grab an API key, store it somewhere safe and
|
||||
accessible like 1Password, and then start formatting a request.
|
||||
|
||||
We need to specify a couple headers as well as `POST` body parameters.
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: $(op item get "Anthropic Claude API Key" --field credential)" \
|
||||
-H "anthropic-version: 2023-06-01" \
|
||||
-d \
|
||||
'{
|
||||
"model": "claude-2.1",
|
||||
"max_tokens_to_sample": 1024,
|
||||
"prompt": "Human: Show me an example of a simple Ruby program.\n\nAssistant:"
|
||||
}' \
|
||||
https://api.anthropic.com/v1/complete
|
||||
```
|
||||
|
||||
The required headers are:
|
||||
- `"Content-Type: application/json"`
|
||||
- `x-api-key` with our API key
|
||||
- `"anthropic-version: 2023-06-01"` (the latest Anthropic API version)
|
||||
|
||||
Then, in the body, we specify:
|
||||
- the `model` (e.g. `claude-2.1`)
|
||||
- the max number of tokens you want the model to use
|
||||
- a prompt that starts with `Human:` and then prompts the `Assistant:`
|
||||
|
||||
Note: this is a legacy API and the [Messages
|
||||
API](https://docs.anthropic.com/claude/reference/messages_post) should be
|
||||
preferred.
|
||||
|
||||
[source](https://docs.anthropic.com/claude/reference/complete_post)
|
||||
26
llm/use-the-llm-cli-with-claude-models.md
Normal file
26
llm/use-the-llm-cli-with-claude-models.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Use The llm CLI With Claude Models
|
||||
|
||||
[Simon Willison's `llm`](https://llm.datasette.io/en/stable/index.html) can be
|
||||
used with a bunch of different models (local and API). The whole thing is
|
||||
plugin driven. To use a specific model, you'll need to install the plugin for
|
||||
it. For instance, to use the [Claude 3 family of
|
||||
models](https://www.anthropic.com/news/claude-3-family) you need to install
|
||||
`llm-claude-3`.
|
||||
|
||||
```bash
|
||||
$ llm install llm-claude-3
|
||||
```
|
||||
|
||||
Then when prompting `llm`, specify which of the Claude models you want to use —
|
||||
`claude-3-haiku`, `claude-3-sonnet`, or `claude-3-opus` — with the `-m` flag:
|
||||
|
||||
```bash
|
||||
$ llm \
|
||||
-m claude-3-haiku \
|
||||
--key $CLAUDE_API_KEY \
|
||||
'Show me the SQL query to create a cocktails table.'
|
||||
```
|
||||
|
||||
Note: instead of adding my Claude API key to the key store, I've opted to
|
||||
include it with the `--key` flag via an environment variable that I've set
|
||||
ahead of time.
|
||||
42
postgres/check-if-clusters-are-upgrade-compatible.md
Normal file
42
postgres/check-if-clusters-are-upgrade-compatible.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Check If Clusters Are Upgrade Compatible
|
||||
|
||||
One of the ways to upgrade a PostgreSQL database from one server version to
|
||||
another is to use the built-in `pg_upgrade` command. This can be faster and
|
||||
require fewer manual steps than something like a `pg_dump` and `pg_restore`.
|
||||
|
||||
However, before you run the `pg_upgrade` command for real, you should check
|
||||
that the target database is compatible with the current database. To do this,
|
||||
write your `pg_update` command with all the flags you need and then tack on
|
||||
`--check` at the end. This does a dry-run reporting the results of a series of
|
||||
consistency checks.
|
||||
|
||||
Here is what a successful _check_ looks like:
|
||||
|
||||
```bash
|
||||
$ /usr/local/opt/postgresql@13/bin/pg_upgrade \
|
||||
--old-bindir $HOME/.asdf/installs/postgres/12.3/bin \
|
||||
--new-bindir /usr/local/opt/postgresql@13/bin \
|
||||
--old-datadir $HOME/.asdf/installs/postgres/12.3/data \
|
||||
--new-datadir ./postgres/data \
|
||||
--check
|
||||
|
||||
Performing Consistency Checks
|
||||
-----------------------------
|
||||
Checking cluster versions ok
|
||||
Checking database user is the install user ok
|
||||
Checking database connection settings ok
|
||||
Checking for prepared transactions ok
|
||||
Checking for system-defined composite types in user tables ok
|
||||
Checking for reg* data types in user tables ok
|
||||
Checking for contrib/isn with bigint-passing mismatch ok
|
||||
Checking for presence of required libraries ok
|
||||
Checking database user is the install user ok
|
||||
Checking for prepared transactions ok
|
||||
Checking for new cluster tablespace directories ok
|
||||
|
||||
*Clusters are compatible*
|
||||
```
|
||||
|
||||
If there is an issue, such as mismatched collation settings, the output will
|
||||
report the issue. You'll have to decide how to resolve those on a case-by-case
|
||||
basis.
|
||||
46
postgres/create-a-cluster-in-a-specific-data-directory.md
Normal file
46
postgres/create-a-cluster-in-a-specific-data-directory.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Create A Cluster In A Specific Data Directory
|
||||
|
||||
Let's say I want to create a PostgreSQL cluster near my app. So, I create a
|
||||
`postgres/data` directory next to my app. Then I run the `initdb` command
|
||||
pointing at that directory and specifying the UTF-8 locale.
|
||||
|
||||
Here is what that looks like:
|
||||
|
||||
```bash
|
||||
$ /usr/local/opt/postgresql@13/bin/initdb -D postgres/data --locale=en_US.UTF-8
|
||||
|
||||
The files belonging to this database system will be owned by user "jbranchaud".
|
||||
This user must also own the server process.
|
||||
|
||||
The database cluster will be initialized with locale "en_US.UTF-8".
|
||||
The default database encoding has accordingly been set to "UTF8".
|
||||
The default text search configuration will be set to "english".
|
||||
|
||||
Data page checksums are disabled.
|
||||
|
||||
fixing permissions on existing directory postgres/data ... ok
|
||||
creating subdirectories ... ok
|
||||
selecting dynamic shared memory implementation ... posix
|
||||
selecting default max_connections ... 100
|
||||
selecting default shared_buffers ... 128MB
|
||||
selecting default time zone ... America/Chicago
|
||||
creating configuration files ... ok
|
||||
running bootstrap script ... ok
|
||||
performing post-bootstrap initialization ... ok
|
||||
syncing data to disk ... ok
|
||||
|
||||
initdb: warning: enabling "trust" authentication for local connections
|
||||
You can change this by editing pg_hba.conf or using the option -A, or
|
||||
--auth-local and --auth-host, the next time you run initdb.
|
||||
|
||||
Success. You can now start the database server using:
|
||||
|
||||
'/usr/local/opt/postgresql@13/bin/pg_ctl' -D postgres/data -l logfile start
|
||||
```
|
||||
|
||||
As stated at the end of the command's output, I can run the `postgres` server
|
||||
with that data directory with:
|
||||
|
||||
```bash
|
||||
$ '/usr/local/opt/postgresql@13/bin/pg_ctl' -D postgres/data -l logfile start
|
||||
```
|
||||
33
postgres/include-columns-in-a-covering-index.md
Normal file
33
postgres/include-columns-in-a-covering-index.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Include Columns In A Covering Index
|
||||
|
||||
A _covering index_ is a special type of B-Tree index that, in addition to
|
||||
indexing on a certain field, also _includes_ one or more columns as extra data
|
||||
in the leaves of the tree. When created correctly, this can speed up the
|
||||
queries it targets by achieving an _index-only scan_.
|
||||
|
||||
Let's say we have a frequently run query on a large `events` table that looks
|
||||
like this:
|
||||
|
||||
```sql
|
||||
select user_id, identifier, type
|
||||
from events
|
||||
where user_id = $1;
|
||||
```
|
||||
|
||||
Here is what it looks like to create an index for this query with the `include`
|
||||
keyword:
|
||||
|
||||
```sql
|
||||
create index user_id_on_events_idx
|
||||
on (user_id)
|
||||
include (identifier, type);
|
||||
```
|
||||
|
||||
An index on its own can already cause a significant speed up to the queries it
|
||||
targets, but may still need to retrieve some `select` attributes from the
|
||||
table. For hot-path queries with a set of specific columns always included in
|
||||
the select, there can be significant additional speed ups by having the index
|
||||
_cover_ those columns.
|
||||
|
||||
For more details, check out [A Close Look At The Index Include
|
||||
Clause](https://use-the-index-luke.com/blog/2019-04/include-columns-in-btree-indexes).
|
||||
31
python/use-pipx-to-install-end-user-apps.md
Normal file
31
python/use-pipx-to-install-end-user-apps.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Use pipx To Install End User Apps
|
||||
|
||||
The [`pipx`](https://pipx.pypa.io/stable/) tool is an installer for the python
|
||||
ecosystem. It differs from `pip` in that it is for installing end-user
|
||||
applications and it does so in isolated environments.
|
||||
|
||||
You can install `pipx` with an OS-specific installer like Homebrew:
|
||||
|
||||
```bash
|
||||
$ brew install pipx
|
||||
```
|
||||
|
||||
Ensure `pipx`-installed apps are on your path:
|
||||
|
||||
```bash
|
||||
$ pipx ensurepath
|
||||
```
|
||||
|
||||
Then use `pipx` to install programs like
|
||||
[`cowsay`](https://pypi.org/project/cowsay/) or
|
||||
[`llm`](https://llm.datasette.io/en/stable/setup.html):
|
||||
|
||||
```bash
|
||||
$ pipx install llm
|
||||
|
||||
$ which llm
|
||||
/Users/jbranchaud/.local/bin/llm
|
||||
|
||||
$ llm --version
|
||||
llm, version 0.13.1
|
||||
```
|
||||
37
rails/get-formatted-utc-offset-value.md
Normal file
37
rails/get-formatted-utc-offset-value.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Get Formatted UTC Offset Value
|
||||
|
||||
The UTC offset (during DST) for Chicago is `-05:00`. And for Newfoundland it is
|
||||
`-02:30`.
|
||||
|
||||
Rails has an [`ActiveSupport::TimeZone`
|
||||
module](https://api.rubyonrails.org/v7.1.3.2/classes/ActiveSupport/TimeZone.html#method-c-seconds_to_utc_offset)
|
||||
that can turn the UTC offset in seconds into this formatted value.
|
||||
|
||||
```ruby
|
||||
> chicago = TZInfo::Timezone.get('America/Chicago')
|
||||
=> #<TZInfo::DataTimezone: America/Chicago>
|
||||
> ActiveSupport::TimeZone.seconds_to_utc_offset(chicago.utc_offset)
|
||||
=> "-05:00"
|
||||
|
||||
> newfoundland = TZInfo::Timezone.get('America/St_Johns')
|
||||
=> #<TZInfo::DataTimezone: America/St_Johns>
|
||||
> ActiveSupport::TimeZone.seconds_to_utc_offset(newfoundland.utc_offset)
|
||||
=> "-02:30"
|
||||
```
|
||||
|
||||
The underlying `tzinfo` gem is DST-aware and its database even knows which time
|
||||
zone identifiers don't observe DST, so you can run this anytime of the year and
|
||||
expect reliable results.
|
||||
|
||||
Here is another way at this:
|
||||
|
||||
```ruby
|
||||
> chicago = TZInfo::Timezone.get('America/Chicago')
|
||||
=> #<TZInfo::DataTimezone: America/Chicago>
|
||||
> ActiveSupport::TimeZone[chicago.name]
|
||||
=> #<ActiveSupport::TimeZone:0x00000001099d8140 @name="America/Chicago", @tzinfo=#<TZInfo::DataTimezone: America/Chicago>, @utc_offset=nil>
|
||||
> ActiveSupport::TimeZone[chicago.name].formatted_offset
|
||||
=> "-06:00"
|
||||
> ActiveSupport::TimeZone[chicago.name].formatted_offset(false)
|
||||
=> "-0600"
|
||||
```
|
||||
33
rails/look-up-time-zone-info-for-identifier.md
Normal file
33
rails/look-up-time-zone-info-for-identifier.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Look Up Time Zone Info For Identifier
|
||||
|
||||
The `ActiveSupport::TimeZone` class overrides the `#[]` method to be a lookup
|
||||
mechanism for IANA Time Zone Identifier strings. These are strings like
|
||||
`America/Chicago` (or anything else listed under `TZInfo::Timezone.all`).
|
||||
|
||||
Let's get an instance for `America/Chicago`.
|
||||
|
||||
```ruby
|
||||
> chi = ActiveSupport::TimeZone['America/Chicago']
|
||||
=> #<ActiveSupport::TimeZone:0x00000001099d8140
|
||||
@name="America/Chicago",
|
||||
@tzinfo=#<TZInfo::DataTimezone: America/Chicago>,
|
||||
@utc_offset=nil>
|
||||
```
|
||||
|
||||
Notice it has a `tzinfo` instance variable that we can access. That object
|
||||
contains all kinds of useful things.
|
||||
|
||||
```ruby
|
||||
> chi.tzinfo.name
|
||||
=> "America/Chicago"
|
||||
> chi.tzinfo.friendly_identifier
|
||||
=> "America - Chicago"
|
||||
> chi.tzinfo.abbr
|
||||
=> "CDT"
|
||||
> chi.tzinfo.utc_offset
|
||||
=> -18000
|
||||
> chi.tzinfo.dst?
|
||||
=> true
|
||||
```
|
||||
|
||||
All of these and more. Run `ls chi.tzinfo` in a `pry` session to see what else.
|
||||
47
ruby/define-multiline-strings-with-heredocs.md
Normal file
47
ruby/define-multiline-strings-with-heredocs.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Define Multiline Strings With Heredocs
|
||||
|
||||
[A _heredoc_ (_here document_) is a special ruby
|
||||
syntax](https://ruby-doc.org/core-2.5.0/doc/syntax/literals_rdoc.html#label-Here+Documents)
|
||||
for defining formatted multiline strings. These are useful for any situation
|
||||
where you need to define a block of text where newlines and indentation are
|
||||
preserved -- e.g. output an error, help message, or some formatted SQL.
|
||||
|
||||
The standard syntax is defined with `<<` and some uppercase identifier (e.g.
|
||||
`TXT`, `DOC`, `SQL`, etc.) to open and close the multiline string.
|
||||
|
||||
```ruby
|
||||
def lookup_team(team_id)
|
||||
query = <<SQL
|
||||
select users.id from users
|
||||
join teams
|
||||
on teams.id = users.team_id
|
||||
where teams.id = #{team_id}
|
||||
order by created_at desc
|
||||
limit 10;
|
||||
SQL
|
||||
|
||||
team_member_ids = db.execute(query)
|
||||
end
|
||||
```
|
||||
|
||||
With the SQL formatted this way, it is easier to read and we can print/log out
|
||||
this nicely formatted version to make debugging easier.
|
||||
|
||||
Notice that the terminating `SQL` identifier is fully left justified. I find
|
||||
that visually off relative to the indentation of everything else, so I like to
|
||||
use the _indented_ heredoc syntax (`<<-`).
|
||||
|
||||
```ruby
|
||||
def lookup_team(team_id)
|
||||
query = <<-SQL
|
||||
select users.id from users
|
||||
join teams
|
||||
on teams.id = users.team_id
|
||||
where teams.id = #{team_id}
|
||||
order by created_at desc
|
||||
limit 10;
|
||||
SQL
|
||||
|
||||
team_member_ids = db.execute(query)
|
||||
end
|
||||
```
|
||||
42
ruby/get-utc-offset-for-different-time-zones.md
Normal file
42
ruby/get-utc-offset-for-different-time-zones.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Get UTC Offset For Different Time Zones
|
||||
|
||||
The [IANA Time Zone Database](https://www.iana.org/time-zones) uses identifiers
|
||||
like `America/Chicago`, `Asia/Hong_Kong`, `Africa/Nairobi`, etc. as specifiers
|
||||
for notable locations with time zone information.
|
||||
|
||||
> Most timezones correspond to a notable location and the database records all
|
||||
> known clock transitions for that location; some timezones correspond instead
|
||||
> to a fixed UTC offset.
|
||||
—[Theory and pragmatics of the tz code and data](https://data.iana.org/time-zones/theory.html)
|
||||
|
||||
These identifiers can be used to look up time zone details with the [`tzinfo`
|
||||
gem](https://github.com/tzinfo/tzinfo).
|
||||
|
||||
Here is an example of passing one to the `#get` method and then getting the UTC
|
||||
offset in seconds.
|
||||
|
||||
```ruby
|
||||
> require 'tzinfo'
|
||||
|
||||
> mountain = TZInfo::Timezone.get('America/Denver')
|
||||
=> #<TZInfo::DataTimezone: America/Denver>
|
||||
> mountain.utc_offset
|
||||
=> -21600
|
||||
```
|
||||
|
||||
We can even get the base UTC offset that doesn't account for DST:
|
||||
|
||||
```ruby
|
||||
> moutain.base_utc_offset
|
||||
=> -25200
|
||||
```
|
||||
|
||||
Notice, this is the same as the standard offset for a time zone like Phoenix
|
||||
that doesn't observe DST.
|
||||
|
||||
```ruby
|
||||
> phoenix = TZInfo::Timezone.get('America/Phoenix')
|
||||
=> #<TZInfo::DataTimezone: America/Phoenix>
|
||||
> phoenix.utc_offset
|
||||
=> -25200
|
||||
```
|
||||
31
vscode/find-the-location-of-user-settings-json-file.md
Normal file
31
vscode/find-the-location-of-user-settings-json-file.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Find The Location Of User Settings JSON File
|
||||
|
||||
There are a ton ways to customize and fine-tune VS Code. All of the settings
|
||||
have defaults which can then be customized on a workspace and user level.
|
||||
Typically you'll access these files within VS Code via the Command Palette. I
|
||||
was curious though: since it is just a JSON file, surely I can view and modify
|
||||
it with any editor.
|
||||
|
||||
On a Mac, the user-level `settings.json` file is located at
|
||||
`~/Library/Application\ Support/Code/User/settings.json`.
|
||||
|
||||
Open it up and you might see something like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"window.zoomLevel": 1,
|
||||
"workbench.editor.showTabs": "single"
|
||||
}
|
||||
```
|
||||
|
||||
A handful of settings with specific overrides.
|
||||
|
||||
Feel free to edit what is in here or add other settings that you want to set.
|
||||
Just make sure you know what you're doing and that you set valid values.
|
||||
|
||||
The VS Code docs list [the locations of these files on other operating
|
||||
systems](https://code.visualstudio.com/docs/getstarted/settings#_settings-file-locations).
|
||||
|
||||
[source](https://stackoverflow.com/questions/53840644/location-of-vs-code-preferences)
|
||||
29
workflow/access-1password-credential-from-cli.md
Normal file
29
workflow/access-1password-credential-from-cli.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Access 1Password Credential From CLI
|
||||
|
||||
With the `op` CLI, I can store things like API keys and secrets in my 1Password
|
||||
vault and then access them from the command line. This assumes I've already
|
||||
installed the CLI (`brew install 1password-cli`) and connected it to the
|
||||
1Password app via the _Developer_ settings.
|
||||
|
||||
The `op item get` command takes a credential name and returns all the details
|
||||
for the entry with that _Title_. Here is how I can access my _Anthropic Claude
|
||||
API Key_ details.
|
||||
|
||||
```bash
|
||||
$ op item get "Anthropic Claude API Key"
|
||||
```
|
||||
|
||||
With the `--field` flag, I can grab a specific field, such as the `credential`,
|
||||
from that entry.
|
||||
|
||||
```bash
|
||||
$ op item get "Anthropic Claude API Key" --field credential
|
||||
sk-ant-api03-abc......xyz
|
||||
```
|
||||
|
||||
A command like this can be embedded in other commands as a way of referencing
|
||||
secrets without explicitly entering them into your shell history.
|
||||
|
||||
```bash
|
||||
$ curl https://api -H "x-api-key: $(op item get "Anthropic Claude API Key" --field credential)" ...
|
||||
```
|
||||
Reference in New Issue
Block a user