mirror of
https://github.com/jbranchaud/til
synced 2026-01-16 21:48:02 +00:00
Compare commits
18 Commits
1072c6ad72
...
ed9c31c259
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed9c31c259 | ||
|
|
42854fdc38 | ||
|
|
eff2c548cd | ||
|
|
1b229b39f1 | ||
|
|
2543651ec0 | ||
|
|
f3d7cf8a06 | ||
|
|
72089e11db | ||
|
|
b766f20012 | ||
|
|
505220d9de | ||
|
|
9684c6a6db | ||
|
|
3b0d76e805 | ||
|
|
b6c8192a04 | ||
|
|
c2f30615c3 | ||
|
|
f54eab20e7 | ||
|
|
b2ddce62fd | ||
|
|
63a57c6bdd | ||
|
|
87d116a4cd | ||
|
|
15337dfd71 |
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).
|
||||
|
||||
_1402 TILs and counting..._
|
||||
_1418 TILs and counting..._
|
||||
|
||||
---
|
||||
|
||||
@@ -41,6 +41,7 @@ _1402 TILs and counting..._
|
||||
* [jq](#jq)
|
||||
* [Kitty](#kitty)
|
||||
* [Linux](#linux)
|
||||
* [LLM](#llm)
|
||||
* [Mac](#mac)
|
||||
* [MongoDB](#mongodb)
|
||||
* [MySQL](#mysql)
|
||||
@@ -98,6 +99,7 @@ _1402 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
|
||||
|
||||
@@ -397,6 +399,7 @@ _1402 TILs and counting..._
|
||||
- [Adding Alt Text To An Image](html/adding-alt-text-to-an-image.md)
|
||||
- [Determine Which Button Submitted The Form](html/determine-which-button-submitted-the-form.md)
|
||||
- [Disable Auto-Completion For A Form Input](html/disable-auto-completion-for-a-form-input.md)
|
||||
- [Make Elements Non-Interactive With Inert](html/make-elements-non-interactive-with-inert.md)
|
||||
- [Prevent Search Engines From Indexing A Page](html/prevent-search-engines-from-indexing-a-page.md)
|
||||
- [Render Text As Superscript](html/render-text-as-superscript.md)
|
||||
- [Submit A Form With A Button Outside The Form](html/submit-a-form-with-a-button-outside-the-form.md)
|
||||
@@ -436,6 +439,7 @@ _1402 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)
|
||||
@@ -552,6 +556,11 @@ _1402 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)
|
||||
@@ -679,6 +688,7 @@ _1402 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)
|
||||
@@ -818,6 +828,7 @@ _1402 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
|
||||
|
||||
@@ -878,6 +889,7 @@ _1402 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)
|
||||
@@ -1089,6 +1101,7 @@ _1402 TILs and counting..._
|
||||
- [Add Progress Reporting To Long-Running Script](ruby/add-progress-reporting-to-long-running-script.md)
|
||||
- [Are They All True?](ruby/are-they-all-true.md)
|
||||
- [Assert About An Object's Attributes With RSpec](ruby/assert-about-an-objects-attributes-with-rspec.md)
|
||||
- [Audit Your Ruby Project For Any CVEs](ruby/audit-your-ruby-project-for-any-cves.md)
|
||||
- [Assoc For Hashes](ruby/assoc-for-hashes.md)
|
||||
- [Block Comments](ruby/block-comments.md)
|
||||
- [Build HTTP And HTTPS URLs](ruby/build-http-and-https-urls.md)
|
||||
@@ -1112,6 +1125,7 @@ _1402 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)
|
||||
@@ -1135,6 +1149,7 @@ _1402 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)
|
||||
@@ -1377,6 +1392,7 @@ _1402 TILs and counting..._
|
||||
- [Less With Style](unix/less-with-style.md)
|
||||
- [List All The Enabled ZSH Options](unix/list-all-the-enabled-zsh-options.md)
|
||||
- [List All Users](unix/list-all-users.md)
|
||||
- [List Files In A Single Column](unix/list-files-in-a-single-column.md)
|
||||
- [List Files Ordered By Modification Date](unix/list-files-ordered-by-modification-date.md)
|
||||
- [List Names Of Files With Matches](unix/list-names-of-files-with-matches.md)
|
||||
- [List Of Sessions To A Machine](unix/list-of-sessions-to-a-machine.md)
|
||||
@@ -1395,6 +1411,7 @@ _1402 TILs and counting..._
|
||||
- [Partial String Matching In Bash Scripts](unix/partial-string-matching-in-bash-scripts.md)
|
||||
- [PID Of The Current Shell](unix/pid-of-the-current-shell.md)
|
||||
- [Print A Range Of Lines For A File With Bat](unix/print-a-range-of-lines-for-a-file-with-bat.md)
|
||||
- [Print DateTime Represented By Unix Timestamp](unix/print-datetime-represented-by-unix-timestamp.md)
|
||||
- [Print Milliseconds In Human-Readable Format](unix/print-milliseconds-in-human-readable-format.md)
|
||||
- [Print Out Files In Reverse](unix/print-out-files-in-reverse.md)
|
||||
- [Print The Current Date In Human-Readable Format](unix/print-the-current-date-in-human-readable-format.md)
|
||||
@@ -1425,6 +1442,7 @@ _1402 TILs and counting..._
|
||||
- [Tell direnv To Load The Env File](unix/tell-direnv-to-load-the-env-file.md)
|
||||
- [Touch Access And Modify Times Individually](unix/touch-access-and-modify-times-individually.md)
|
||||
- [Undo Some Command Line Editing](unix/undo-some-command-line-editing.md)
|
||||
- [Unrestrict Where ripgrep Searches](unix/unrestrict-where-ripgrep-searches.md)
|
||||
- [Update Package Versions Known By asdf Plugin](unix/update-package-versions-known-by-asdf-plugin.md)
|
||||
- [Use fzf To Change Directories](unix/use-fzf-to-change-directories.md)
|
||||
- [Use Regex Pattern Matching With Grep](unix/use-regex-pattern-matching-with-grep.md)
|
||||
@@ -1611,6 +1629,7 @@ _1402 TILs and counting..._
|
||||
- [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)
|
||||
- [Toggle Between Terminals](vscode/toggle-between-terminals.md)
|
||||
- [Turn Off Display Of Tabs For Files](vscode/turn-off-display-of-tabs-for-files.md)
|
||||
|
||||
### Webpack
|
||||
|
||||
@@ -1623,6 +1642,7 @@ _1402 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.
|
||||
@@ -23,11 +23,11 @@ version from my `.tool-versions` file with a step that uses `set-output`.
|
||||
- name: Read Node.js version to install from `.tool-versions`
|
||||
id: nodejs
|
||||
run: >-
|
||||
echo "::set-output name=NODE_VERSION::$(
|
||||
echo "NODE_VERSION=$(
|
||||
cat .tool-versions |
|
||||
grep nodejs |
|
||||
sed 's/nodejs \(.*\)$/\1/'
|
||||
)"
|
||||
)" >> $GITHUB_OUTPUT
|
||||
```
|
||||
|
||||
`echo` runs the command in the string which sets `NODE_VERSION` as an output
|
||||
@@ -45,4 +45,4 @@ This output value can be referenced in a later step.
|
||||
`steps` has a reference to the `nodejs` step (note the `id` above) which then
|
||||
has `outputs` like the `NODE_VERSION`.
|
||||
|
||||
[source](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#using-workflow-commands-to-access-toolkit-functions)
|
||||
[source](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter)
|
||||
|
||||
25
html/make-elements-non-interactive-with-inert.md
Normal file
25
html/make-elements-non-interactive-with-inert.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Make Elements Non-Interactive With Inert
|
||||
|
||||
The [`inert`
|
||||
attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert)
|
||||
global attribute is a boolean that can be applied to an element or section of
|
||||
content in an HTML document. When it is `true`, that elements and anything
|
||||
nested within it will not be interactive.
|
||||
|
||||
```html
|
||||
<div class="fancy-animation" inert>
|
||||
<!-- ... -->
|
||||
</div>
|
||||
```
|
||||
|
||||
This has a couple different implications:
|
||||
|
||||
1. Click events are not fired on these elements.
|
||||
|
||||
2. These elements will not be able to gain focus.
|
||||
|
||||
3. These elements and content are hidden from assistive technology.
|
||||
|
||||
This is useful for a variety of things. In particular, it is good for
|
||||
accessibility when a portion of the document, like a fancy animation, isn't
|
||||
meant to be traversed by assistive technology.
|
||||
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.
|
||||
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
|
||||
```
|
||||
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"
|
||||
```
|
||||
45
ruby/audit-your-ruby-project-for-any-cves.md
Normal file
45
ruby/audit-your-ruby-project-for-any-cves.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Audit Your Ruby Project For Any CVEs
|
||||
|
||||
The [`bundler-audit` gem](https://github.com/rubysec/bundler-audit) is a handy
|
||||
tool that you can run manually or integrate into your CI workflow to warn you
|
||||
about any CVEs in your dependencies.
|
||||
|
||||
Running this tool without any arguments will perform a check of your
|
||||
`Gemfile.lock` file. It will check against the
|
||||
[`ruby-advisory-db`](https://github.com/rubysec/ruby-advisory-db) for any CVEs
|
||||
linked to your dependencies, down to the patch-level.
|
||||
|
||||
```bash
|
||||
$ bundle exec bundler-audit
|
||||
|
||||
Name: puma
|
||||
Version: 4.3.12
|
||||
CVE: CVE-2024-21647
|
||||
GHSA: GHSA-c2f4-cvqm-65w2
|
||||
Criticality: Medium
|
||||
URL: https://github.com/puma/puma/security/advisories/GHSA-c2f4-cvqm-65w2
|
||||
Title: Puma HTTP Request/Response Smuggling vulnerability
|
||||
Solution: upgrade to '~> 5.6.8', '>= 6.4.2'
|
||||
|
||||
Vulnerabilities found!
|
||||
```
|
||||
|
||||
In this example run, a vulnerability was found in the currently installed
|
||||
version of the `puma` gem.
|
||||
|
||||
I believe a standard `bundler-audit` command will make sure the advisory DB is
|
||||
up-to-date, but to be sure, you can run the `update` command.
|
||||
|
||||
```bash
|
||||
$ bundle exec bundler-audit update
|
||||
|
||||
Updating ruby-advisory-db ...
|
||||
From https://github.com/rubysec/ruby-advisory-db
|
||||
* branch master -> FETCH_HEAD
|
||||
Already up to date.
|
||||
Updated ruby-advisory-db
|
||||
ruby-advisory-db:
|
||||
advisories: 884 advisories
|
||||
last updated: 2024-03-26 16:27:16 -0700
|
||||
commit: 840f21aeeb8a06a93a3c3bf1e2a92d7167029992
|
||||
```
|
||||
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
|
||||
```
|
||||
34
unix/list-files-in-a-single-column.md
Normal file
34
unix/list-files-in-a-single-column.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# List Files In A Single Column
|
||||
|
||||
The `ls` command lists out the files and directories in your current directory
|
||||
or a specified directory.
|
||||
|
||||
The standard output for an `ls` command expands the fit the width of your
|
||||
terminal screen.
|
||||
|
||||
```bash
|
||||
❯ ls *.(ts|js)
|
||||
cypress.config.ts postcss.config.js remix.config.js remix.env.d.ts server.ts tailwind.config.ts vitest.config.ts
|
||||
```
|
||||
|
||||
This might not always be the ideal way to view that output. For instance, the
|
||||
above example when shared as a code block like in this post ends up with
|
||||
horizontal scroll.
|
||||
|
||||
With the `-1` flag, we can tell `ls` to display the results in a single
|
||||
vertical column.
|
||||
|
||||
```bash
|
||||
❯ ls -1 *.(ts|js)
|
||||
cypress.config.ts
|
||||
postcss.config.js
|
||||
remix.config.js
|
||||
remix.env.d.ts
|
||||
server.ts
|
||||
tailwind.config.ts
|
||||
vitest.config.ts
|
||||
```
|
||||
|
||||
See `man ls` for more details.
|
||||
|
||||
[source](https://askubuntu.com/questions/954924/listing-files-in-directory-in-one-column)
|
||||
16
unix/print-datetime-represented-by-unix-timestamp.md
Normal file
16
unix/print-datetime-represented-by-unix-timestamp.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Print DateTime Represented By Unix Timestamp
|
||||
|
||||
A lot of tools and systems use a Unix timestamp to represent a point in time.
|
||||
It is the number of seconds since the Unix epoch (Jan 1, 1970). However, just
|
||||
looking at a timestamp like `1623867544` doesn't tell a human much. I can't
|
||||
mentally translate that to the date and time that it is representing.
|
||||
|
||||
The `date` utility can help. Give it the `-r` flag with the timestamp value (in
|
||||
seconds) and it will display the date and time in a human-readable format.
|
||||
|
||||
```bash
|
||||
❯ date -r '1623867544'
|
||||
Wed Jun 16 13:19:04 CDT 2021
|
||||
```
|
||||
|
||||
See `man date` for more details.
|
||||
33
unix/unrestrict-where-ripgrep-searches.md
Normal file
33
unix/unrestrict-where-ripgrep-searches.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Unrestrict Where ripgrep Searches
|
||||
|
||||
One of the conveniences of [`rg`
|
||||
(ripgrep)](https://github.com/BurntSushi/ripgrep) is that by default it doesn't
|
||||
search in places you probably don't want it to search. That means it ignores
|
||||
anything specified by your `.gitignore` file, it excludes hidden files and
|
||||
directories (dotfiles, e.g. `.git/` or `.env`), and it excludes binary files.
|
||||
|
||||
These restrictions can be incrementally undone as needed using the `-u` flag.
|
||||
|
||||
The `-u` flag on its own will remove the ignored files restriction. This is
|
||||
equivalent to the `--no-ignore` flag.
|
||||
|
||||
```bash
|
||||
$ rg -u pattern
|
||||
```
|
||||
|
||||
Adding an additional `u` (`-uu`) to that flag will remove both the ignored files and
|
||||
hidden files restrictions. This is a shorthand equivalent to both `--no-ignore`
|
||||
and `--hidden`.
|
||||
|
||||
```bash
|
||||
$ rg -uu pattern
|
||||
```
|
||||
|
||||
Adding one more `u` (`-uuu`) will additionally remove the binary file
|
||||
restriction. Equivalent to those other two flags plus `--text`.
|
||||
|
||||
```bash
|
||||
$ rg -uuu pattern
|
||||
```
|
||||
|
||||
[source](https://github.com/BurntSushi/ripgrep/blob/master/GUIDE.md#automatic-filtering)
|
||||
18
vscode/turn-off-display-of-tabs-for-files.md
Normal file
18
vscode/turn-off-display-of-tabs-for-files.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Turn Off Display Of Tabs For Files
|
||||
|
||||
Each time a file is opened in VS Code, it appears as one of many toward the top
|
||||
of the window right above the text editor area. It shows the name of the file
|
||||
and the 'dirty' status. Over time as more and more files are opened and edited,
|
||||
the tabs accumulate and can only be viewed by horizontally scrolling left and
|
||||
right.
|
||||
|
||||
There are other ways to navigate to files besides selecting tabs of already
|
||||
opened files. So, if you'd like to reclaim some screen real estate and reduce
|
||||
the visual clutter of the tabs, you can turn them off.
|
||||
|
||||
Hit `Cmd+Shift+P`, then search for and go to _Preferences: Open Settings (UI)_.
|
||||
Search for _Show Tabs_ which will show up under _Workbench > Editor_.
|
||||
|
||||
The default is _Multiple_. You can switch it to _None_ to completely hide tabs.
|
||||
You can also set it to _Single_ which will display file name and path for the
|
||||
current file, but eliminate the clutter of all other tabs.
|
||||
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