1
0
mirror of https://github.com/jbranchaud/til synced 2026-01-17 05:58:01 +00:00

Compare commits

...

9 Commits

Author SHA1 Message Date
nick-w-nick
265861e249 Merge 295fe153ad into 43ea7acd74 2024-10-21 12:25:05 -04:00
jbranchaud
43ea7acd74 Add Use A Space To Exclude Command Fromm History as a Zsh TIL 2024-10-21 11:21:21 -05:00
jbranchaud
d7d331b688 Add Put Unique Constraint On Generated Column as a Postgres TIL 2024-10-21 11:04:04 -05:00
jbranchaud
b743dc2ac0 Add Exclude AI Overview From Google Search as an Internet TIL 2024-10-20 19:38:08 -05:00
jbranchaud
4a72c63e42 Add Enforce Uniqueness On Column Expression as a Postgres TIL 2024-10-19 19:13:30 -05:00
jbranchaud
431507fd0e Add Send A Message To A Discord Channel as a Workflow TIL 2024-10-18 17:59:08 -05:00
jbranchaud
fb153f35bf Add Postgre Does Not Support Unsigned Integers as a PostgreSQL TIL 2024-10-18 17:43:46 -05:00
jbranchaud
f4ba6a9ef7 Add Override The Global Git Ignore File as a Git TIL 2024-10-18 15:55:40 -05:00
nick-w-nick
295fe153ad added mention of ES6 compatibility
Hello, I've added a small blockquote below the description to indicate that this method of accessing an indefinite number of function arguments has been superseded by the use of the spread operator via rest parameters for ES6+ compatibility.
2022-01-06 11:39:04 -05:00
9 changed files with 269 additions and 1 deletions

View File

