mirror of
https://github.com/jbranchaud/til
synced 2026-01-20 15:38:02 +00:00
Compare commits
7 Commits
cab482c7e6
...
7c41c38d13
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c41c38d13 | ||
|
|
adc6b2e903 | ||
|
|
9a6ebd4c6b | ||
|
|
6df0693804 | ||
|
|
507602ef0c | ||
|
|
18bdcc88b8 | ||
|
|
295fe153ad |
@@ -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).
|
For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186).
|
||||||
|
|
||||||
_1493 TILs and counting..._
|
_1496 TILs and counting..._
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -442,6 +442,7 @@ _1493 TILs and counting..._
|
|||||||
- [Add Emoji To GitHub Repository Description](internet/add-emoji-to-github-repository-description.md)
|
- [Add Emoji To GitHub Repository Description](internet/add-emoji-to-github-repository-description.md)
|
||||||
- [Analyze Your Website Performance](internet/analyze-your-website-performance.md)
|
- [Analyze Your Website Performance](internet/analyze-your-website-performance.md)
|
||||||
- [Check Your Public IP Address](internet/check-your-public-ip-address.md)
|
- [Check Your Public IP Address](internet/check-your-public-ip-address.md)
|
||||||
|
- [Digraph Unicode Characters Have A Titlecase](internet/digraph-unicode-characters-have-a-titlecase.md)
|
||||||
- [Enable Keyboard Shortcuts In Gmail](internet/enable-keyboard-shortcuts-in-gmail.md)
|
- [Enable Keyboard Shortcuts In Gmail](internet/enable-keyboard-shortcuts-in-gmail.md)
|
||||||
- [Exclude AI Overview From Google Search](internet/exclude-ai-overview-from-google-search.md)
|
- [Exclude AI Overview From Google Search](internet/exclude-ai-overview-from-google-search.md)
|
||||||
- [Exclude Whitespace Changes From GitHub Diffs](internet/exclude-whitespace-changes-from-github-diffs.md)
|
- [Exclude Whitespace Changes From GitHub Diffs](internet/exclude-whitespace-changes-from-github-diffs.md)
|
||||||
@@ -839,6 +840,7 @@ _1493 TILs and counting..._
|
|||||||
- [Survey Of User-Defined Ordering Of Records](postgres/survey-of-user-defined-ordering-of-records.md)
|
- [Survey Of User-Defined Ordering Of Records](postgres/survey-of-user-defined-ordering-of-records.md)
|
||||||
- [Switch Non-Castable Column Type With Using Clause](postgres/switch-non-castable-column-type-with-using-clause.md)
|
- [Switch Non-Castable Column Type With Using Clause](postgres/switch-non-castable-column-type-with-using-clause.md)
|
||||||
- [Switch The Running Postgres Server Version](postgres/switch-the-running-postgres-server-version.md)
|
- [Switch The Running Postgres Server Version](postgres/switch-the-running-postgres-server-version.md)
|
||||||
|
- [Table Names Are Treated As Lower-Case By Default](postgres/table-names-are-treated-as-lower-case-by-default.md)
|
||||||
- [Temporarily Disable Triggers](postgres/temporarily-disable-triggers.md)
|
- [Temporarily Disable Triggers](postgres/temporarily-disable-triggers.md)
|
||||||
- [Temporary Tables](postgres/temporary-tables.md)
|
- [Temporary Tables](postgres/temporary-tables.md)
|
||||||
- [Terminating A Connection](postgres/terminating-a-connection.md)
|
- [Terminating A Connection](postgres/terminating-a-connection.md)
|
||||||
@@ -980,6 +982,7 @@ _1493 TILs and counting..._
|
|||||||
- [Parse Request Params In Rack::Attack Block](rails/parse-request-params-in-rack-attack-block.md)
|
- [Parse Request Params In Rack::Attack Block](rails/parse-request-params-in-rack-attack-block.md)
|
||||||
- [Perform SQL Explain With ActiveRecord](rails/perform-sql-explain-with-activerecord.md)
|
- [Perform SQL Explain With ActiveRecord](rails/perform-sql-explain-with-activerecord.md)
|
||||||
- [Polymorphic Path Helpers](rails/polymorphic-path-helpers.md)
|
- [Polymorphic Path Helpers](rails/polymorphic-path-helpers.md)
|
||||||
|
- [Prefer select_all Over execute For Read Queries](rails/prefer-select-all-over-execute-for-read-queries.md)
|
||||||
- [Pretend Generations](rails/pretend-generations.md)
|
- [Pretend Generations](rails/pretend-generations.md)
|
||||||
- [Prevent Writes With A Sandboxed Rails Console](rails/prevent-writes-with-a-sandboxed-rails-console.md)
|
- [Prevent Writes With A Sandboxed Rails Console](rails/prevent-writes-with-a-sandboxed-rails-console.md)
|
||||||
- [Query A Single Value From The Database](rails/query-a-single-value-from-the-database.md)
|
- [Query A Single Value From The Database](rails/query-a-single-value-from-the-database.md)
|
||||||
|
|||||||
29
internet/digraph-unicode-characters-have-a-titlecase.md
Normal file
29
internet/digraph-unicode-characters-have-a-titlecase.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Digraph Unicode Characters Have a Titlecase
|
||||||
|
|
||||||
|
Coming from primarily being exposed to the US American alphabet, I'm familiar
|
||||||
|
with characters that I type into the computer having one of two cases. Either
|
||||||
|
it is lowercase by default (`c`) or I can hit the shift key to produce the
|
||||||
|
uppercase version (`C`).
|
||||||
|
|
||||||
|
Unicode, which has broad support for character encoding across most languages,
|
||||||
|
has a couple characters that are called _digraphs_. These are single code
|
||||||
|
points, but look like they are made up of two characters.
|
||||||
|
|
||||||
|
A good example of this is `dž`. And if that character were to appear in an all
|
||||||
|
uppercase word, then it would display as `DŽ`.
|
||||||
|
|
||||||
|
But what if it appears at the beginning of a capitalized word?
|
||||||
|
|
||||||
|
That's where _titlecase_ comes into the picture -- `Dž`.
|
||||||
|
|
||||||
|
From [wikipedia](https://en.wikipedia.org/wiki/D%C5%BE):
|
||||||
|
|
||||||
|
> Note that when the letter is the initial of a capitalised word (like Džungla
|
||||||
|
> or Džemper, or personal names like Džemal or Džamonja), the ž is not
|
||||||
|
> uppercase. Only when the whole word is written in uppercase, is the Ž
|
||||||
|
> capitalised.
|
||||||
|
|
||||||
|
(I find it odd that wikipedia's article on this digraph code point is using
|
||||||
|
separate characters instead of the digraph.)
|
||||||
|
|
||||||
|
[source](https://devblogs.microsoft.com/oldnewthing/20241031-00/?p=110443)
|
||||||
@@ -5,6 +5,8 @@ an array-like object with all of the arguments to the function. Even if not
|
|||||||
all of the arguments are referenced in the function signature, they can
|
all of the arguments are referenced in the function signature, they can
|
||||||
still be accessed via the `arguments` object.
|
still be accessed via the `arguments` object.
|
||||||
|
|
||||||
|
> For ES6+ compatibility, the `spread` operator used via [rest parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) is preferred over the `arugments` object when accessing an abritrary number of function arguments.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function argTest(one) {
|
function argTest(one) {
|
||||||
console.log(one);
|
console.log(one);
|
||||||
|
|||||||
@@ -32,6 +32,16 @@ select string_agg(
|
|||||||
from positions, random_bytes, chars;
|
from positions, random_bytes, chars;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Here is an example of the output:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
+----------+
|
||||||
|
| short_id |
|
||||||
|
|----------|
|
||||||
|
| NXdu9AnV |
|
||||||
|
+----------+
|
||||||
|
```
|
||||||
|
|
||||||
The
|
The
|
||||||
[`generate_series`](https://www.postgresql.org/docs/current/functions-srf.html)
|
[`generate_series`](https://www.postgresql.org/docs/current/functions-srf.html)
|
||||||
gives us an 8-row table from 0 to 7 that we can use as indexes into the byte
|
gives us an 8-row table from 0 to 7 that we can use as indexes into the byte
|
||||||
|
|||||||
80
postgres/table-names-are-treated-as-lower-case-by-default.md
Normal file
80
postgres/table-names-are-treated-as-lower-case-by-default.md
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# Table Names Are Treated As Lower-Case By Default
|
||||||
|
|
||||||
|
This one is a bit unintuitive and can cause some real confusion -- when you
|
||||||
|
create a table in PostgreSQL, any casing is ignored, it is treated as
|
||||||
|
lower-case. Let's see it to believe it:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
> create table BookMarks (
|
||||||
|
id integer generated always as identity primary key,
|
||||||
|
location text not null
|
||||||
|
);
|
||||||
|
|
||||||
|
> \d
|
||||||
|
+--------+--------------------+----------+----------+
|
||||||
|
| Schema | Name | Type | Owner |
|
||||||
|
|--------+--------------------+----------+----------|
|
||||||
|
| public | bookmarks | table | postgres |
|
||||||
|
| public | bookmarks_id_seq | sequence | postgres |
|
||||||
|
+--------+--------------------+----------+----------+
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice that when we list our tables, the uppercase `M` and `B` are gone. That's
|
||||||
|
because Postgres folds away the casing when processing the table name
|
||||||
|
identifier.
|
||||||
|
|
||||||
|
It doesn't matter how we refer to it for queries:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
> select * from BookMarks;
|
||||||
|
+----+----------+
|
||||||
|
| id | location |
|
||||||
|
|----+----------|
|
||||||
|
+----+----------+
|
||||||
|
|
||||||
|
> select * from bookmarks;
|
||||||
|
+----+----------+
|
||||||
|
| id | location |
|
||||||
|
|----+----------|
|
||||||
|
+----+----------+
|
||||||
|
```
|
||||||
|
|
||||||
|
You can force Postgres to respect the casing by wrapping the table name in
|
||||||
|
quotes.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
> create table "BookMarks" (
|
||||||
|
id integer generated always as identity primary key,
|
||||||
|
location text not null
|
||||||
|
);
|
||||||
|
|
||||||
|
> \d
|
||||||
|
+--------+--------------------+----------+----------+
|
||||||
|
| Schema | Name | Type | Owner |
|
||||||
|
|--------+--------------------+----------+----------|
|
||||||
|
| public | BookMarks | table | postgres |
|
||||||
|
| public | BookMarks_id_seq | sequence | postgres |
|
||||||
|
+--------+--------------------+----------+----------+
|
||||||
|
|
||||||
|
> select * from "BookMarks";
|
||||||
|
+----+----------+
|
||||||
|
| id | location |
|
||||||
|
|----+----------|
|
||||||
|
+----+----------+
|
||||||
|
|
||||||
|
> select * from "bookmarks";
|
||||||
|
relation "bookmarks" does not exist
|
||||||
|
LINE 1: select * from "bookmarks"
|
||||||
|
^
|
||||||
|
|
||||||
|
> select * from BookMarks;
|
||||||
|
relation "bookmarks" does not exist
|
||||||
|
LINE 1: select * from BookMarks
|
||||||
|
^
|
||||||
|
```
|
||||||
|
|
||||||
|
That then means you have to quote your table name anytime you want to refer to
|
||||||
|
it in a query. It's not worth it. It is better to always keep your table names
|
||||||
|
lower-case using snake case.
|
||||||
|
|
||||||
|
[source](https://weiyen.net/articles/avoid-capital-letters-in-postgres-names)
|
||||||
63
rails/prefer-select-all-over-execute-for-read-queries.md
Normal file
63
rails/prefer-select-all-over-execute-for-read-queries.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# Prefer select_all Over execute For Read Queries
|
||||||
|
|
||||||
|
Though the `#execute` function provided by ActiveRecord technically works as a
|
||||||
|
general-purpose query runner for strings of raw SQL, it has some downsides.
|
||||||
|
|
||||||
|
First, let's say we have a large semi-complex (better in SQL than ActiveRecord
|
||||||
|
DSL) SQL query defined in a heredoc.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
books_by_status_query = <<-SQL
|
||||||
|
select
|
||||||
|
books.*,
|
||||||
|
latest_statuses.status as current_status,
|
||||||
|
array_to_json(array_agg(...)) as reading_statuses
|
||||||
|
from books
|
||||||
|
-- plus several left joins
|
||||||
|
-- where clause, group by, and order by
|
||||||
|
SQL
|
||||||
|
```
|
||||||
|
|
||||||
|
I reflexively reach for
|
||||||
|
[`#execute`](https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html#method-i-execute)
|
||||||
|
in a situation like that:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
result = ActiveRecord::Base.connection.execute(books_by_status_query)
|
||||||
|
```
|
||||||
|
|
||||||
|
However, if we're doing a read-only query and we are expecting multiple rows in
|
||||||
|
the result, then we are better off reaching for
|
||||||
|
[`#select_all`](https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html#method-i-select_all).
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
result = ActiveRecord::Base.connection.select_all(books_by_status_query)
|
||||||
|
```
|
||||||
|
|
||||||
|
It has the advantage of semantically communicating that it's just a read and
|
||||||
|
won't have any side-effects. It also avoids an unnecessary clear of the query
|
||||||
|
cache.
|
||||||
|
|
||||||
|
> Note: [when execute is used] the query is assumed to have side effects and
|
||||||
|
> the query cache will be cleared. If the query is read-only, consider using
|
||||||
|
> select_all instead.
|
||||||
|
|
||||||
|
The `#execute` method also has been known to leak memory with some database
|
||||||
|
connectors.
|
||||||
|
|
||||||
|
> Note: depending on your database connector, the result returned by this
|
||||||
|
> method may be manually memory managed. Consider using exec_query wrapper
|
||||||
|
> instead.
|
||||||
|
|
||||||
|
We can then iterate through and transform the results just as we would have
|
||||||
|
done with `#execute`.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
result.map do |row|
|
||||||
|
row.tap do |hash|
|
||||||
|
hash["reading_statuses"] = JSON.parse(hash["reading_statuses"])
|
||||||
|
end
|
||||||
|
|
||||||
|
OpenStruct.new(row)
|
||||||
|
end
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user