mirror of
https://github.com/jbranchaud/til
synced 2026-01-03 23:28:02 +00:00
Compare commits
8 Commits
ab36b2e467
...
d3f211773a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3f211773a | ||
|
|
a547b9cee2 | ||
|
|
99ce5aee7b | ||
|
|
60b6aa40ad | ||
|
|
f97634a61e | ||
|
|
34ba60d313 | ||
|
|
3a178e901e | ||
|
|
460473a87f |
@@ -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).
|
||||
|
||||
_1628 TILs and counting..._
|
||||
_1634 TILs and counting..._
|
||||
|
||||
See some of the other learning resources I work on:
|
||||
- [Ruby Operator Lookup](https://www.visualmode.dev/ruby-operators)
|
||||
@@ -114,6 +114,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
||||
|
||||
- [AWS CLI Requires Groff Executable](aws/aws-cli-requires-groff-executable.md)
|
||||
- [Find And Follow Server Logs](aws/find-and-follow-server-logs.md)
|
||||
- [List RDS Snapshots With Matching Identifier Prefix](aws/list-rds-snapshots-with-matching-identifier-prefix.md)
|
||||
- [Output CLI Results In Different Formats](aws/output-cli-results-in-different-formats.md)
|
||||
- [Sign Up User With Email And Password](aws/sign-up-user-with-email-and-password.md)
|
||||
- [SSH Into An ECS Container](aws/ssh-into-an-ecs-container.md)
|
||||
@@ -134,6 +135,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
||||
- [Duplicate The Current Tab](chrome/duplicate-the-current-tab.md)
|
||||
- [Easier Access To Network Throttling Controls](chrome/easier-access-to-network-throttling-controls.md)
|
||||
- [Keybinding To Focus The Address Bar](chrome/keybinding-to-focus-the-address-bar.md)
|
||||
- [Open Current Tab In New Window With Vimium](chrome/open-current-tab-in-new-window-with-vimium.md)
|
||||
- [Pause JavaScript From The Source DevTools Panel](chrome/pause-javascript-from-the-source-devtools-panel.md)
|
||||
- [Navigate The Browser History With Vimium](chrome/navigate-the-browser-history-with-vimium.md)
|
||||
- [Pretty Print Tabular Data](chrome/pretty-print-tabular-data.md)
|
||||
@@ -1035,6 +1037,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
||||
- [Ensure A Rake Task Cannot Write Data](rails/ensure-a-rake-task-cannot-write-data.md)
|
||||
- [Ensure Migrations Use The Latest Schema](rails/ensure-migrations-use-the-latest-schema.md)
|
||||
- [Ensure Record Saved With after_commit Callback](rails/ensure-record-saved-with-after-commit-callback.md)
|
||||
- [Filter ActiveModel Validation Errors](rails/filter-active-model-validation-errors.md)
|
||||
- [Filter ActiveStorage Blobs To Only Images](rails/filter-active-storage-blobs-to-only-images.md)
|
||||
- [Find Or Create A Record With FactoryBot](rails/find-or-create-a-record-with-factory-bot.md)
|
||||
- [Find Records With Multiple Associated Records](rails/find-records-with-multiple-associated-records.md)
|
||||
@@ -1539,6 +1542,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
||||
- [Count The Number Of ripgrep Pattern Matches](unix/count-the-number-of-ripgrep-pattern-matches.md)
|
||||
- [Count The Number Of Words On A Webpage](unix/count-the-number-of-words-on-a-webpage.md)
|
||||
- [Create A File Descriptor with Process Substitution](unix/create-a-file-descriptor-with-process-substitution.md)
|
||||
- [Create A Filename With The Current Date](unix/create-a-filename-with-the-current-date.md)
|
||||
- [Create A Sequence Of Values With A Step](unix/create-a-sequence-of-values-with-a-step.md)
|
||||
- [Curl With Cookies](unix/curl-with-cookies.md)
|
||||
- [Curling For Headers](unix/curling-for-headers.md)
|
||||
@@ -1586,6 +1590,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
||||
- [Grep For Files Without A Match](unix/grep-for-files-without-a-match.md)
|
||||
- [Grep For Files With Multiple Matches](unix/grep-for-files-with-multiple-matches.md)
|
||||
- [Grep For Multiple Patterns](unix/grep-for-multiple-patterns.md)
|
||||
- [Have Script ShellCheck Itself When Executing](unix/have-script-shellcheck-itself-when-executing.md)
|
||||
- [Hexdump A Compiled File](unix/hexdump-a-compiled-file.md)
|
||||
- [Ignore A Directory During ripgrep Search](unix/ignore-a-directory-during-ripgrep-search.md)
|
||||
- [Ignore The Alias When Running A Command](unix/ignore-the-alias-when-running-a-command.md)
|
||||
@@ -1696,6 +1701,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
||||
- [Breaking The Undo Sequence](vim/breaking-the-undo-sequence.md)
|
||||
- [Buffer Time Travel](vim/buffer-time-travel.md)
|
||||
- [Build And Install A Go Program](vim/build-and-install-a-go-program.md)
|
||||
- [Bypass On-Save Tooling When Writing File](vim/bypass-on-save-tooling-when-writing-file.md)
|
||||
- [Case-Aware Substitution With vim-abolish](vim/case-aware-substitution-with-vim-abolish.md)
|
||||
- [Case-Insensitive Substitution](vim/case-insensitive-substitution.md)
|
||||
- [Center The Cursor](vim/center-the-cursor.md)
|
||||
|
||||
29
aws/list-rds-snapshots-with-matching-identifier-prefix.md
Normal file
29
aws/list-rds-snapshots-with-matching-identifier-prefix.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# List RDS Snapshots With Matching Identifier Prefix
|
||||
|
||||
I'm working on a script that manually creates a snapshot which it will then
|
||||
restore to a temporary database that I can scrub and dump. The snapshots that
|
||||
this script takes are _manual_ and they are named with identifiers that have a
|
||||
defining prefix (`dev-snapshot-`). Besides the few snapshots created by this
|
||||
script, there are tons of automated snapshots that RDS creates for
|
||||
backup/recovery purposes.
|
||||
|
||||
I want to list any snapshots that have been created by the script. I can do
|
||||
this with the `describe-db-snapshots` command and some filters.
|
||||
|
||||
```bash
|
||||
$ aws rds describe-db-snapshots \
|
||||
--snapshot-type manual \
|
||||
--query "DBSnapshots[?starts_with(DBSnapshotIdentifier, 'dev-snapshot-')].DBSnapshotIdentifier" \
|
||||
--no-cli-pager
|
||||
|
||||
[
|
||||
"dev-snapshot-20250327-155355"
|
||||
]
|
||||
```
|
||||
|
||||
There are two key pieces. The `--snapshot-type manual` filter excludes all
|
||||
those automated snapshots. The `--query` both filters to any snapshots whose
|
||||
identifier `?starts_with` the prefix `dev-snapshot-` and then refines the
|
||||
output to just the `DBSnapshotIdentifier` instead of the entire JSON object.
|
||||
|
||||
[source](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-snapshots.html)
|
||||
14
chrome/open-current-tab-in-new-window-with-vimium.md
Normal file
14
chrome/open-current-tab-in-new-window-with-vimium.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Open Current Tab In New Window With Vimium
|
||||
|
||||
Sometime I have a busy Chrome window going with a bunch of tabs open for
|
||||
various lines of work as well as a number of tabs that I've neglected to close.
|
||||
I then open a new tab, find something useful, and realize I'm at a "branching
|
||||
point". I'm about to start in on a specific chunk of work that will probably
|
||||
involve opening several more tabs and switch back and forth between some
|
||||
dashboards. I want to start all of this from a fresh slate -- or at least from
|
||||
a fresh Chrome window.
|
||||
|
||||
With [Vimium](https://github.com/philc/vimium), I can hit `W` (`Shift-w`) to
|
||||
have the current tab move from the current window to a new window. The original
|
||||
window, minus that one tab, will be left as is so that I can go back to it as
|
||||
needed.
|
||||
@@ -15,10 +15,8 @@ const remove = (items,index) => {
|
||||
};
|
||||
|
||||
const list = [1,2,3,4,5];
|
||||
remove(list, 2);
|
||||
// [1,2,3,4]
|
||||
list
|
||||
// [1,2,3,4,5]
|
||||
remove(list, 2); // [1,2,4,5]
|
||||
// list still [1,2,3,4,5]
|
||||
```
|
||||
|
||||
It only took a couple lines of code and immutability is baked in.
|
||||
|
||||
43
rails/filter-active-model-validation-errors.md
Normal file
43
rails/filter-active-model-validation-errors.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Filter ActiveModel Validation Errors
|
||||
|
||||
Now that `ActiveModel` has a custom `Errors` class (as of Rails 6.1) instead of
|
||||
a hash, we get some useful functionality. Namely, we get a [`#where`
|
||||
method](https://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-where)
|
||||
that allows us to filter errors based on the attribute name, type of
|
||||
validation, and even properties of that validation.
|
||||
|
||||
Here I have created a new `Book` without any attributes. All of its validations
|
||||
are going to fail and we are going to have an `ActiveModel::Errors` object
|
||||
attached to it with several errors.
|
||||
|
||||
```ruby
|
||||
> book = Book.new
|
||||
=>
|
||||
#<Book:0x00000001110397a8
|
||||
...
|
||||
> book.valid?
|
||||
=> false
|
||||
> book.errors
|
||||
=> #<ActiveModel::Errors [#<ActiveModel::Error attribute=added_by, type=blank, options={:message=>:required, :if=>#<Proc:0x0000000110096260 /Users/jbranchaud/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.2.1/lib/active_record/associations/builder/belongs_to.rb:130 (lambda)>}>, #<ActiveModel::Error attribute=title, type=blank, options={}>, #<ActiveModel::Error attribute=title, type=too_short, options={:count=>3}>, #<ActiveModel::Error attribute=author, type=blank, options={}>, #<ActiveModel::Error attribute=publication_date, type=blank, options={}>]>
|
||||
```
|
||||
|
||||
Let's say I want to check for a specific validation error. I can use `#where`
|
||||
to filter down by attribute name (e.g. `:title`). I can filter even further by
|
||||
including the validation type as well (e.g. `:too_short`).
|
||||
|
||||
```ruby
|
||||
> book.errors.where(:title)
|
||||
=>
|
||||
[#<ActiveModel::Error attribute=title, type=blank, options={}>,
|
||||
#<ActiveModel::Error attribute=title, type=too_short, options={:count=>3}>]
|
||||
> book.errors.where(:title, :too_short)
|
||||
=> [#<ActiveModel::Error attribute=title, type=too_short, options={:count=>3}>]
|
||||
> book.errors.where(:title, :too_short).first.message
|
||||
=> "is too short (minimum is 3 characters)"
|
||||
> book.errors.where(:title, :too_short).first.full_message
|
||||
=> "Title is too short (minimum is 3 characters)"
|
||||
```
|
||||
|
||||
This filtering could be used as part of conditional checks for what flash
|
||||
message gets displayed to the user or even what route/view gets rendered in
|
||||
response to the error.
|
||||
38
unix/create-a-filename-with-the-current-date.md
Normal file
38
unix/create-a-filename-with-the-current-date.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Create A Filename With The Current Date
|
||||
|
||||
I was recently working on a script to pull a scrubbed database dump using the
|
||||
`pg_dump` Postgres utility. Ultimately, the script does something like this to
|
||||
dump a remote database to a local file:
|
||||
|
||||
```bash
|
||||
pg_dump \
|
||||
-h host.region.rds.amazonaws.com \
|
||||
-U db_username \
|
||||
-d db_name \
|
||||
-F c \
|
||||
-f scrubbed-database-$(date +%Y-%m-%d).dump
|
||||
```
|
||||
|
||||
Notice the last part of that command where we define the name of the dump file.
|
||||
It has a `$(...)` that is used to run and interpolate a command as part of the
|
||||
filename.
|
||||
|
||||
Here is that `date` command run on its own:
|
||||
|
||||
```bash
|
||||
$ date +%Y-%m-%d
|
||||
2025-04-02
|
||||
```
|
||||
|
||||
In the above command, that would mean if I were to run it today, I'd get
|
||||
`scrubbed-database-2025-04-02.dump`.
|
||||
|
||||
This approach can be used with any command where you are producing a file that
|
||||
you want to be dated or timestamped.
|
||||
|
||||
Here is another example that incorporates the time as well:
|
||||
|
||||
```bash
|
||||
$ touch $(date +%Y%m%d_%H%M%S)-migration.sql
|
||||
# => 20250402_092442-migration.sql
|
||||
```
|
||||
60
unix/have-script-shellcheck-itself-when-executing.md
Normal file
60
unix/have-script-shellcheck-itself-when-executing.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Have Script ShellCheck Itself When Executing
|
||||
|
||||
The [ShellCheck](https://www.shellcheck.net/) utility can be run against bash
|
||||
scripts to check if there are any warnings or errors we should fix. It works
|
||||
great as long as we remember to run it.
|
||||
|
||||
I wondered if I could make it easier on myself by not having to remember to run
|
||||
it. What if my bash script were to `shellcheck` itself?
|
||||
|
||||
Here is an example script where at the beginning it looks for and runs the
|
||||
`shellcheck` utility against `$0` (the path of the script). This is kind of
|
||||
meta. As the script is executing, it has an external program run against the
|
||||
entire contents of itself. If there are any `shellcheck` issues, they get
|
||||
displayed and the program exits early.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Exit immediately if any command fails
|
||||
set -e
|
||||
|
||||
# Self-validation using ShellCheck
|
||||
if command -v shellcheck &> /dev/null; then
|
||||
echo "Validating script with ShellCheck..."
|
||||
|
||||
# $0 refers to the script itself
|
||||
if ! shellcheck "$0"; then
|
||||
echo "ShellCheck found issues in the script. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
echo "Script validation passed."
|
||||
else
|
||||
echo "Warning: ShellCheck not found. Skipping validation."
|
||||
fi
|
||||
|
||||
echo "Script execution continuing..."
|
||||
|
||||
# shellcheck warning here
|
||||
read -p "Continue with current operation? (yes/no): " CONTINUE_WITH_EXISTING
|
||||
if [[ ! "$CONTINUE_WITH_EXISTING" =~ ^[Yy][Ee][Ss]$ ]]; then
|
||||
echo "Operation cancelled."
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
This last bit of the script with the `read` command will trigger a warning from
|
||||
`shellcheck`.
|
||||
|
||||
```bash
|
||||
$ ./check.sh
|
||||
Validating script with ShellCheck...
|
||||
|
||||
In ./check.sh line 23:
|
||||
read -p "Continue with current operation? (yes/no): " CONTINUE_WITH_EXISTING
|
||||
^--^ SC2162 (info): read without -r will mangle backslashes.
|
||||
|
||||
For more information:
|
||||
https://www.shellcheck.net/wiki/SC2162 -- read without -r will mangle backs...
|
||||
ShellCheck found issues in the script. Exiting.
|
||||
```
|
||||
30
vim/bypass-on-save-tooling-when-writing-file.md
Normal file
30
vim/bypass-on-save-tooling-when-writing-file.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Bypass On-Save Tooling When Writing File
|
||||
|
||||
Every once in a while I run into an issue where my code formatters or linters
|
||||
are misconfigured for a project. I try to save a file and it applies formatting
|
||||
that I don't want. Or in an extreme case, the error ouput of the tool is what
|
||||
overwrites the file.
|
||||
|
||||
I need to troubleshoot my dev tooling eventually, but I don't want to get
|
||||
sidetracked at the moment. I just want to save the file. What can I do?
|
||||
|
||||
Tools like linters and code formatters are typically hooked up to Vim via
|
||||
autocommands on certain actions like `FileWrite*` or `BufWrite*`. We can
|
||||
execute a Vim command like writing a file (`w`) while disregarding autocommands
|
||||
like so:
|
||||
|
||||
```vim
|
||||
:noautocmd w
|
||||
```
|
||||
|
||||
or, write and quit:
|
||||
|
||||
```vim
|
||||
:noautocmd wq
|
||||
```
|
||||
|
||||
This disables all autocommands for this one command. The file gets saved and
|
||||
the misconfigured formatters and linters don't clobber the changes you
|
||||
intended.
|
||||
|
||||
See `:h noautocmd` for more details.
|
||||
Reference in New Issue
Block a user