@@ -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).
_1472 TILs and counting..._
_1479 TILs and counting..._
---
@@ -326,6 +326,7 @@ _1472 TILs and counting..._
- [List Untracked Files](git/list-untracked-files.md)
- [List Untracked Files For Scripting](git/list-untracked-files-for-scripting.md)
- [Move The Latest Commit To A New Branch](git/move-the-latest-commit-to-a-new-branch.md)
- [Override The Global Git Ignore File](git/override-the-global-git-ignore-file.md)
- [Pick Specific Changes To Stash](git/pick-specific-changes-to-stash.md)
- [Pulling In Changes During An Interactive Rebase](git/pulling-in-changes-during-an-interactive-rebase.md)
- [Push To A Branch On Another Remote](git/push-to-a-branch-on-another-remote.md)
@@ -434,6 +435,7 @@ _1472 TILs and counting..._
- [Add Emoji To GitHub Repository Description](internet/add-emoji-to-github-repository-description.md)
- [Check Your Public IP Address](internet/check-your-public-ip-address.md)
- [Enable Keyboard Shortcuts In Gmail](internet/enable-keyboard-shortcuts-in-gmail.md)
- [Exclude AI Overview From Google Search](internet/exclude-ai-overview-from-google-search.md)
- [Exclude Whitespace Changes From GitHub Diffs](internet/exclude-whitespace-changes-from-github-diffs.md)
- [Figure Out Your Public IP Address](internet/figure-out-your-public-ip-address.md)
- [Focus The URL Bar](internet/focus-the-url-bar.md)
@@ -743,6 +745,7 @@ _1472 TILs and counting..._
- [Duplicate A Local Database](postgres/duplicate-a-local-database.md)
- [Edit Existing Functions](postgres/edit-existing-functions.md)
- [Enable Logging Of Database Activity](postgres/enable-logging-of-database-activity.md)
- [Enforce Uniqueness On Column Expression](postgres/enforce-uniqueness-on-column-expression.md)
- [Escaping A Quote In A String](postgres/escaping-a-quote-in-a-string.md)
- [Escaping String Literals With Dollar Quoting](postgres/escaping-string-literals-with-dollar-quoting.md)
- [Export Query Results To A CSV](postgres/export-query-results-to-a-csv.md)
@@ -795,11 +798,13 @@ _1472 TILs and counting..._
- [Max Identifier Length Is 63 Bytes](postgres/max-identifier-length-is-63-bytes.md)
- [Open Heroku Database In Postico From Terminal](postgres/open-heroku-database-in-postico-from-terminal.md)
- [pg Prefix Is Reserved For System Schemas](postgres/pg-prefix-is-reserved-for-system-schemas.md)
- [Postgres Does Not Support Unsigned Integers](postgres/postgres-does-not-support-unsigned-integers.md)
- [Prepare, Execute, And Deallocate Statements](postgres/prepare-execute-and-deallocate-statements.md)
- [Pretty Print Data Sizes](postgres/pretty-print-data-sizes.md)
- [Pretty Printing JSONB Rows](postgres/pretty-printing-jsonb-rows.md)
- [Prevent A Query From Running Too Long](postgres/prevent-a-query-from-running-too-long.md)
- [Print The Query Buffer In psql](postgres/print-the-query-buffer-in-psql.md)
- [Put Unique Constraint On Generated Column](postgres/put-unique-constraint-on-generated-column.md)
- [Remove Not Null Constraint From A Column](postgres/remove-not-null-constraint-from-a-column.md)
- [Renaming A Sequence](postgres/renaming-a-sequence.md)
- [Renaming A Table](postgres/renaming-a-table.md)
@@ -1717,6 +1722,7 @@ _1472 TILs and counting..._
- [Prune The Excess From node_modules](workflow/prune-the-excess-from-node-modules.md)
- [Rotate An Image To Be Oriented Upright](workflow/rotate-an-image-to-be-oriented-upright.md)
- [See Overlaps For A Set Of Time Zones](workflow/see-overlaps-for-a-set-of-time-zones.md)
- [Send A Message To A Discord Channel](workflow/send-a-message-to-a-discord-channel.md)
- [Set Recurring Reminders In Slack](workflow/set-recurring-reminders-in-slack.md)
- [Toggle Between Stories In Storybook](workflow/toggle-between-stories-in-storybook.md)
- [Update asdf Plugins With Latest Package Versions](workflow/update-asdf-plugins-with-latest-package-versions.md)
@@ -1752,6 +1758,7 @@ _1472 TILs and counting..._
- [Add To The Path Via Path Array](zsh/add-to-the-path-via-path-array.md)
- [Link A Scalar To An Array](zsh/link-a-scalar-to-an-array.md)
- [Use A Space To Exclude Command From History](zsh/use-a-space-to-exclude-command-from-history.md)
## Usage

View File

