mirror of
https://github.com/jbranchaud/til
synced 2026-01-20 15:38:02 +00:00
Compare commits
7 Commits
b92e6729ff
...
6984685276
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6984685276 | ||
|
|
877537228f | ||
|
|
1513611857 | ||
|
|
74514b462d | ||
|
|
484dec8e24 | ||
|
|
8574113dc6 | ||
|
|
1c4e37ed8a |
@@ -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).
|
||||
|
||||
_1503 TILs and counting..._
|
||||
_1508 TILs and counting..._
|
||||
|
||||
---
|
||||
|
||||
@@ -297,6 +297,7 @@ _1503 TILs and counting..._
|
||||
- [Configure Global gitignore File](git/configure-global-gitignore-file.md)
|
||||
- [Configuring The Pager](git/configuring-the-pager.md)
|
||||
- [Copy A File From Another Branch](git/copy-a-file-from-another-branch.md)
|
||||
- [Count All Files Of Specific Type Tracked By Git](git/count-all-files-of-specific-type-tracked-by-git.md)
|
||||
- [Create A New Branch With Git Switch](git/create-a-new-branch-with-git-switch.md)
|
||||
- [Delete All Untracked Files](git/delete-all-untracked-files.md)
|
||||
- [Determine The Hash Id For A Blob](git/determine-the-hash-id-for-a-blob.md)
|
||||
@@ -886,6 +887,7 @@ _1503 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)
|
||||
- [Dunder Methods](python/dunder-methods.md)
|
||||
- [Store And Access Immutable Data In A Tuple](python/store-and-access-immutable-data-in-a-tuple.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)
|
||||
@@ -940,6 +942,7 @@ _1503 TILs and counting..._
|
||||
- [Demodulize A Class Name](rails/demodulize-a-class-name.md)
|
||||
- [Different Ways To Add A Foreign Key Reference](rails/different-ways-to-add-a-foreign-key-reference.md)
|
||||
- [Disambiguate Where In A Joined Relation](rails/disambiguate-where-in-a-joined-relation.md)
|
||||
- [Empty find_by Returns First Record](rails/empty-find-by-returns-first-record.md)
|
||||
- [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)
|
||||
@@ -1208,6 +1211,7 @@ _1503 TILs and counting..._
|
||||
- [Enumerate A Pairing Of Every Two Sequential Items](ruby/enumerate-a-pairing-of-every-two-sequential-items.md)
|
||||
- [Evaluating One-Off Commands](ruby/evaluating-one-off-commands.md)
|
||||
- [Exclude Values From An Array](ruby/exclude-values-from-an-array.md)
|
||||
- [Execute Several Commands With Backtick Heredoc](ruby/execute-several-commands-with-backtick-heredoc.md)
|
||||
- [Exit A Process With An Error Message](ruby/exit-a-process-with-an-error-message.md)
|
||||
- [Expect A Method To Be Called And Actually Call It](ruby/expect-a-method-to-be-called-and-actually-call-it.md)
|
||||
- [Extract A Column Of Data From A CSV File](ruby/extract-a-column-of-data-from-a-csv-file.md)
|
||||
@@ -1461,6 +1465,7 @@ _1503 TILs and counting..._
|
||||
- [Global Substitution On The Previous Command](unix/global-substitution-on-the-previous-command.md)
|
||||
- [Globbing For All Directories In Zsh](unix/globbing-for-all-directories-in-zsh.md)
|
||||
- [Globbing For Filenames In Zsh](unix/globbing-for-filenames-in-zsh.md)
|
||||
- [Gracefully Exit A Script With Trap](unix/gracefully-exit-a-script-with-trap.md)
|
||||
- [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)
|
||||
|
||||
27
git/count-all-files-of-specific-type-tracked-by-git.md
Normal file
27
git/count-all-files-of-specific-type-tracked-by-git.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Count All Files Of Specific Type Tracked By Git
|
||||
|
||||
I want to get a count of all the markdown files in my [TIL
|
||||
repo](https://github.com/jbranchaud/til). Since all the files I care about are
|
||||
tracked by `git`, I can use `git ls-files` to get a listing of all files. That
|
||||
command on its own lists all files tracked by your git repository. Though there
|
||||
are many other flags we can apply, that will do for my purposes.
|
||||
|
||||
By giving `git ls-files` a pattern to match against, I can turn up just, for
|
||||
instance, markdown files (`*.md`). I can pipe that to `wc -l` to get a count
|
||||
rather than exploding my terminal with a list of file names.
|
||||
|
||||
```bash
|
||||
❯ git ls-files '*.md' | wc -l
|
||||
1503
|
||||
```
|
||||
|
||||
That command includes `README.md` and `CONTRIBUTING.md`, but really I only want
|
||||
to count the markdown files that constitute a TIL. Those all happen to be
|
||||
nested under a single directory. So I can tweak the glob pattern like so:
|
||||
|
||||
```bash
|
||||
❯ git ls-files '*/*.md' | wc -l
|
||||
1501
|
||||
```
|
||||
|
||||
See `man git-ls-files` for more details.
|
||||
22
python/dunder-methods.md
Normal file
22
python/dunder-methods.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Dunder Methods
|
||||
|
||||
Python has all kinds of special, or rather, _magic_ methods that allow for
|
||||
customizing all kinds of class behavior. There is `__init__()`, `__bool__()`,
|
||||
and so many others.
|
||||
|
||||
The thing they all have in common is that their names are wrapped in _double
|
||||
underscores_. This is why they are called _dunder methods_.
|
||||
|
||||
Some of these are used every single day, like the `__init__()` method for
|
||||
defining how a class should create an object. Others, used from time to time,
|
||||
are for overriding how comparisons or conversions happen. E.g. you may want to
|
||||
override `__bool__()` or `__len__()` to customize the truthiness of a custom
|
||||
class.
|
||||
|
||||
There are so many others, ones you probably haven't even heard of. To see a
|
||||
full listing, check out this [cheat sheet of every dunder
|
||||
method](https://www.pythonmorsels.com/every-dunder-method/#cheat-sheet).
|
||||
|
||||
Note: these are not to be confused with _dunder attributes_ which are things
|
||||
like `__name__`, `__file__`, and `__version__` which correspond to a value that
|
||||
you can access in a specific context rather than behavior to override.
|
||||
49
rails/empty-find-by-returns-first-record.md
Normal file
49
rails/empty-find-by-returns-first-record.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Empty find_by Returns First Record
|
||||
|
||||
During a RubyConf 2024 talk, a speaker mentioned that if you pass `nil` to
|
||||
[ActiveRecord's `#find_by`
|
||||
method](https://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find_by),
|
||||
it will return the first record from the database. This is a bit unintuitive,
|
||||
so lets look at an example and then I'll show you why.
|
||||
|
||||
```ruby
|
||||
> Book.first
|
||||
#=> #<Book:0x00000001142e4c48 id: 13, title: "The Secret History", ... >
|
||||
|
||||
> Book.find_by(nil)
|
||||
#=> #<Book:0x00000001142ca3c0 id: 13, title: "The Secret History", ... >
|
||||
```
|
||||
|
||||
So, that is the same object in both cases, but why?
|
||||
|
||||
Our first hint is in the SQL that gets constructed when making that method
|
||||
call.
|
||||
|
||||
```ruby
|
||||
Book Load (2.5ms) SELECT "books".* FROM "books" LIMIT $1 [["LIMIT", 1]]
|
||||
```
|
||||
|
||||
It's grabbing all books and limiting to _one_ result.
|
||||
|
||||
Lets look at the underlying implementation of the `#find_by` method.
|
||||
|
||||
```ruby
|
||||
# File activerecord/lib/active_record/relation/finder_methods.rb, line 111
|
||||
def find_by(arg, *args)
|
||||
where(arg, *args).take
|
||||
end
|
||||
```
|
||||
|
||||
Sure enough, the implementation is a `#where` followed by a `#take`. Since the
|
||||
`#where` is receiving `nil` as its `arg`, there are no conditions _filtering_
|
||||
the query. And the `#take` corresponds to the `limit 1`.
|
||||
|
||||
Knowing that, we can understand that we will also get the first record from the
|
||||
database if we call `#find_by` with `{}`. Again, no conditions to filter on, so
|
||||
give me all books limited to one.
|
||||
|
||||
One small caveat: notice how there is no `order by` clause in the above SQL
|
||||
output. This differs from `Books.first` which implicitly does an order on the
|
||||
`id` column. Though these method are likely to return the same result, the
|
||||
ordering of `#find_by` is not guaranteed to be the same without an `order by`
|
||||
clause.
|
||||
38
ruby/execute-several-commands-with-backtick-heredoc.md
Normal file
38
ruby/execute-several-commands-with-backtick-heredoc.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Execute Several Commands With Backtick Heredoc
|
||||
|
||||
A fun feature of Ruby is that we can execute a command in a subprocess just by
|
||||
wrapping it in backticks.
|
||||
|
||||
For instance, we might shell out to `git` to check if a file is tracked:
|
||||
|
||||
```ruby
|
||||
`git ls-files --error-unmatch #{file_path} 2>/dev/null`
|
||||
$?.success?
|
||||
```
|
||||
|
||||
But what if we need to execute several commands? Perhaps they depend on one
|
||||
another. We want them to run in the same subprocess.
|
||||
|
||||
For this, we can use the backtick version of a heredoc. That is a special
|
||||
version of a heredoc where the delimiter is wrapped in backticks.
|
||||
|
||||
```ruby
|
||||
puts <<`SHELL`
|
||||
# Set up trap
|
||||
trap 'echo "Cleaning up temp files"; rm -f *.tmp' EXIT
|
||||
|
||||
# Create temporary file
|
||||
echo "test data" > work.tmp
|
||||
|
||||
# Do some work
|
||||
cat work.tmp
|
||||
|
||||
# Trap will clean up on exit
|
||||
SHELL
|
||||
```
|
||||
|
||||
Here we set up a `trap` for file cleanup on exit, then create a file, then do
|
||||
something with the file, and that's it, the process exits (triggering the
|
||||
trap).
|
||||
|
||||
[source](https://ruby-doc.org/3.3.6/syntax/literals_rdoc.html#label-Here+Document+Literals)
|
||||
29
unix/gracefully-exit-a-script-with-trap.md
Normal file
29
unix/gracefully-exit-a-script-with-trap.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Gracefully Exit A Script With Trap
|
||||
|
||||
With `trap` you can intercept signals that would cause your script to exit and
|
||||
then inject some additional behavior. Perhaps you want to make sure the script
|
||||
cleans up after itself before it exists.
|
||||
|
||||
During this script's execution, it creates a file in the filesystem. It would
|
||||
be nice to make sure that no matter path this script ends up down that it will
|
||||
clean up after itself as it exits. We set up a `trap` that looks for the `EXIT`
|
||||
signal to do this.
|
||||
|
||||
```bash
|
||||
# Set up trap
|
||||
trap 'echo "Cleaning up temp files"; rm -f *.tmp' EXIT
|
||||
|
||||
# Create temporary file
|
||||
echo "test data" > work.tmp
|
||||
|
||||
# Do some work
|
||||
cat work.tmp
|
||||
|
||||
# Trap will clean up on exit
|
||||
```
|
||||
|
||||
Whatever is in quotes is what the trap will execute when it is triggered. The
|
||||
following one or more signals are what the trap listens for, in this case
|
||||
`EXIT`.
|
||||
|
||||
[source](https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html)
|
||||
Reference in New Issue
Block a user