1
0
mirror of https://github.com/jbranchaud/til synced 2026-01-18 14:38:01 +00:00

Compare commits

...

19 Commits

Author SHA1 Message Date
Dylan Irlbeck
c5db038daa Merge 5365e75267 into 01c9c0d19b 2024-05-02 09:25:59 +05:30
jbranchaud
01c9c0d19b Add Add Only Tracked Files From A Directory as a Git TIL 2024-05-01 09:31:52 -05:00
jbranchaud
c06bb2ea7b Add Find The Location Of User Settings JSON File as a VSCode TIL 2024-04-28 20:28:57 -05:00
jbranchaud
7dad6508d0 Fix typo in code snippet for latest TIL 2024-04-27 23:00:38 -05:00
jbranchaud
5bcdbbb3c7 Add Include Columns In A Covering Index as a Postgres TIL 2024-04-27 22:48:32 -05:00
jbranchaud
41f5b526d2 Add Ensure Lookup Can Be Retried as an Inngest TIL 2024-04-26 23:26:51 -05:00
jbranchaud
e974a184c6 Add Check If Clusters Are Upgrade Compatible as a Postgres TIL 2024-04-25 20:25:48 -05:00
jbranchaud
c832b9a70d Add Look Up Time Zone Info For Identifier as a Rails TIL 2024-04-25 10:50:49 -05:00
jbranchaud
42854fdc38 Add Create A Cluster In A Specific Data Directory as a Postgres TIL 2024-04-23 18:04:45 -05:00
jbranchaud
eff2c548cd Add List All Services Managed By Brew as a Brew TIL 2024-04-23 15:41:01 -05:00
jbranchaud
1b229b39f1 Add Use The llm CLI With Claude Models as an LLM TIL 2024-04-22 20:54:58 -05:00
jbranchaud
2543651ec0 Add Use pipx To Install End User Apps as a Python TIL 2024-04-22 19:47:09 -05:00
jbranchaud
f3d7cf8a06 Add Access 1Password Credential From CLI as a Workflow TIL 2024-04-21 19:57:10 -05:00
jbranchaud
72089e11db Add Send cURL To Claude Text Completion API as an LLM TIL 2024-04-21 19:06:13 -05:00
jbranchaud
b766f20012 Add Define Multiline Strings With Heredocs as a Ruby TIL 2024-04-21 13:46:04 -05:00
jbranchaud
505220d9de Add Convert Seconds To Date Object as a JavaScript TIL 2024-04-19 14:38:40 -05:00
jbranchaud
9684c6a6db Add Get Formatted UTC Offset Value as a Rails TIL 2024-04-18 14:32:46 -05:00
jbranchaud
3b0d76e805 Add Get UTC Offset For Different Time Zones as a Ruby TIL 2024-04-18 10:49:29 -05:00
Dylan Irlbeck
5365e75267 Update git show TIL 2020-04-29 22:17:44 -05:00
18 changed files with 604 additions and 4 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).
_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)

View 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.

View 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.

View File

@@ -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)

View 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.

View 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.

View 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)

View 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.

View 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.

View 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
```

View 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).

View 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
```

View 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"
```

View 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.

View 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
```

View 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
```

View 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)

View 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)" ...
```