@@ -0,0 +1,33 @@
# Override The Global Git Ignore File
One of the places that `git` looks when deciding whether to pay attention to or
ignore a file is in your global _ignore_ file. By default, `git` will look for
this file at `$XDG_CONFIG_HOME/git/ignore` or `$HOME/.config/git/ignore`.
I don't have `$XDG_CONFIG_HOME` set on my machine, so it will fall back to the
config directory under `$HOME`.
I may have to create the `git` directory and `ignore` file.
```bash
$ mkdir $HOME/.config/git
$ touch $HOME/.config/git/ignore
```
Then I can add file and directories to exclude to that `ignore` file just like
I would any other `.gitignore` file.
If I'd prefer for the global _ignore_ file to live somewhere else, I can
specify that location and filename in my `$HOME/.gitconfig` file.
```
[core]
excludesFile = ~/.gitignore
```
Setting this will override the default, meaning the default file mentioned
above will be ignored ("now you know how it feels, ignore file!"). In this
case, I'll need to create the `.gitignore` file in my home directory and add
any of my ignore rules.
[source](https://git-scm.com/docs/gitignore)

View File

@@ -0,0 +1,14 @@
# Exclude AI Overview From Google Search
At the top of most Google searches these days is a section of text that takes a
moment to appear, presumably because it is being generated in the moment. This
is Google's _AI Overview_. These are sometimes useful summaries of the article
you are about to click on anyway. Other times the overview is no good, it takes
up a bunch of screen real estate, and may even [10x the energy consumed by a
regular
search](https://www.reddit.com/r/technology/comments/1dsvefb/googles_ai_search_summaries_use_10x_more_energy/).
If you want to exclude the _AI Overview_, tack on a `-ai` when writing out your
search query.
[source](https://www.yahoo.com/tech/turn-off-ai-overview-results-170014202.html)

View File

@@ -5,6 +5,8 @@ an array-like object with all of the arguments to the function. Even if not
all of the arguments are referenced in the function signature, they can
still be accessed via the `arguments` object.
> For ES6+ compatibility, the `spread` operator used via [rest parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) is preferred over the `arugments` object when accessing an abritrary number of function arguments.
```javascript
function argTest(one) {
console.log(one);

View File

@@ -0,0 +1,35 @@
# Enforce Uniqueness On Column Expression
When creating a table for, say `users`, where you will store `email` addresses,
you'll likely want to enforce uniqueness on the that `email` field. And because
people have all sorts of ways of entering their emails, in terms of casing, you
may be tempted to try to enforce uniqueness on a lowercased version of `email`.
```sql
create table users (
id integer generated always as identity primary key,
email text not null,
unique ( lower(email) ) -- !! this won't work
);
```
A unique _constraint_ must be on one or more columns. You cannot include an
_expression_ when defining the unique constraint.
You can however accomplish similar aims with [a _unique index_ on the
expression](https://www.postgresql.org/docs/current/indexes-expressional.html).
That is because the index is able to store the result of the expression in
itself.
```sql
create table users (
id integer generated always as identity primary key,
email text not null
);
create unique index unq_lower_email on users ( lower(email) );
```
This is likely what you want for this example anyway because it will probably
be a common query to look up the user by `lower(email)` and the index will
speed up those queries.

View File

@@ -0,0 +1,30 @@
# Postgres Does Not Support Unsigned Integers
PostgreSQL has a variety of sizes of integer types, from `smallint` (2 bytes)
to `integer` (4 bytes) to `bigint` (8 bytes), as well as [other numeric
types](https://www.postgresql.org/docs/current/datatype-numeric.html).
It does _not_ however support unsigned versions of these numeric types.
That means, with an `integer` for instance, we can store numbers between
`-2147483648` and `+2147483647`. That's everything that can fit into 4 bytes.
In a system that supported 4 byte unsigned integers we'd be able to represent
from `0` all the way up to `4294967295`.
In PostgreSQL, we're limited to these _signed_ numeric types.
That means if we were hoping that the data type could essentially enforce a
non-negative restriction on the data in one of our columns, we're going to have
to be more creative. The obvious choice to me is to consider adding a [check
constraint](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-CHECK-CONSTRAINTS)
(e.g. `quantity integer check (quantity > 0)`).
Another option, as pointed out by [this StackOverflow
answer](https://stackoverflow.com/a/31833279/535590), is to create [a
user-defined _domain
type_](https://www.postgresql.org/docs/current/domains.html) that restricts
valid values. To me, the ergonomics of using a domain type are a bit awkward
and not worth the effort.
With either of these solutions, we are only approximating an unsigned integer
and do not actually have the same range of values available.

View File

@@ -0,0 +1,46 @@
# Put Unique Constraint On Generated Column
You cannot apply a _unique constraint_ to an expression over a column, e.g.
`lower(email)`. You can, however, create a [generated
column](https://www.postgresql.org/docs/current/ddl-generated-columns.html) for
that expression and then apply the unique constraint to that generated column.
Here is what that could look like:
```sql
> create table users (
id integer generated always as identity primary key,
name text not null,
email text not null,
email_lower text generated always as (lower(email)) stored,
unique ( email_lower )
);
> \d users
+-------------+---------+-----------------------------------------------------------------+
| Column | Type | Modifiers |
|-------------+---------+-----------------------------------------------------------------|
| id | integer | not null generated always as identity |
| name | text | not null |
| email | text | not null |
| email_lower | text | default lower(email) generated always as (lower(email)) stored |
+-------------+---------+-----------------------------------------------------------------+
Indexes:
"users_pkey" PRIMARY KEY, btree (id)
"users_email_lower_key" UNIQUE CONSTRAINT, btree (email_lower)
```
And then an demonstration of violating that constraint:
```sql
> insert into users (name, email) values ('Bob', 'bob@email.com');
INSERT 0 1
> insert into users (name, email) values ('Bobby', 'BOB@email.com');
duplicate key value violates unique constraint "users_email_lower_key"
DETAIL: Key (email_lower)=(bob@email.com) already exists.
```
The main tradeoff here is that you are doubling the amount of storage you need
for that column. Unless it is a massive table, that is likely not an issue.

View File

@@ -0,0 +1,64 @@
# Send A Message To A Discord Channel
I recently added a form to [visualmode.dev](https://www.visualmode.dev) that
when submitted should send the details to an internal channel in my discord
server.
I didn't need to set up an _App_ or a _Bot_ to do this. It is much simpler than
that. All I needed was a valid [_webhook_
endpoint](https://discord.com/developers/docs/resources/webhook) for my channel
that I can `POST` to.
From Discord, I can select _Edit Channel_ for a specific channel, go to the
_Integrations_ tab, go to _Webhooks_, and then create a _New Webhook_. I can
name it, save it, and then copy the webhook URL.
As a demonstration, I can `POST` to that webhook URL using `cURL` like so:
```bash
curl -H "Content-Type: application/json" -X POST -d '{"content":"Hello from cURL!"}' <YOUR_WEBHOOK_URL>
```
Similarly, in some non-public-facing code like a Next.js serverless function, I
can `POST` to that webhook URL with the `content` that I want to appear in my
channel.
```
import { NextResponse } from 'next/server'
export async function POST(request: Request) {
const data = await request.json()
const discordWebhookUrl = process.env.DISCORD_WEBHOOK_URL
if (discordWebhookUrl) {
try {
const response = await fetch(discordWebhookUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
content: `New contact form submission:\nName: ${data.name}\nEmail: ${data.email}\nCompany: ${data.company}\nPhone: ${data.phone}\nMessage: ${data.message}`,
}),
})
if (!response.ok) {
throw new Error('Failed to send Discord message')
}
} catch (error) {
console.error('Error sending to Discord:', error)
return NextResponse.json(
{ error: 'Failed to process form submission' },
{ status: 500 },
)
}
}
return NextResponse.json({ message: 'Form submitted successfully' })
}
```
This [Structure of Webhook
guide](https://birdie0.github.io/discord-webhooks-guide/discord_webhook.html)
has more details on how to specifically structure and format a more complex
message.

View File

@@ -0,0 +1,37 @@
# Use A Space To Exclude Command From History
When using a shell like `zsh`, you get the benefit of it keeping track of the
history of the commands you've entered into the shell. This means you can
quickly traverse pack to a previous command that you want to run again. It also
means [a tool like `fzf` can hook into your history
file](https://github.com/junegunn/fzf?tab=readme-ov-file#key-bindings-for-command-line)
so that you can fuzzy-search for a command you may have executed weeks ago.
The history is stored on your machine in a plaintext file. Not every command
should be stored in a plaintext file. For instance, you don't want `zsh` to
persist a command that includes a password.
With the `histignorespace` option enabled in `zsh`, we can put a leading space
in front of our command and it will be excluded from the history file.
Try it yourself:
```bash
$ echo 'this command will be remembered'
this command will be remembered
$ echo 'this command will be forgotten'
this command will be forgotten
```
Notice the leading space in the second command. Trying pressing your _up_ arrow
and notice only that first `echo` is remembered.
Make sure `histignorespace` is included in the list when you run `setopt`. If
it isn't, then add it:
```bash
$ setopt histignorespace
```
[source](https://stackoverflow.com/questions/8473121/execute-a-command-without-keeping-it-in-history/49643320#49643320)