# Today I learned
> Articles and learnings on Elixir, Rust, Ruby, Go, Javascript, Platform engineering, SRE.
Public Ghost content for AI and LLM tooling. This file includes a bounded export of public pages first, then recent public posts.
Append `.md` to any post or page URL to get the content in Markdown (for example, `/example-post.md`).
## Pages
### About this site
URL: https://til.codes/about/
Last updated: 2024-07-13T20:54:24.000Z
Today I learned is an independent publication launched in July 2024 by Manu Ajith. If you subscribe today, you'll get full access to the website as well as email newsletters about new content when it's available. Your subscription makes this site possible, and allows Today I learned to continue to exist. Thank you!
### Access all areas
By signing up, you'll get access to the full archive of everything that's been published before and everything that's still to come. Your very own private library.
### Fresh content, delivered
Stay up to date with new content sent straight to your inbox! No more worrying about whether you missed something because of a pesky algorithm or news feed.
### Meet people like you
Join a community of other subscribers who share the same interests.
---
### Start your own thing
Enjoying the experience? Get started for free and set up your very own subscription business using [Ghost](https://ghost.org/?ref=til.codes), the same platform that powers this website.
## Posts
### Gremlins After Midnight: How 794 Git Packs Hit the macOS 256 File Limit
URL: https://til.codes/gremlins-after-midnight-how-794-git-packs-hit-the-macos-256-file-limit/
Last updated: 2026-06-02T21:39:40.000Z
This was on Determinate Nix 3.15.2 (Nix 2.33.1). If you are on something newer, the specific failure below may not reproduce: Nix 2.34 and Determinate Nix 3.16 both started raising the soft descriptor limit at process startup, which defuses this exact class of crash. The mechanics are still worth understanding, because the underlying ingredients have not changed.
I ran `darwin-rebuild switch` the way I have a thousand times. Same flake, same machine, nothing exotic in the diff. It had worked that morning. This time it fell over before it built a single derivation:
```
error: opening Git repository "~/.cache/nix/tarball-cache-v2": could not open '~/.cache/nix/tarball-cache-v2/config': Too many open files
```
Too many open files. On a rebuild that touches my own config. Nothing was leaking, nothing was in a loop. The machine had simply run out of something, and the something was file descriptors.
## What a file descriptor limit even is
Every open file, socket, and pipe in a Unix process is a file descriptor: a small integer that the kernel hands back so you can refer to it later. There is a cap on how many a single process may hold open at once, and on macOS there are two of them. The soft limit is what a process gets by default, and it can be raised on its own up to the hard limit. The hard limit is the ceiling, and only the root can lift it.
You can read both from a shell:
```
$ ulimit -Sn; ulimit -Hn
1048576
unlimited
```
So my interactive shell was fine: a million descriptors soft, no hard ceiling. That high number is not a macOS default, though. A stock login shell on macOS also starts at 256; something in my environment had raised it long ago, and I had forgotten. If the rebuild had run from this shell, it would have inherited the raised limit and never noticed. Here is the catch: not everything runs from your shell.
macOS keeps a third number, the one launchd uses, and that is the one that bites. launchd is the system supervisor, and it seeds the limits for anything it starts: daemons, agents, and any process spawned by something that did not bother to raise its own soft limit. Ask launchd what it thinks:
```bash
$ launchctl limit maxfiles
maxfiles 256 unlimited
```
There it is. 256\. In 2026, a fresh macOS still imposes a soft limit of 256 open files on new processes, a number that would have felt generous on a workstation in 1995\. Whatever raised my shell's limit never touched launchd, so the low number sat out of sight. Anything launchd starts, rather than my shell, does not get the favor.
## Why libgit2 opens so many at once
The path in the error is a clue most people skip past. `~/.cache/nix/tarball-cache-v2` is not a plain directory of downloaded tarballs. It is a Git repository. Nix keeps its flake and tarball inputs in a libgit2-backed store, which is why the failure is literally "opening Git repository" and the file it choked on is `config`, the first thing any Git repo reads on open.
libgit2 is the C library Nix links against to talk to that store. A pack comes in pairs: a `.pack` with the compressed objects and a `.idx` with the lookup table. To resolve objects, libgit2 `mmap`s pack files and keeps them mapped, so the descriptors it holds scale with how many packs are in the object store. There is a configurable cap on this (`GIT_OPT_SET_MWINDOW_FILE_LIMIT`), but the point that matters here is the direction: more packs means more descriptors held open while the cache is in use, and opening or indexing a cache full of packs is exactly when that count spikes.
Wait. Why would there be enough packs for that to matter? A healthy repo has a handful.
## Why the cache grows a forest of packs
A Git pack is normally the product of garbage collection: many loose objects compacted into one tidy file. But Nix's tarball cache is not gc'd on a schedule the way a working repo is. As it fetches flake inputs and tarball revisions, it writes packs, and nothing ever runs maintenance to fold them back together. They just accumulate for as long as the cache lives.
I counted mine:
```bash
$ du -sh ~/.cache/nix/tarball-cache-v2
306M ~/.cache/nix/tarball-cache-v2
$ find ~/.cache/nix/tarball-cache-v2/objects/pack -type f | wc -l
1593
```
1593 files in the pack directory: `.idx` and `.pack` paired up, plus a few stragglers, so on the order of 790-odd packs. Against a soft limit of 256, a cache this size does not need anything exotic to go wrong; the descriptors libgit2 holds while working through the packs are enough to walk a 256-limit process off the edge. The cache had quietly grown a forest, and the rebuild was the first thing to walk into it from a process that inherited launchd's stingy 256 instead of my shell's million.
Two correct decisions composed into one broken rebuild. Nix never compacts the cache because it is a cache, and compaction is not free. macOS ships a tiny soft limit because it always has, and your shell hides it.
## The immediate fix: collapse the packs
The fastest way out is to give libgit2 fewer files to open. The instinct is to reach for `git gc --aggressive --prune=now`, and do not: this cache has no refs of its own (`git -C ~/.cache/nix/tarball-cache-v2 show-ref` comes back empty), so every object is unreachable from gc's point of view. `--prune=now` then happily discards the cached inputs you were trying to keep. You end up with a tidy repo and an empty cache.
The safe way to compact in place is the multi-pack-index, which folds the packs without pruning objects out from under Nix:
```
git -C ~/.cache/nix/tarball-cache-v2 multi-pack-index write
git -C ~/.cache/nix/tarball-cache-v2 multi-pack-index repack
git -C ~/.cache/nix/tarball-cache-v2 multi-pack-index expire
```
That collapses the pack count, reducing the descriptors libgit2 needs to a handful while leaving the actual objects intact. The rebuild stops the limit from tripping because the limit is no longer the binding constraint.
If you do not care about keeping the cached inputs, there is an even blunter option. It is a cache, so you are allowed to throw it away:
```
rm -rf ~/.cache/nix/tarball-cache-v2
```
Nix rebuilds it clean on the next fetch. The repack is the nicer move because you keep everything already downloaded, but both clear the immediate error. I repacked.
## The durable fix: tell launchd to stop being from 1995
Repacking buys you time. It does not stop the packs from accumulating again, and it does nothing about the actual root cause, which is that 256 soft limit waiting to ambush the next process launchd spawns. The real fix is to raise launchd's `maxfiles` so it survives reboots and applies to invokers that never see your shell rc.
For the running session, raise it directly:
```
sudo launchctl limit maxfiles 524288 524288
```
That sets both the soft and hard limit to 524288 until the next reboot. To make it stick, drop a launch daemon at `/Library/LaunchDaemons/limit.maxfiles.plist` that re-applies the same limit every boot:
```xml
Label
limit.maxfiles
ProgramArguments
launchctl
limit
maxfiles
524288
524288
RunAtLoad
```
It runs one command at load, `launchctl limit maxfiles 524288 524288`, and exits. After a reboot, `launchctl limit maxfiles` reports `524288 524288` instead of the factory `256`, and every process launchd starts inherits the saner ceiling.
It is worth a look at what the Nix daemon itself already does, because it solved this for its own process years ago. The `systems.determinate.nix-daemon` plist sets `SoftResourceLimits` and `HardResourceLimits` with `NumberOfFiles` at 1048576\. The daemon was never the thing hitting the wall. The thing hitting the wall was whatever spawned the `nix` invocation for the rebuild, inheriting 256 because nobody told launchd otherwise.
## Where it landed
After the repack the rebuild went through on the first try. After the plist, `launchctl limit maxfiles` shows 524288 across the board, so a future pack forest will have room to breathe even from a non-shell invoker. I still expect to repack that cache again someday, because Nix will keep minting packs and never folding them, but it will not take the rebuild down with it.
The takeaway I am keeping: when a tool dies with "Too many open files" on macOS, do not trust `ulimit` in your shell. Your shell may show a comfortable number that launchd never agreed to. Ask `launchctl limit maxfiles` what the process actually inherited, because that is the limit that was really in force.
### When the Nix Eval Cache Serves You a Ghost Derivation
URL: https://til.codes/when-the-nix-eval-cache-serves-you-a-ghost-derivation/
Last updated: 2026-05-31T22:00:57.000Z
The project config said `15432`. The process was on `15433`. Tests could not connect, because they were dialing the port the app expected and nothing was answering there.
I opened `devenv.nix`. Port 15432\. I opened `.env`. Port 15432\. I grepped the whole repo for 15433\. Nothing. Not a single reference. And yet `devenv up` had booted Postgres on 15433, and it had done it confidently, with no warning, every single time.
So the question was simple and infuriating. Neither `.env` nor `devenv.nix` mentions 15433 anywhere. Both say 15432\. Where is Postgres getting 15433 from?
One caveat before blaming the cache: in devenv 2.x, the Postgres port is also the base for automatic port allocation, so 15433 can be legitimate if 15432 is already occupied. That did not make the mismatch less real. It just meant I needed to find the exact generated config the running process had loaded.
## What is actually listening
First, confirm reality. The config is a claim; the running process is the fact. So I went and looked at the fact.
The Postgres that was actually serving had its data directory at `.devenv/state/postgres`, and that directory had a `postgresql.conf` in it. Line 17:
```
port = 15433
```
There it is. Not in any file I had edited. Sitting in the runtime state directory that devenv manages. So the next question writes itself. Who put 15433 in `.devenv/state/postgres/postgresql.conf`?
## Walking the process tree
In this setup, devenv did not start Postgres directly. It started a process manager wrapper, which ran a chain of generated scripts. Following the running process back up:
```
devenv-processes-postgres
-> /nix/store/vy3ndzy...-start-postgres/bin/start-postgres
-> /nix/store/f7zr5mg...-setup-postgres/bin/setup-postgres
```
`setup-postgres` is the interesting one. It is the script that prepares `$PGDATA` before the server boots. And the way devenv ships a `postgresql.conf` is not by templating it into the state directory at runtime. It bakes the config into the Nix store at evaluation time and then copies it into place. The relevant line inside that setup script:
```
cp /nix/store/dasdnbj41...-postgresql.conf "$PGDATA/postgresql.conf"
```
So the `postgresql.conf` in my state directory was not authored by me and was not derived from the `devenv.nix` I had open. It was `cp`\-ed out of a specific store path. Read that store path:
```
$ cat /nix/store/dasdnbj41rjsw5hnp94vw2vfdllqvz20-postgresql.conf
...
port = 15433
```
The store object had 15433 baked in. The lie was now located. It lived in an immutable Nix store path, and `setup-postgres` faithfully stamped it into my data directory every time it ran.
## The part where it gets genuinely weird
Here is the catch. My current shell's PATH did not point at that derivation.
When I checked which `start-postgres` was on my PATH, it resolved to a *different* store hash:
```
/nix/store/90bj99hi3f1d1vffwl34qbag44f15043-start-postgres/bin/start-postgres
```
But the process actually running had been launched from:
```
/nix/store/vy3ndzyhaa961vd5swbahdlx0hzafi0w-start-postgres/bin/start-postgres
```
Two different `start-postgres` derivations. The one in my shell would copy a 15432 conf. The one that the live process had actually come from was an older build that copied the 15433 conf.
Same name. Different content. My environment was internally inconsistent: the interactive shell knew about the new world, but the running daemon was still a fossil from the old one. That alone did not prove the eval cache was guilty; it proved the live process was not using the derivation I thought it was using. That is why grepping the repo found nothing. The 15433 was never in the repo. It was frozen inside a store object that the live process was still pointed at.
Wait. If `devenv.nix` already says 15432, why was the old derivation still getting revived?
## The eval cache is the part to distrust
devenv keeps an evaluation cache so it does not have to re-run Nix evaluation on every command. It lives here:
```
.devenv/nix-eval-cache.db
.devenv/nix-eval-cache.db-shm
.devenv/nix-eval-cache.db-wal
```
That cache maps evaluated attributes to the files, environment variables, and options they depended on. It is supposed to invalidate when a source file read during evaluation changes. Fast in the common case. A trap when that dependency tracking goes sideways.
The cache should have noticed my edit and rebuilt the process config. But the result I kept getting was the stale `start-postgres` derivation, and forcing the cache to refresh was what finally broke the loop. That old derivation referenced the stale `postgresql.conf` store path. `setup-postgres` copied 15433 into my data directory. Postgres booted on 15433\. Every restart reproduced the exact same wrong port, which is precisely why it felt like gaslighting. A flaky bug you can dismiss. A bug that is perfectly consistent and contradicts the file in front of you is the one that makes you doubt your own eyes.
## The fix
To get unblocked for tests immediately, the cheapest move is to stop arguing with the running process and just point the client at where Postgres actually is. Set the port in `.env` to match reality:
```
DB_PORT=15433
```
Postgres was already up on 15433, so tests connect right away. One line, reversible, buys you time.
But that is a workaround, not a fix. The actual repair is to force devenv to refresh its eval cache so it re-reads the file I edited:
```bash
# stop the devenv processes first
devenv up --refresh-eval-cache
```
If that still leaves the cache wedged, the sledgehammer version is deleting `.devenv/nix-eval-cache.db` and its SQLite sidecar files, if they exist.
With the cache refreshed, devenv re-evaluates `devenv.nix`, produces a fresh `start-postgres` derivation, that derivation references a `postgresql.conf` store path with `port = 15432`, and `setup-postgres` copies the correct conf into `$PGDATA`. Postgres comes up on 15432\. The config and the process finally agree, and I reverted the `.env` line.
There is a tempting third option I deliberately avoided: hand-editing `.devenv/state/postgres/postgresql.conf` from 15433 back to 15432\. It works until the next `devenv up`, at which point `setup-postgres` cheerfully `cp`s the stale store conf right back over your edit. Editing the copy is pointless when the source of the copy is the thing that is wrong.
The Nix lesson is the one worth carrying out of this. There are three layers and you have to keep them straight: the config you declare in `devenv.nix`, the immutable artifact that config evaluates to in the store, and the eval cache that is supposed to decide when to re-derive that artifact. When the running process diverges from the file you are editing, the file is rarely the liar. Walk down to the store path the process actually loaded, account for port allocation, and if that path is older than your last edit, suspect the process state and the cache that handed it to you.
### The Filter in the Wrong Place: 76x Faster by Moving One WHERE Clause
URL: https://til.codes/the-filter-in-the-wrong-place-76x-faster-by-moving-one-where-clause/
Last updated: 2026-05-29T17:29:26.000Z
I was reviewing a PR that added a `GET /accounts` endpoint to a payments API. Each account has many transactions, and the endpoint returns each account's most recent transaction so the list can show last activity at a glance. It supports a partial name filter and paginates. The shape was sensible. The query looked reasonable until I saw where the name filter landed.
The ranking was a textbook window function. For each account, rank that account's transactions newest first, and keep rank 1\. In Ecto it built up as a pipeline of subqueries:
```elixir
defp ranked_transaction_query do
from t in Transaction,
select: %{
account_id: t.account_id,
amount: t.amount,
currency: t.currency,
inserted_at: t.inserted_at,
rank:
over(row_number(),
partition_by: t.account_id,
order_by: [desc: t.inserted_at, desc: t.id]
)
}
end
defp best_transaction_query(ranked) do
from t in subquery(ranked), where: t.rank == 1
end
```
Then it joined accounts onto that best-transaction subquery, ordered by name, and only then, on the outer query, applied the name filter:
```elixir
defp maybe_filter_by_name(query, name) do
sanitized = "%" <> QueryUtils.sanitize_like(name) <> "%"
where(query, [a, ...], ilike(a.name, ^sanitized))
end
```
Read top to bottom, it tells a clean story. Rank the transactions, take the newest per account, join the accounts, filter by name. Each step is correct in isolation. The results were right. The problem is the order those steps actually run in, and what the window function is forced to do because of it.
## How a window function actually evaluates
Does Postgres push an outer `ILIKE` filter down into a window subquery so it only ranks matching accounts?
Not in this case. Postgres can push an outer filter into a subquery that contains a window function, but only when the filter is on the partition key itself. Dropping a whole partition cannot change the ranking of the rows that survive, so that push is safe. The name filter is on `accounts.name`, which is not the partition key, and is not even a column the ranking subquery outputs. There is nothing for the planner to push down.
So the window has to work from the unfiltered transaction input. `row_number() OVER (PARTITION BY account_id ORDER BY ...)` is defined relative to each whole account partition, so a filter that removes arbitrary rows from inside a partition would change the ranking. Postgres has executor optimizations and does not have to literally materialize and number every row, but the planner still cannot use `accounts.name` to shrink the input to this transactions-only window subquery.
The name filter sat on the outer query, after the ranking subquery had already produced its output. By the time `ILIKE` ran, the window node had still been planned over the whole transactions table. The filter was not pruning the expensive input. It was discarding finished work. Searching for one account still paid the full cost of processing all \~40k transaction rows through that ranking plan, then kept the handful that matched.
That was the inversion. The cheapest, most selective predicate in the query, a name match that usually returns a few rows, was the last thing to run.
## What the numbers said
The endpoint logged the generated SQL. The unfiltered version shows the window running over the bare `transactions` table with no scoping at all:
```sql
SELECT a0."id", a0."name", t1."amount", t1."currency", t1."inserted_at"
FROM "accounts" AS a0
INNER JOIN (
SELECT tt0."account_id", tt0."amount", tt0."currency", tt0."inserted_at", tt0."rank"
FROM (
SELECT ttt0."account_id", ttt0."amount", ttt0."currency", ttt0."inserted_at",
row_number() OVER (
PARTITION BY ttt0."account_id"
ORDER BY ttt0."inserted_at" DESC, ttt0."id" DESC
) AS "rank"
FROM "transactions" AS ttt0
) AS tt0
WHERE (tt0."rank" = 1)
) AS t1 ON t1."account_id" = a0."id"
ORDER BY a0."name", a0."id"
LIMIT $1 OFFSET $2
```
The benchmark ran against 20k accounts and 40k transactions. The unfiltered listing came in around 66ms. With the filter applied the old way, ranking all 40k rows then matching the name, the filtered query measured about 61ms. Almost no savings, because the expensive part ran regardless of how few accounts matched. The filter was decoration on top of a full-table sort.
## Moving the filter into the subquery
The fix is to make the name match happen first, so the window only ever sees transactions that belong to matching accounts. Resolve the matching account ids up front, then scope the ranking subquery to those ids:
```elixir
defp matching_account_ids(name) do
sanitized = "%" <> QueryUtils.sanitize_like(name) <> "%"
from a in Account, where: ilike(a.name, ^sanitized), select: a.id
end
defp ranked_transaction_query(account_ids_query) do
from t in Transaction,
where: t.account_id in subquery(account_ids_query),
select: %{
account_id: t.account_id,
amount: t.amount,
currency: t.currency,
inserted_at: t.inserted_at,
rank:
over(row_number(),
partition_by: t.account_id,
order_by: [desc: t.inserted_at, desc: t.id]
)
}
end
```
Same window, same partition, same ordering. The only change is that the input to the window is now a few accounts' transactions instead of all of them. The `WHERE account_id IN (...)` runs at the same query level as the window, so it applies before the window is computed. Because it filters whole accounts in or out, every surviving account still gets its correct rank 1\. The `PARTITION BY account_id` work shrinks from 40k rows to whatever the name matched. A `pg_trgm` GIN index on `accounts.name` can make resolving those ids cheap, so the window starts from a tiny set.
The filtered query dropped from about 61ms to roughly 0.9ms. On the full benchmark the name-filter path sat at 0.86ms median against the 66ms unfiltered listing, about 76x faster. The query went from ranking the whole table then looking for Acme, to finding Acme then ranking only Acme's transactions.
## Why the unfiltered case is still inherent
The unfiltered listing is the honest baseline for this query shape, and it stays at \~66ms no matter what. When there is no name to filter on, there is nothing in this plan to scope the window down to. The window subquery has to consider the full transaction set to produce each account's most recent one, and offset pagination makes the outer query produce the ranked account rows before it can skip to a page in the middle. Walking to page 500 measured about 76ms versus 66ms for page 1, the extra \~10ms being Postgres skipping the \~9,980 rows ahead of the offset. That penalty grows linearly with page depth, and it is the price of offset pagination over this full-table window plan. Cursor-based pagination, a `LATERAL ... LIMIT 1` lookup, `DISTINCT ON` with the right index, or maintained latest-transaction state could attack the unfiltered path, but that is a separate problem. Moving the filter does not help the unfiltered path, and it was never supposed to.
## The escaping aside
One more thing I checked while I was in there, because interpolating user input into an `ILIKE` pattern is its own small trap. The filter wraps the search term in `%...%`, but the term itself can contain LIKE metacharacters. Someone searching for `50%` or `a_b` would otherwise have the `%` and `_` interpreted as wildcards, quietly matching far more than they asked for. The helper escapes them before interpolation:
```elixir
def sanitize_like(value) do
value
|> String.replace("\\", "\\\\")
|> String.replace("%", "\\%")
|> String.replace("_", "\\_")
end
```
Order matters here. Escape the backslash first, then the wildcards, otherwise you double-escape the backslashes you just added. With PostgreSQL's default LIKE escape behavior, `%` matches a literal percent sign and `_` matches a literal underscore. If you want that contract to be visible at the SQL boundary, add an explicit `ESCAPE '\'` too. The wrapping `%...%` the query adds itself stays meaningful, and only the user's own metacharacters get neutralized.
The takeaway from this review: a window-function subquery can block useful predicate pushdown unless the predicate safely removes whole partitions. Anything placed after the ranking can only discard rows the window plan already paid to produce. A predicate that filters on the partition key can be pushed down for free, but anything more selective, like a name match, has to live before the window, inside the subquery, or it buys you nothing. Correct results are not the same as correct order of operations, and with window functions the order is where the cost hides.
### Your Pin-to-Bottom Hook Is Missing the Users Who Need It Most
URL: https://til.codes/your-pin-to-bottom-hook-is-missing-the-users-who-need-it-most/
Last updated: 2026-04-22T08:17:11.000Z
If you're building a chat view, a log viewer, a live feed, or anything else that needs to stay pinned to the latest content, you'll eventually write a handler that recomputes scroll position when the layout changes. The instinct is to listen for the browser's `resize` event. That instinct is usually wrong, and the users it fails are the ones who need the feature to work most.
Here's how to recognize the problem, and what to use instead.
## The Default Approach
The code you might start with looks like this:
```javascript
const { signal } = this.abortController
window.addEventListener("resize", this.handlers.resize, { signal })
this.elements.container.addEventListener("scroll", this.handlers.scroll, { signal })
this._scrollToInitialPosition()
```
It handles the obvious cases. Drag the browser window larger, the handler fires and the view stays pinned. Rotate a tablet, same thing. Open DevTools, covered. This is what most people test, and it passes.
But the viewport and the element you're trying to pin are not the same thing. The `resize` event fires for the former, not the latter. Your scroller is blind to almost every reason a layout actually changes.
## What `window.resize` Doesn't See
- A user with low vision bumping browser zoom to 200%.
- Firefox's "Zoom Text Only" mode, where layout reflows without the
window reporting any new size.
- A textarea auto-grows as the user types a long message. Less room
for content above, same window dimensions.
- A side panel or sidebar toggles open. The container got narrower;
the window didn't move.
- Images, attachments, or late-loading content pushing earlier content
down after initial layout.
- A soft keyboard appearing on mobile. Some browsers fire `resize`,
many don't.
Some of these are polish. Several are accessibility failures. The irony is that these are the events most likely to go unnoticed by a developer working at 100% zoom on a laptop. The users most likely to notice a pin drifting out of sync are the ones who rely on larger text, higher zoom, and wider layouts.
## The Right Primitive
The fix is `ResizeObserver`, bound to the element you actually want to
keep pinned:
```javascript
const { signal } = this.abortController
this.resizeObserver = new ResizeObserver(() => {
this.handlers.resize()
})
this.resizeObserver.observe(this.elements.container)
this.elements.container.addEventListener("scroll", this.handlers.scroll, { signal })
```
`ResizeObserver` doesn't care *why* the element resized. Browser zoom, text-only zoom, a flex sibling taking more space, a new font loading, a panel opening: if the observed element's box changes, the callback runs.
The shift in mental model is subtle but important. Stop asking "did the viewport change?" and start asking "did the thing I'm trying to keep pinned change shape?" The second question is almost always the one you want.
## How the Observer Actually Works
Switching to `ResizeObserver` means understanding a few details that differ from `resize` events, especially if you're leaving it running on a critical UI element.
**The callback runs between layout and paint.** The event loop has a dedicated phase for resize observer notifications, after layout has settled but before anything gets painted. You can read layout geometry inside the callback without forcing a synchronous reflow, because the layout is already current. Writes that only affect paint, like` scrollTop`, happen in the same frame.
**It receives entries, not just a signal.** Each call gets an array of `ResizeObserverEntry` objects, one per observed element that changed. The entry carries the new dimensions, so you rarely need to query the DOM again:
```javascript
this.resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const { blockSize } = entry.contentBoxSize[0]
this.handlers.resize(blockSize)
}
})
```
I prefer `contentBoxSize` and `borderBoxSize` over the older `contentRect`. The boxSize APIs are writing-mode aware (`blockSize` and `inlineSize` flip for vertical or RTL layouts, so your pin math keeps working in Japanese or Arabic) and they expose the border box directly. If your scroll math depends on padded or bordered geometry instead of content box, pass `{ box: "border-box" }` as the second argument to `observe()`.
`contentRect` is still useful as a fallback for older browsers (Safari before 15.4). Its `width` and `height` are always content-box, so if you need border-box you have no choice but the newer API. One quirk: `contentRect.top` and `contentRect.left` are always `0`. The rect describes the content box relative to *itself*, not to the viewport. For on-screen position, use `getBoundingClientRect()`.
```javascript
// Portable fallback. width/height are always content-box.
new ResizeObserver((entries) => {
for (const entry of entries) {
const { width, height } = entry.contentRect
this.handlers.resize(height)
}
})
```
**It fires once immediately after `observe()`.** Unlike `window.resize`, which only fires on changes, `ResizeObserver` delivers an initial notification as soon as observation begins. That's your "starting layout" signal for free, and much of the initial-measurement plumbing you might otherwise hand-roll collapses into the same callback.
**It batches to one fire per frame.** The browser coalesces notifications per animation frame, so you don't need to debounce or wrap the callback in `requestAnimationFrame`. A flurry of resizes during a CSS transition appears as a single batched call per frame.
**It will complain if you cause a loop.** If your callback changes the observed element's size, or anything upstream that affects it, the browser skips remaining notifications and logs `ResizeObserver loop completed with undelivered notifications`. The canonical way to trip it is reading the entry's size and writing it straight back:
```javascript
// Don't do this.
new ResizeObserver((entries) => {
const entry = entries[0]
entry.target.style.height = `${entry.contentRect.height + 10}px`
}).observe(container)
```
First notification: height is `H`. Callback sets it to `H + 10`. Browser relays out, fires callback with `H + 10`. Callback sets `H + 20`. The browser gives up and logs the error.
Scroll pinning dodges this because `scrollTop` is paint-only; it doesn't affect layout:
```javascript
// Safe: scrollTop does not resize the element.
new ResizeObserver(() => {
if (isPinned) {
container.scrollTop = container.scrollHeight
}
}).observe(container)
```
Problems start when you do something more ambitious in the callback: toggling a "jump to latest" badge's visibility, swapping classes on a flex sibling, and resizing the composer. Any of those can round-trip into the observed box. If you need that kind of work, defer layout mutations behind `requestAnimationFrame` so they land in the next frame, or observe a different element (often the parent) whose size stays stable.
## Don't forget to Clean Up
`ResizeObserver` doesn't accept `AbortSignal`, so you can't hand it to the `AbortController` that cleans up your scroll listener. It needs explicit teardown. Observing one element? Use `disconnect()`. Observing several and want to stop watching one? Use `unobserve(target)`.
In a LiveView hook:
```javascript
destroyed() {
this.resizeObserver?.disconnect()
this.abortController?.abort()
},
```
Skip this, and you leak observers across navigations. In a long session, that adds up to real memory and callbacks firing on detached nodes.
## The Accessibility Angle
The deeper reason to reach for `ResizeObserver` isn't just that it catches more cases. It's that `window.resize` encodes the assumption that layout changes only when the window does, which was already wrong in 2016 and is completely false today. Users reshape their own layouts all the time: zoom, OS font preferences, reader mode, extensions, translation widgets, dynamic content, virtual keyboards.
An accessible UI responds to *what the user actually changed*, not just to the coarse event the browser fires for a window drag. If any feature you build has "stay pinned," "recompute on resize," or "reflow when the layout changes," the default tool should be `ResizeObserver` on the element in question. `window.resize` is a fallback for the rare cases where the window itself genuinely matters.
**Further reading:**
- [ResizeObserver on MDN](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver?ref=til.codes)
- [ResizeObserverEntry on MDN](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry?ref=til.codes) (covers `contentBoxSize`, `borderBoxSize`, `devicePixelContentBoxSize`)
- [Resize Observer W3C specification](https://www.w3.org/TR/resize-observer/?ref=til.codes) (authoritative on loop-error behavior)
- [WCAG 1.4.4: Resize Text](https://www.w3.org/WAI/WCAG22/Understanding/resize-text.html?ref=til.codes)
- [Firefox: Font size and zoom, including Zoom Text Only](https://support.mozilla.org/en-US/kb/font-size-and-zoom-increase-size-of-web-pages?ref=til.codes)
- [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver?ref=til.codes) and [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver?ref=til.codes) (sibling APIs in the Observer family)
### Picking Where jj absorb Lands: Adding --into to jjui
URL: https://til.codes/picking-where-jj-absorb-lands-adding-into-to-jjui/
Last updated: 2026-04-18T23:14:13.000Z
I [wrote about jj absorb recently](https://til.codes/the-magic-of-jj-absorb-rewriting-history-without-the-pain), and how it takes your working copy changes and quietly redistributes them into the right ancestors. It's the command I miss most when I'm forced back to git. But there's a wall I kept hitting, and last week I finally did something about it.
## The Problem with "Every Mutable Ancestor"
`jj absorb` defaults to `mutable()` for its destination set. Every mutable revision in your repo becomes a candidate for receiving your changes. Most of the time, this is what you want, since the algorithm only absorbs into ancestors of the source, so the list narrows itself naturally.
But "every mutable ancestor" gets unwieldy fast. I work in stacks. A typical morning looks like this:
```
@ follow-up fixes touching backend and UI
o Add UI module
o Add backend handler
o ... five other commits I'm still iterating on
```
Sometimes the working copy has a fix that belongs in `Add UI module` , but absolutely shouldn't touch `Add backend handler`. Maybe that backend commit is queued for a separate PR, and I'm being careful not to mix scopes. Or maybe one of the older commits is technically mutable, but I want to keep it frozen until I get review feedback.
The CLI handles this with `--into`:
```
jj absorb --from @ --into pmmspwst
```
Pass it once or many times, and the destination set shrinks to exactly those revisions. But I use [jjui](https://github.com/idursun/jjui?ref=til.codes) for almost all my interactive `jj` work. Pressing `shift+a` ran a bare `jj absorb`, with no way to constrain. Every time I needed `--into`, I dropped to a terminal, navigated, typed out change IDs, and hoped I picked them right.
## Building the Picker
I [opened an issue](https://github.com/idursun/jjui/issues/634?ref=til.codes). The maintainer came back with a clean design: convert absorb into an "operation" like `set_parents` or `abandon`. Mark the source revision with `<< absorb >>`. Mark each candidate with `<< into >>`. Bind `space` to toggle. Bind `enter` to apply.
The crucial detail: if you make no selections, it should still run plain `jj absorb`. Preserve the existing `shift+a` then `enter` flow exactly. Just one extra keypress if you need it.
Here's what shipped:

Three states visible. The source (working copy, `sptvnwlk`) shows `<< absorb >>` in cyan. Default candidates (`pmmspwst`, `lypnkxpn`) show `<< into >>` in red. Move the cursor, hit `space` on a candidate, and the marker dims to `<< default >>`, which excludes it from the destination set but keeps it visible. Hit `enter` and absorb runs with `--into` for whatever remains.
The first version I wrote had a subtle bug: toggle every candidate off and press `enter`, and it would silently fall back to jj's default behavior. That's the opposite of what the user is asking for. If you explicitly deselected everything, you probably want to cancel, not run the unconstrained version.
## Why Ancestors-Only for the Candidate Set
The maintainer suggested `mutable()` as the default candidate set, which is what jj's CLI does. I went with `mutable() & ::source` instead, narrowing to ancestors of the source.
The absorb algorithm explains why. `jj absorb` only ever distributes hunks into ancestors of the source. Non-ancestors can't receive content because the file annotation walk never visits them. jj's own [docstring is explicit](https://github.com/jj-vcs/jj/blob/main/cli/src/commands/absorb.rs?ref=til.codes): *"Only ancestors of the source revision will be considered."*
If the picker showed non-ancestors as candidates, users could toggle them on, but absorb would silently ignore them. That's misleading UX. Showing only ancestors keeps the picker honest about what's actually possible.
## The Trap of Tracked State
My first iteration tracked a `userModified bool`. Toggle anything, set the flag. At apply time, if the flag was true, pass `--into`. Otherwise, run plain absorb.
This sounds reasonable until you toggle a candidate off and then on again. You're back to the original set, but the flag is still true, so absorb runs with `--into a --into b`, which is functionally identical to no `--into`, just verbose and ugly in the command history.
Worse: if defaults are empty (small repo, no mutable ancestors), pressing `space` on something then `space` again to undo leaves you with empty targets AND a true flag. The empty-targets close logic kicks in and the operation exits without running anything. The user did nothing, but jjui treated it as "I want to cancel."
The fix was to drop the bool and compare sets at apply time. If `targets == defaults`, no `--into`. If `targets` is empty AND `defaults` wasn't, close. Otherwise, pass `--into` for each kept target. The state model is now derived, not tracked.
This is the kind of bug unit tests don't catch easily, because the assertion you'd write has the same shape as the bug. I wrote a test for the toggle-on-then-off path asserting "userModified stays true" and it passed because that's exactly what the buggy code did. The test confirmed the bug, not the requirement.
## When the Lua API Collides
`jjui` exposes actions to Lua so users can script workflows. The action that opens the absorb operation was registered as `revisions.absorb`. The new picker scope was also `revisions.absorb`.
In jjui's Lua API, scopes are tables and actions are functions. Registering both means the scope table overwrites the action function. Anyone with a Lua script calling `jjui.revisions.absorb()` would suddenly find that function gone.
The fix was renaming the entry action from `revisions.absorb` to `revisions.open_absorb`. This matches the convention every other operation uses: `open_abandon`, `open_squash`, `open_set_parents`. Honestly, it should have been named that way from the start, since the action opens an operation instead of running absorb directly. The Lua collision just made the rename non-optional.
## Closing
This is a small feature. But when you live in stacks, being able to constrain absorb to a single ancestor turns "drop to terminal, type carefully" into "space twice, enter." The friction difference compounds.
The PR is [open against idursun/jjui](https://github.com/idursun/jjui?ref=til.codes). If you use `jjui` and have thoughts on the picker UX, that's the place.
**Resources:**
- [jjui](https://github.com/idursun/jjui?ref=til.codes)
- [GitHub issue #634](https://github.com/idursun/jjui/issues/634?ref=til.codes)
- [jj absorb docs](https://docs.jj-vcs.dev/cli/?ref=til.codes#jj-absorb?ref=til.codes)
### Bridging git worktrees and jj workspaces for agentic workflows
URL: https://til.codes/bridging-git-worktrees-and-jj-workspaces-for-agentic-workflows/
Last updated: 2026-04-07T17:14:09.000Z
I run agentic workflows in jj workspaces: parallel feature development, code reviews, spikes, experiments, each isolated in its own working copy. The workflow is ideal for isolation. You can work on a feature, create stacked PRs, switch to another workspace for spikes or code reviews, or set up a scratch environment for debugging flaky tests. But when I opened a workspace, the editors showed no diff gutters, no change indicators, no blame annotations. As far as Zed, Neovim, and the others were concerned, I was editing unversioned directories.
This sent me down a rabbit hole through libgit2's repository discovery, Git's internal storage model, and jj's colocated backend, and the fix turned out to be a single line.
## How Git Repository Discovery Actually Works
When an editor opens a directory, it needs to find the Git repository. How it does this varies. Zed links against [libgit2](https://libgit2.org/?ref=til.codes), a C implementation of Git's object model, and performs repository discovery in-process. VS Code shells out to a bundled `git` binary, which means PATH-based shims can still affect it. Neovim plugins vary; some use libgit2 via FFI, others call `git` directly. But the discovery algorithm is the same regardless of who runs it. It starts with [git\_repository\_discover()](https://libgit2.org/libgit2/?ref=til.codes#HEAD/group/repository/git%5Frepository%5Fdiscover) (or the equivalent CLI invocation), walking up from the working directory:
```
~/project/feature-auth/lib/accounts/
~/project/feature-auth/lib/
~/project/feature-auth/
~/project/
~/
...
```
If `til_codes/.git` existed somewhere along this path, discovery would succeed. But the workspace is a sibling directory, `feature-auth/` sits next to `til_codes/`, not inside it. There's no `.git` anywhere in the walk.
At each level, it looks for a `.git` entry. Here's where it gets interesting: `.git` can be one of two things.
Case 1: A directory. The standard layout. Contains `objects/`, `refs/`, `HEAD`, `index`, and the rest of the repository internals. libgit2 opens it directly.
Case 2: A file. A plain text file containing a single line:
```
gitdir: /path/to/actual/git/directory
```
libgit2 reads the file, resolves the path (relative paths are resolved against the file's parent directory), and opens the referenced directory as the repository. This isn't an extension or a hack; it's part of the [Git repository layout specification](https://git-scm.com/docs/gitrepository-layout?ref=til.codes). Git originally added it for submodule support and later adopted the same mechanism for `git worktree`.
When you run `git worktree add ../feature-branch`, Git creates exactly this: a `.git` file in the new worktree that points back to `.git/worktrees/feature-branch/` inside the main repository. Every tool built on libgit2 follows these pointers transparently.
A jj workspace has neither. It has a `.jj` directory, which libgit2 doesn't recognize. Discovery fails at the workspace root, bubbles up to the filesystem root, finds nothing, and the IDE concludes there's no repository.
## Inside jj's Storage Model
To understand why a fix is even possible, you need to know how jj stores data. When you initialize a repository with `jj git init --colocate` and in current jj releases, colocation is the default, you get two version control systems sharing one directory:
```
til_codes/
.git/ # Standard Git repository
HEAD
objects/ # Git object store (commits, trees, blobs)
refs/ # Branch refs, tags
index # Working tree cache
info/
exclude # Per-repo ignore patterns
.jj/ # Jujutsu metadata
repo/
store/
git_target # Points to ../.git (the colocated backend)
op_store/ # Operation log (jj's undo history)
op_heads/ # Current operation heads
working_copy/ # Snapshot state for this working copy
```
The critical detail is in `.jj/repo/store/git_target`. In a colocated repository, this file contains the path to the `.git` directory. jj doesn't maintain its own object store; it writes directly to Git's. Every `jj describe`, `jj new`, or `jj squash` creates real Git commit objects in `.git/objects/`. The commit graph, the tree objects, the file blobs, they're all standard Git objects that any Git tool can read.
When you create a workspace with `jj workspace add ../feature-auth`, the new directory gets a minimal `.jj`:
```
feature-auth/
.jj/
repo # Text file: path back to the main repo's .jj/repo/
working_copy/ # This workspace's snapshot state
lib/
test/
mix.exs
...
```
The `repo` file is a pointer, not a copy. All workspaces in a jj repository share the same commit graph, operation log, and, because jj is colocated, the same Git object store. The Git objects representing your feature branch's commits are sitting in the main repo's `.git/objects/`. The workspace just has no way to tell libgit2 where to find them.
## Why the Shim Approach Can't Solve This
Before arriving at the fix, I tried the obvious approach: intercepting `git` commands. [jj-worktree](https://github.com/kawaz/jj-worktree?ref=til.codes) is a Rust binary that gets symlinked as `git` early in `PATH`. When invoked inside a jj repository, it translates commands:
```
git status -> jj diff --summary (output converted to porcelain v1)
git rev-parse HEAD -> jj log -r @ -T commit_id
git worktree add -> jj workspace add
git branch -d -> jj bookmark delete
```
The translation includes output format conversion. `jj diff --summary` produces `M file.txt`, but tools that parse `git status --porcelain` expect `M file.txt` (note the leading space indicating unstaged changes). jj-worktree handles this:
```rust
// From jj-worktree's shim.rs - cmd_status()
for line in diff.lines() {
let trimmed = line.trim();
if let Some((status, path)) = trimmed.split_once(' ') {
match status {
"M" => println!(" M {path}"),
"A" => println!("?? {path}"),
"D" => println!(" D {path}"),
"R" => println!(" M {path}"),
_ => println!(" M {path}"),
}
}
}
```
This works for CLI tools. Claude Code's git integration, `gh`pre-commit hooks, anything that spawns `git` as a subprocess sees the shim. VS Code would too, since its built-in Git extension shells out to a `git` binary. But Zed doesn't spawn `git`. It calls `git_repository_discover()` from libgit2, which is compiled into the editor binary. There's no PATH lookup, no process spawning, no opportunity for interception. Other tools that use libgit2 directly, including some Neovim plugins and GUI clients, have the same limitation.
I verified this by adding debug logging to the shim and opening the workspace in Zed. The shim was never invoked. Zed's git integration operates entirely within its own process space.
## The Fix: One Line
Since jj's colocated backend writes to Git's object store, and libgit2 follows `gitdir:` pointers, the fix is to connect the two:
```bash
echo "gitdir: ~/project/til_codes/.git" > ~/project/feature-auth/.git
```
That's it. One file, one line. libgit2's discovery walk hits the workspace root, finds a `.git` file, reads the `gitdir:` pointer, opens the main repository's `.git` directory, and now has full access to the object store. Zed immediately shows diff gutters. Codex shows file changes. `git diff`, `git status`, and `git blame` become useful from the workspace directory. `git log` still follows the shared Git HEAD, it won't show your workspace's jj history unless you explicitly point it at exported refs or commit hashes.
But to understand the limitations of this approach, you need to understand how Git actually computes diffs.
## Git's Three-Layer Diffing Model
Git doesn't compute diffs by comparing files against a single reference point. It maintains three distinct representations of your project, and different commands compare different pairs:
```
+------------------+
| HEAD commit | (the tree object pointed to by HEAD)
+------------------+
|
git diff --cached
|
+------------------+
| Index | (.git/index - binary file, aka "staging area")
+------------------+
|
git diff
|
+------------------+
| Working tree | (actual files on disk)
+------------------+
```
- `git diff` compares the index against the working tree.
- `git diff --cached` compares HEAD against the index.
- `git status` does both comparisons and reports the union.
The index is the key piece. It's a binary file at `.git/index` that caches metadata about every tracked file: path, file size, modification time, inode number, and the SHA-1 of the blob object representing the file's contents. When you run `git status`, Git stats every file in the working tree, compares the stat data against the index entries, and only reads file contents (to compute SHA-1) when the stat data doesn't match. This is what makes `git status` fast even in large repositories, it's a stat cache, not a content scan.
Here's why this matters for our workspace setup. The `gitdir:` pointer shares the main repository's `.git` directory, which means it shares the main repository's index. That index was built by the main repository's working copy. It contains stat entries for files as they exist in the main repo, not in the workspace.
This creates three distinct behaviors depending on the type of change:
New files (files that exist in the workspace but not in the index) show as "untracked." This is correct, the IDE displays them with the "new file" indicator, which is exactly what you want.
Modified files (files that exist in both the workspace and the index) are compared against the index's cached blob SHA-1\. If the shared index still reflects the tree state your workspace branched from, the diff is accurate, the cached content matches the file's pre-modification state. But if any Git operation or tool updates that shared index to reflect a different working copy (e.g., running `git checkout` or `git reset` in the main repo), diffs in the workspace will be computed against the wrong base.
Deleted files (files in the index but not in the workspace) would show as deleted if the workspace doesn't contain them. In practice, jj workspaces start as copies of the full tree, so this only matters if you've explicitly removed files.
For my workflow, feature branches off trunk, usually a handful of files changed, shared index untouched, and the diffs have been accurate. The index still reflects the tree state my workspace branched from, so the comparison base is correct.
## Contrast: How `git worktree` Does It Properly
For context, here's what `git worktree add` creates that our approach doesn't. When you run `git worktree add ../feature-branch`, Git creates:
```
.git/worktrees/feature-branch/
HEAD # Separate HEAD for this worktree
index # Separate index for this worktree
commondir # Points back to the main .git
gitdir # Path to the worktree's .git file
```
Each worktree gets its own HEAD and its own index. The object store and refs are shared (via `commondir`), but the working tree state is independent. This is why `git worktree` doesn't have the index-sharing problem, each worktree tracks its own file state.
Our `gitdir:` hack skips this entirely. We point directly at the main `.git`, sharing everything, including the index and HEAD. It's a read-only window into the object store, not a proper worktree registration. This is fine for IDE diffing but means you should never run Git write operations (`git add`, `git commit`, `git checkout`) from the workspace, they would mutate the main repository's state.
## Hiding `.jj` From Git's View
With the `gitdir:` pointer in place, `git status` now sees the `.jj` directory as untracked. Git has three layers of ignore rules, evaluated in this order:
1. `.gitignore` tracked, committed, and shared with the team. Not appropriate for this; `.jj` is a local concern.
2. `core.excludesFile` (defaults to `~/.config/git/ignore`) global, applies to every repository. Too broad.
3. `.git/info/exclude` per-repository, never committed, never shared. This is the right layer.
The `info/exclude` file uses identical syntax to `.gitignore` but lives inside the `.git` directory:
```bash
echo '.jj' >> ~/project/til_codes/.git/info/exclude
```
After adding this, `.jj` disappears from `git status` and from Zed's file tree. The exclude file doesn't need to exist beforehand; Git creates the `info/` directory during `git init`, but the `exclude` file may not be present. The `>>` append handles both cases (creates the file if missing, appends if it exists).
## Automating the Setup
I manage jj workspaces with two shell functions: `jwa` (workspace add) and `jws` (workspace sync). `jwa` creates the workspace and calls `jws` to copy configuration files from the main repo. Adding the `gitdir:` setup to `jws` means every new workspace gets IDE support automatically:
```bash
jws() {
local target="$1"
local root=$(jj root 2>/dev/null)
if [[ -z "$root" ]]; then
echo "Not in a jj repository"
return 1
fi
# Sync AI tool configs into the workspace
local items=(".claude" "CLAUDE.md" "AGENTS.md" ".env" ".mcp.json")
local copied=0
for item in "${items[@]}"; do
if [[ -e "$root/$item" ]]; then
cp -r "$root/$item" "$target/"
((copied++))
fi
done
# Set up gitdir pointer for IDE diff support
if [[ -e "$root/.git" ]]; then
local git_dir
if [[ -d "$root/.git" ]]; then
git_dir="$root/.git"
elif [[ -f "$root/.git" ]]; then
git_dir=$(cat "$root/.git" | sed 's/^gitdir: //')
[[ "$git_dir" != /* ]] && git_dir="$root/$git_dir"
fi
if [[ -n "$git_dir" ]]; then
echo "gitdir: $git_dir" > "$target/.git"
mkdir -p "$git_dir/info"
if ! grep -qx '.jj' "$git_dir/info/exclude" 2>/dev/null; then
echo '.jj' >> "$git_dir/info/exclude"
fi
echo "Linked .git for IDE diff support"
fi
fi
echo "Synced $copied items to $target"
}
```
The `elif` branch handles the case where the main repo's `.git` is itself a `gitdir:` pointer (e.g., the main repo was created inside another git worktree). It reads the pointer, resolves relative paths, and chains through to the actual `.git` directory.
The `jwa` function creates the workspace and calls `jws`:
```bash
jwa() {
local input="$1"
local root=$(jj root 2>/dev/null)
local workspace_path
if [[ "$input" = /* ]]; then
workspace_path="$input"
elif [[ "$input" == */* ]]; then
workspace_path="$PWD/$input"
else
workspace_path="$root/../$input"
fi
jj workspace add "$workspace_path" || return 1
workspace_path="$(cd "$workspace_path" && pwd)"
jws "$workspace_path"
cd "$workspace_path"
}
```
The full workflow becomes:
```bash
$ cd ~/project/til_codes
$ jwa feature-auth
Created workspace in "../feature-auth"
Linked .git for IDE diff support
Synced 3 items to ~/project/feature-auth
$ cd ../feature-auth
$ zed . # Diff gutters work immediately
```
## The Rule: Read-Only Git, All Writes Through jj
This bears repeating because violating it will corrupt your main repo's state. The `gitdir:` pointer gives IDEs read access to the object store. It does not register the workspace as a proper git worktree. Git commands that read from the working tree and object store (diff, status, blame) are safe and useful. `git log` works but follows the shared HEAD, not your workspace's jj history. Git commands that write (add, commit, checkout, reset, stash) will modify the main repo's index and HEAD.
In the workspace, all version control goes through jj:
```bash
jj describe -m "add user authentication" # set commit message
jj new # start next change
jj bookmark set feature-auth -r @- # create bookmark for push
jj git push -b feature-auth # push for PR
```
Zed shows the diffs. jj manages the history. They operate on the same underlying objects without needing to agree on a protocol.
## When This Breaks
There are specific scenarios where the diff accuracy degrades:
Shared index gets mutated. If a Git operation in the main repo updates the shared index, `git checkout`, `git reset`, or even an IDE refreshing the main repo's working tree, diffs in the workspace will be computed against the wrong base. Note that jj operations alone don't touch the Git index; this only happens when something invokes Git directly against the main repo. The fix is simple: avoid Git write operations in the main repo while workspaces are active, or accept occasional noise in the diff gutter.
Multiple workspaces sharing one `.git`. All workspaces point to the same index. If you open two workspaces in Zed simultaneously, both see diffs computed against the same index state. For new files (the most common case in feature branches), this is fine. For modified files, the workspace whose base commit matches the index will show correct diffs; the other may not.
Binary files and large objects. Diff computation requires reading blob objects from the object store. If your workspace modifies large binaries, the IDE may be slower to compute diffs since it's resolving objects from the main repo's packfiles over the `gitdir:` pointer.
## Complementary Tools
The `gitdir:` pointer and jj-worktree solve different problems and can coexist:
| Concern | gitdir: pointer | jj-worktree |
| --------------------------- | ----------------------------- | -------------------------- |
| IDE diff gutters | Yes | No (IDEs bypass PATH) |
| CLI git status/diff/log | Yes (read-only) | Yes (full translation) |
| git commit/add/checkout | Dangerous (mutates main repo) | Translated to jj commands |
| Dependencies | None | Rust binary in PATH |
| Workspace metadata tracking | None | Bookmark and path tracking |
For IDE-only support, the `gitdir:` pointer is sufficient. For CLI tools that need transparent git compatibility, install jj-worktree alongside it. They don't conflict, jj-worktree's shim detects whether it's in a jj repo and passes through to real git otherwise, and the `gitdir:` file is invisible to jj.
## The Long-Term Fix
The real solution is native jj support in editors. Zed has an open issue for it. VS Code has community extensions in early development. Until those ship, the `gitdir:` pointer gets you most of the way there, accurate diffs for new and modified files (when the shared index still matches the expected base), blame annotations, and object resolution, with a single line of text and zero dependencies.
The objects were always there. libgit2 just needed a signpost.
---
Further reading:
- [Git repository layout specification](https://git-scm.com/docs/gitrepository-layout?ref=til.codes) \-- the `gitdir:` format definition
- [libgit2 repository discovery](https://libgit2.org/libgit2/?ref=til.codes#HEAD/group/repository/git%5Frepository%5Fdiscover) \-- the C API that IDEs call
- [jj workspace documentation](https://jj-vcs.github.io/jj/latest/working-copy/?ref=til.codes) \-- how workspaces share the repo store
- [jj-worktree](https://github.com/kawaz/jj-worktree?ref=til.codes) \-- Rust git shim for CLI compatibility
- [Git index format](https://git-scm.com/docs/index-format?ref=til.codes) – the binary index specification
### LiveView Already Knows When Your Server Crashed
URL: https://til.codes/liveview-already-knows-when-your-server-crashed/
Last updated: 2026-04-03T03:18:56.000Z
This week, I reviewed a pull request that added error flash handling to a Phoenix app. The JavaScript implementation seemed straightforward: listening for `phx:page-loading-start`, checking the socket connection, showing a popover for server crashes, and hiding it during navigation. It included two helper functions, an event listener, and a manual `isConnected()` check to differentiate between server errors and network issues. Then I opened the LiveView documentation and realized we were reinventing functionality that already exists in the framework.
### What We Initially Built
Here's the code we thought was complete:
```javascript
window.addEventListener("phx:page-loading-start", (info) => {
topbar.show(300)
if (info.detail.kind === "error" && liveSocket.socket.isConnected()) {
showErrorFlash()
} else {
clearErrorFlash()
}
})
function showErrorFlash() {
const el = document.getElementById("client-error-flash")
if (el && !el.matches(":popover-open")) {
el.showPopover()
}
}
function clearErrorFlash() {
const el = document.getElementById("client-error-flash")
if (el?.matches(":popover-open")) {
el.hidePopover()
}
}
```
The key logic here is the `isConnected()` check. The `phx:page-loading-start` event triggers with `kind: "error"` for both server crashes and network disconnects. To show the error flash only for server crashes, we checked if the socket was connected at the time of the error, an indicator that the server process failed rather than the network. It worked, and initially, it made sense. But as I dug deeper into the docs, I realized LiveView already accounts for this distinction.
### LiveView's Built-in Classes
LiveView uses [CSS classes on the root container](https://hexdocs.pm/phoenix%5Flive%5Fview/syncing-changes.html?ref=til.codes#navigation-classes) to represent connection states. The `data-phx-main` element gets the following classes:
- `phx-connected` when the WebSocket is active.
- `phx-disconnected` when the network connection drops.
- `phx-error` when the server process crashes.
That last class, `phx-error`, was exactly what we needed. LiveView distinguishes between server crashes and network disconnects, applying `phx-error` only to server issues. The manual `isConnected()` check and event logic we wrote were redundant.
### Observing Classes Instead of Events
If we were just toggling a `div` CSS alone could handle this: `.phx-error #client-error-flash { display: block }`. But since we're using the [Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover%5FAPI?ref=til.codes) with `popover="manual"`, CSS can't do it alone. The popover needs to be in the top layer to properly display above `
"
# text = "Someone hacked Terms & Conditions with & <script>alert('hi')<script>
"
# text = strip_tags(text)
# => "Someone hacked Terms & Conditions with & <script>alert('hi')<script>"
# text = to_text(text)
# => "Someone hacked Terms & Conditions with &
```
That's it and now you have syntax highlighting enabled for your blog.
### Tweaking the layout: list instead of cards and bigger fonts.
I did not quite like the new layout of the Casper theme. Cards instead of a list. Also, the fonts were smaller. But the good thing is that you can always tweak the theme and make it the way you like.
So I tweaked a few css classes to make the layout the way I liked. The following are the changes that I made:
```
// bigger cover image
.site-header {
height: 50vh
}
// a little bit wider lists
.inner {
max-width: 1200px;
}
// bigger fonts
.post-template .kg-card-markdown>p {
font-size: 1.25em;
line-height: 1.5em
}
.post-full-content pre code {
font-size: 1.55em;
line-height: 1.5em
}
.post-card-excerpt p {
font-size: 1.55em;
line-height: 1.5em
}
.post-card-title {
font-size: 2em
}
// tweaks for the code/syntax highlights
pre {
word-wrap: normal;
-moz-hyphens: none;
-ms-hyphens: none;
-webkit-hyphens: none;
hyphens: none;
font-size: 1em;
line-height: 1.3em
}
pre code,
pre tt {
white-space: pre
}
// don't use the margin for the lists
.post-card {
min-height: 0
}
// Change cards to table
.read-next-feed .post-card,
.post-feed {
display: flex;
}
// keep the card layout for similar posts
.post-card,
.post-feed {
display: table
}
// smaller subscribers form
.subscribe-form {
padding: 3.0vw;
}
```
So that's it, looks much better now.
Let me know how you feel the new ghost and Casper theme and any nice tweaks that you have made.
Sharing is caring.! 🍻
### How to disable Adobe Flash Player update notification
URL: https://til.codes/how-to-disable-adobe-flash-player-update-notification-2/
Last updated: 2017-11-18T16:16:32.000Z
Well, lets not talk about the history/legacy of Flash/HTML5 etc here. Flash has its place but its really annoying when the Adobe Flash Player updater pops in when you are working on something important and distracts you.
And even worse, you are presented with only option to **Remind Me Later** or **Download**. And if you select Remind Later option, the annoying popup returns after 60mins again.
###### So how do I get rid of this popup?
Two options:
Either let adobe install the flash player updates automatically or disable the updates forever.
###### Disabling/Auto Install updates
To customise your settings for disabling updates or to enable auto installs on a Mac
Goto: **System Preferences -> Flash Player -> Updates**
You now have option to either:
1. Allow Adobe to install updates(auto install updates)
2. Notify me to install updates(the annoying per 60min reminder when update is available)
3. Never check for updates(I don't care with it)
Select the one which is convenient for you.!
Hope this helps someone.!
Thanks for reading.
### Disable pry and exit debugger without killing the main program in Ruby
URL: https://til.codes/disable-pry-and-exit-debugger-without-killing-the-main-program-in-ruby/
Last updated: 2017-11-19T16:02:31.000Z
You ever ran into a situation where you had a huge loop running and you put a `binding.pry` within that loop for debugging and wondered how the hell you would exit the debugger?
The answer is simple
`disable-pry` is your saviour.!
[via GIPHY](https://giphy.com/gifs/loki-saviour-l2QEjYgve6wmqLKog?ref=til.codes)
This has got its downside though, this will disable any further invocations of the `pry` again.
Under the hood its disabling the whole pry and setting `ENV['DISABLE_PRY'] = true`
To re-enable pry for any further debugging you will have to clear the ENV var by `ENV['DISABLE_PRY'] = nil`
I have defined a helper method `enable_pry` with the following inside my `.pryrc` for my convenience.
```
def enable_pry
ENV['DISABLE_PRY'] = nil
end
```
Credits where its due: [https://stackoverflow.com/questions/8015531/how-do-i-step-out-of-a-loop-with-ruby-pry](https://stackoverflow.com/questions/8015531/how-do-i-step-out-of-a-loop-with-ruby-pry?ref=til.codes)
Happy coding.!!
### Don't forget to update the sequence in PostgreSQL after a COPY command
URL: https://til.codes/dont-forget-to-update-the-sequence-in-postgresql-after-a-copy-command/
Last updated: 2017-11-19T19:53:40.000Z
You might have noticed that after bulk inserting records using the `COPY` statement in PostgreSQL the sequence IDs are not getting updated for any further inserts later on, and it would throw duplicate sequence ID errors.
So you would be wondering what makes this `COPY` statement different that it does not update the sequences.
Well the copy statement is not entirely the culprit here.
###### Internal Details/Reason
When you perform a normal `INSERT`, you often don't specify the value for the SEQUENCE-backed primary key explicitly. But if for some reason you did, you would run in to the same problems as you have with `COPY`. So as you see, `COPY` statement is not the real culprit here.
The sequence only increments when a value is evaluated by the database itself during the INSERT statements( it internally uses the nextval function underneath). If you provide values for your ID, the sequence is not used, thus it doesn't get incremented.
###### Fix
So now you know why it does not increment the sequence, but how do you fix the sequence after a bulk insert?
The answer is simple: you need to call the `nextval` function to reset the sequence generator.
```
select setval('seqname',select max(id) from tablename));
```
so lets say you have a `users` table with `users_id_seq` as the sequence name then:
```
select setval('users_id_seq',select max(id) from users));
```
###### Further reading:
PostgreSQL provides a lot more configuration options for your sequence generator. You can read them over here [Postgres docs](https://www.postgresql.org/docs/9.1/static/sql-createsequence.html?ref=til.codes)
Thanks for reading, and hope it helps someone.!
### Copy data from one postgres instance to another. remote copy options explored: Copy, CSV and STDIN
URL: https://til.codes/using-postgres-copy-command-to-copy-data-from-one-server-to-another/
Last updated: 2017-11-19T21:18:59.000Z
Its very common use case to copy data from one database instance to another be it from local to staging, staging to production etc.
For copying data from one PostgreSQL instance to another, there are a couple of techniques.
You can take a data dump as an SQL file or as a CSV from your PostgreSQL instance and do a restore.
But what happens when you are dealing with Gigs of data?
It might not be a good idea to do a dump of 100s of Gigs to your local system and then copy to the remote host and restore.
Well, PostgreSQL also has a `\copy` statement which can be quite handy in this case. What if I say that you can even do a remote copy of data from one database to another over ssh. Interesting isn't it.
Let's explore various options for copying data to from local/remote servers.
I am not going to cover the `pg_dump` and `pg_restore` methods here as there are a lot of resources out there explaining those in detail.
### Understanding `COPY` and `\copy` statements
`COPY` command is to input and output data between database and file only in the database server. If we connect to the database remotely (E.g. from another computer), we cannot use `COPY` command from the remote computer. In other words, input file or output file has to be in the database server. This is because SQL statements that are entered at the `psql` prompt are sent to the server before they are executed. This means that any file paths included in SQL statements are interpreted by the server. Since the server doesn't know what directory a user is in when they execute a statement, this means that all file paths have to be absolute.
On the other hand, `\COPY`, the meta command provided by PostgreSQL, is to input or output file in the client computer. If we connect to database server remotely by utilizing `psql` command, we can input or use a file on the client computer. This meta command initiates copies from the client (which is the `psql` process in this case), and this allows it to interpret paths that are relative to the user's current directory.
### Copy data from a CSV file to local database.
The simplest solution to copy data from one database to another is to save to a local file and then restore it
```
\COPY users TO 'users.csv' CSV HEADER
```
The above command selects the data that you want and then writes it to a CSV file using the `\copy` command.
Now its time to restore the CSV file to the second database.
Loading the data is also pretty straightforward with the same `\copy` command.
```
\COPY users FROM 'users.csv' WITH CSV HEADER;
```
### Copy data using STDIN to a local database.
While it's useful to save the data to a local CSV file, it's not always needed. You can even copy the data from one database or table using the STDOUT-> STDIN technique.
```
psql
-h localhost \
-d your_primary_db \
-U postgres -c \
"\copy users (id, email, first_name, last_name) from STDIN
with delimiter as ','" \ < /tmp/users.csv
```
Note that the above statement also leverages SQL statements inside the `\copy` statement thereby you can choose what data you need to copy.
### Copy data from a CSV file to remote database.
The following command copies data from a local CSV file to a remote PostgreSQL database
```
psql \
-h remotehost \
-d your_primary_db \
-U postgres \
-c "\copy users (id, email, first_name, last_name) from '/tmp/users.csv' with delimiter as ','"
```
### Copy data using STDIN to a remote database.
Now, lets use STDIN for reading the CSV file and copying data to a remote host.
```
psql
-h remotehost \
-d your_primary_db \
-U postgres -c \
"\copy users (id, email, first_name, last_name) from STDIN
with delimiter as ','" \ < /tmp/users.csv
```
### Copy data from one server to another server
```
psql \
-U user_name \
-h production_server \
-d database_name \
-c "\\copy users to stdout" | \
psql -U user_name \
-h staging_server \
-d database_name \
-c "\\copy users from stdin"
```
The above command STDOUTs the data from the production server and copies the same data over STDIN on the staging server.
### Other techniques
There are also a few other techniques that can be used to copy data from one server to another like setting up replication between databases or doing a full snapshot replication of the db.
Reference:
[https://www.postgresql.org/docs/current/static/sql-copy.html](https://www.postgresql.org/docs/current/static/sql-copy.html?ref=til.codes)
Hope that someone finds it useful. 🖖🏻
### Escape character sequence "E" in PostgreSQL explained
URL: https://til.codes/escape-character-sequence-e-in-postgresql-explained/
Last updated: 2017-11-19T19:35:37.000Z
You might have encountered situations like where you have to insert some data into your PostgreSQL table that has special characters.
eg: `this is a very large sentence \n and hence this is broken down into two sentence`
and when you try to do that without the escape sequence postgreSQL starts to behave wieirdly with you, and might start throwing errors like:
`nonstandard use of escape in a string literal`
Most often this is handle in the code where the programming language takes care of this for you or the ORM do the magic for you.
If you are interested in knowing a bit more about the escape character sequences in PostgreSQL, keep reading.
# Escape String Constants.
PostgreSQL also has the C-styled escape characters as it closely follows the SQL standard. In postgreSQL you can specify the escape character by prefixing the letter `E`
From the PostgreSQL [docs](https://www.postgresql.org/docs/10/static/sql-syntax-lexical.html?ref=til.codes)
> PostgreSQL also accepts "escape" string constants, which are an extension to the SQL standard. An escape string constant is specified by writing the letter E (upper or lower case) just before the opening single quote, e.g., E'foo'. (When continuing an escape string constant across lines, write E only before the first opening quote.) Within an escape string, a backslash character () begins a C-like backslash escape sequence, in which the combination of backslash and following character(s) represent a special byte value
So you can write the above statement using the escape sequence as:
`E'this is a very large sentence \n and hence this is broken down into two sentence'`
This is particularly useful when you are using the PostgreSQL `\copy` statement and trying to load the data from a CSV file.
### Passing multiple options/argument with default options in rake
URL: https://til.codes/passing-multiple-options-argument-with-default-options-in-rake/
Last updated: 2017-04-12T09:48:05.000Z
Rake task allows you to accept multiple arguments which can be used within the task, and also allows us to specify default options for these arguments.
###### Accept multiple arguments/options
Lets say we have a simple rake task to sync data from/across our servers to different enviroments.
We can accept the `server` and `host` as arguments here.
```
namespace :db do
desc "Restores the database dump to the given environment"
task :sync, [:server, :host] => [:environment, 'db:drop', 'db:create'] do |_t, args|
...
end
end
```
The above rake task can be called using:
```
bin/rake 'db:sync[staging, local]'
```
###### With default values
Sometimes it makes sense to have default values for the arguments. An eg use case would be if no value is specified for the host, we are expecting the DB to be synced to our local database. In such situations, we can use `args.with_defaults`
```
namespace :db do
desc "Restores the database dump to the given environment"
task :sync, [:server, :host] => [:environment, 'db:drop', 'db:create'] do |_t, args|
args.with_defaults(:server => 'staging', :host => 'local')
....
end
end
```
and the rake task can be executed using:
```
bin/rake 'db:sync[staging]'
```
###### Note:
**if you are using zsh**, you will need to wrap the task inside **'** **'**. this is because zsh doesn't play too nicely with the arguments/commands.
### How to fix the Index name too long error in rails migrations
URL: https://til.codes/how-to-fix-the-index-name-too-long-error-in-rails-migrations/
Last updated: 2017-03-16T13:06:39.000Z
Today, I was reviewing some legacy code, trying to isolate the bottlenecks and pinpoint the optimisation strategies for scaling and performance optimisations of a rails app.
As the usual procedure, I wanted to check the database indexes and see if something was missing here. And my guess was in the right direction. Some of the indexes were missing.
So the next obvious thing to do:
Create a migration for adding the missing indexes.
I thought it was gonna be a breeze, I generated the migration, filled the migration file with the correct table name and fields etc, but when I tried to run the migration, I stumbled upon an issue.
```
ArgumentError: Index name 'index_loan_application_status_message_template_groups_on_message_template_group_id' on table 'loan_application_status_message_template_groups' is too long; the limit is 63 characters
```
Problem: **The index name is too long**
So here is what my migration looked like:
```
class IndexForeignKeysInLoanApplicationStatusMessageTemplateGroups < ActiveRecord::Migration
def change
add_index :loan_application_status_message_template_groups, :message_template_group_id
end
end
```
After a bit of googling I learned that PostgreSQL has a limit of 63 char for naming, as can be found [here](https://www.postgresql.org/docs/current/static/sql-syntax-lexical.html?ref=til.codes#SQL-SYNTAX-IDENTIFIERS).
So I need to keep my index identified under 63 chars.
And our nice folks who build rails/active record have given us a nice way to accomplish this.
**[Solution](solution)**: You can specify the name of the index and keep it under the 63 chars mark by passing values to the `name` argument in your migration.
So I modified my migration to the following:
```
class IndexForeignKeysInLoanApplicationStatusMessageTemplateGroups < ActiveRecord::Migration
def change
add_index :loan_application_status_message_template_groups,
:message_template_group_id,
name: 'loan_application_status_message_template_group_index'
end
end
```
Hope that helps someone. :)
### Find out which part of your code is triggering ActiveRecord or SQL queries.
URL: https://til.codes/find-out-which-part-of-your-code-is-triggering-activerecord-or-sql-queries/
Last updated: 2017-03-16T13:21:08.000Z
Today, I got a new pet project to play with and my job was to identify the bottlenecks and performance improvements we can make in the application.
So I wanted to jump in and wanted to see what SQL queries were being triggered when someone requests data. Going through the entire code was not a feasible option for me.
So I was more like looking for a silver bullet, which would give me a list of queries that were triggered and the code snippets or areas which triggered them, so that I can see if it can be optimised any further.
What I had mind was to log all SQL queries and the caller or method which triggered them.
Looking a bit deep into the rails documentation, and some google and stack overflow links, I finally came with this helper script.
You can add this inside `config/intializers` directory and see the magic.
```
module LogQuerySource
def debug(*args, &block)
return unless super
backtrace = Rails.backtrace_cleaner.clean caller
relevant_caller_line = backtrace.detect do |caller_line|
!caller_line.include?('/initializers/')
end
if relevant_caller_line
logger.debug(" ↳ #{relevant_caller_line.sub("#{Rails.root}/", '')}")
end
end
end
ActiveRecord::LogSubscriber.send :prepend, LogQuerySource
```
So how does it shows its magic:
Here is an extract from my logs. As you can see the SQL query is bieng triggered by the block in `processed_repayments_changes` in `app/services/lead_services/timeline.rb`.
```
CACHE (0.1ms) SELECT "admin_users".* FROM "admin_users" WHERE "admin_users"."id" = $1 LIMIT 1 [["id", "2"]]
↳ app/services/lead_services/timeline.rb:175:in `block in processed_repayments_changes'
```
Super useful yea ??
Spread the word and let it help someone else too :)
### Bypassing ssh firewall by overriding Type of Service headers for TCP packets in routers
URL: https://til.codes/bypassing-ssh-firewall-by-overriding-type-of-service-headers-for-tcp-packets-in-routers/
Last updated: 2017-02-16T13:37:48.000Z
I was recently having issues when trying to ssh into one of my servers. The normal debugging techniques and solutions didn't work for me and I had to debug this in depth to figure out the issue was actually with my router blocking the packets
###### The actual problem.!
When you ask for a regular ssh terminal, ssh sets the TCP packet type of service (ToS) to "interactive". I was working from a cafe using a public wifi hotspot and the public wifi router that I was using was blocking those packet types!
###### Solution
So I now need to way to figure out and bypass those headers that were being set. I found that using `netcat`, the tunnelled TCP packets get no type of service directives. Thus, if you tunnel all your ssh traffic through `netcat`, you reset the ToS of the TCP packets to the default ones.
you can just add this to your ssh config file (either `~/.ssh/config` or `/etc/ssh/ssh_config`):
```
Host *.example.com
ProxyCommand nc %h %p
```
###### What is Type of Service(ToS)
The type of service (ToS) field in the IPv4 header. It had various definitions over time and the modern redefinition of the ToS field is a six-bit Differentiated Services Code Point (DSCP) field and a two-bit Explicit Congestion Notification (ECN) field.
The ToS field could specify a datagram's priority and request a route for low-delay, high-throughput, or highly-reliable service.
Based on these ToS values, a packet would be placed in a prioritized outgoing queue, or take a route with appropriate latency, throughput, or reliability.
### Debugging Git network connection issues using GIT_TRACE
URL: https://til.codes/debugging-git-network-connection-issues-using-git_trace/
Last updated: 2017-02-16T13:17:06.000Z
I have been travelling a lot this month and working remotely from cafes and public places during my stay in Europe. And most often I was connected to the internet using the public hot spots or free Wifi provided by the cafes or restaurants.
The quality of the connections were really good I must admit, but one common trouble I had with these connections was when using git.
Most of these connections had some restrictions with using git.
#### Problem
In one of the instances, I was able to push to github but was not able to fetch/clone/pull from the repo. As I issued the command
```
git fetch origin
```
it hangs there forever and didn't respond at all.
#### Debugging
So let's open our troubleshooting guide and go to Rule 1:
- Check your connectivity :P
```
ping google.com
PING google.com (216.58.205.238): 56 data bytes
64 bytes from 216.58.205.238: icmp_seq=0 ttl=46 time=124.577 ms
```
Okay, so I am connected.!!
- Check if you have access to the repo
Since I am able to push to repo, I am pretty sure that I have access to the repo, but still :check:
- Check if ssh was disabled.
```
$ ssh git@github.com
PTY allocation request failed on channel 0
Hi manusajith! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
```
Okay.!! so ssh is not blocked on the router for sure now.
- Replace `git://` protocol with `http/https`
I was pretty sure that this was not the issue, but still lets give it a try.!!
- Try changing your DNS to `8.8.8.8`
I already had that :P
Since all of the above failed, I realised that it needs a bit more serious debugging.
My immediate thoughts was to troubleshoot the network connections and to log the connection attempts to GitHub in a more verbose manner so that I can debug it in depth.
#### GIT\_TRACE
Welcome to `GIT_TRACE`. This configuration option gives us a more verbose trace to the git network connections and all the internal commands it goes through.
This environment variable can accept the following values:
- 1, 2, or true
If this variable is set to `1`, `2` or `true` ( the comparison is case insensitive), git will print trace: messages on stderr telling about alias expansion, built-in command execution and external command execution.
- greater than 1 and less than 10
If this variable is set to an integer value greater than 1 and lower than 10 (strictly) then git will interpret this value as an open file descriptor and will try to write the trace messages into this file descriptor.
- absolute path
Alternatively, if this variable is set to an absolute path (starting with a / character), git will interpret this as a file path and will try to write the trace messages into it.
```
$ GIT_TRACE=1 git fetch origin
13:44:47.299097 git.c:350 trace: built-in: git 'fetch' 'origin'
13:44:47.403611 run-command.c:336 trace: run_command: 'ssh' 'git@github.com' 'git-upload-pack '\''woumedia/naturalblender-api.git'\'''
```
With the more in-depth trace, I was able to figure out that it hanged forever at when trying to upload the pack.
Since I know where exactly the problem was I am now able to find an fix for the same, further research and debugging gave me clues as to why it was stuck there forever: It was a type of service issue with TCP packets handling on my router, which unfortunately couldn't do much about.
### Script/runner vz Rake tasks
URL: https://til.codes/script-runner-vz-rake-in-cron-job-rails/
Last updated: 2017-02-16T14:02:42.000Z
When it comes to running Rails tasks the common question that comes to mind is whether to use `script/runner` or to call a `rake` task
```
script/runner long_running_task
VZ
rake long_running_task
```
To understand it better we need to understand how both works under the hood.
Whenever `script/runner` is called it boots the entire Rails
But on the other hand Rake task doesn't load the entire Rails app unless you tell it to by making the task depend on `:environment`, like this:
```
task :some_useful_task => :environment do
# do some useful task
end
```
Since booting your Rails app is expensive each time, it might be worth skipping if you can avoid it.
### Elegant way to silently ignore a Ruby exception
URL: https://til.codes/which-is-the-shortest-way-to-silently-ignore-a-ruby-exception/
Last updated: 2017-02-16T13:47:55.000Z
I was working on a small hobby project and wanted to ignore some of the Exceptions that were raised.
The first version of the code that I wrote was something similar to:
```
def ignore_exception
begin
yield
rescue Exception
end
end
```
and using
```
ignore_exception { puts "Ignoring Exception"; raise Exception; puts "This is Ignored" }
```
After a bit of more googling and research, I came across another clean solution provided by `ActiveSupport`
```
suppress(Exception) do
# dangerous code here
end
```
**PS: Don't ask me why I wanted to do this, as I mentioned this was just a hobby project and will/should never go out into a production code.**
Ref: [http://api.rubyonrails.org/classes/Kernel.html#method-i-suppress](http://api.rubyonrails.org/classes/Kernel.html?ref=til.codes#method-i-suppress)
### brew cask: Error: Unknown command: cask
URL: https://til.codes/brew-cask-error-unknown-command-cask/
Last updated: 2016-09-24T14:45:08.000Z
After upgrading my OS to Sierra I was having an issue with homebrew. It failed to recognize the `cask` command and was throwing an error:
```
brew cask install haskell-platform
Error: Unknown command: cask
```
Brew wasn't able to find the correct path and was causing this issue.
### Fix:
```
brew update
brew cleanup
brew cask cleanup
```
### Manage sidekiq workers using deployment setup and Capistrano
URL: https://til.codes/manage-sidekiq-workers-using-deployment-setup-and-capistrano/
Last updated: 2016-09-09T06:17:33.000Z
In real world, most of the Rails applications would be having a Sidekiq instance as its companion in production systems. And it's a necessary thing to have some sort of mechanism to manage your Sidekiq instance with your deployment setup.
In this post, I am going to throw light on some of the options that you have with managing Sidekiq workers with the deployment setup capistrano.
1. using `capistrano-sidekiq` gem.
2. using custom tasks
###### Option1: `capistrano-sidekiq`
The first one is using `capistrano-sidekiq` gem which takes care of the hassle for you
First add `capistrano-sidekiq` to your Gemfile:
```
gem 'capistrano-sidekiq'
```
After you do a:
```
bundle install
```
Require `capistrano-sidekiq` in your Capfile:
```
require 'capistrano/sidekiq'
```
The gem comes with a lot of options to customize your Sidekiq instance, you can see the various available options from the [github page](https://github.com/seuros/capistrano-sidekiq?ref=til.codes#usage)
###### sidekiq default hooks
`capistrano-sidekiq` adds some default hooks when `capistrano-rails` is installed.
```
task :add_default_hooks do
after 'deploy:starting', 'sidekiq:quiet'
after 'deploy:updated', 'sidekiq:stop'
after 'deploy:reverted', 'sidekiq:stop'
after 'deploy:published', 'sidekiq:start'
end
```
\== Sidekiq will start or stop automatically during Rails deployments.== Just set `sidekiq_default_hooks` to false if you don't want this to happen.
You also can start/stop Sidekiq instances manually anytime using:
```
cap production sidekiq:start
```
**Note**: This option is prefered if you need advanced control of your sidekiq workers.
###### Option:2: Your own capistrano task
If you dont want to manage your sidekiq instances using `capistrano-sidekiq` gem you can simply add a custom task in your code like:
```
task :restart_sidekiq do
on roles(:worker) do
execute :service, "sidekiq restart"
end
end
after "deploy:published", "restart_sidekiq"
```
This will restart your sidekiq instance whenever capistrano publishes the artifacts to your server after a deployment.
### How to turn on SQL debug logging for ActiveRecord
URL: https://til.codes/how-to-turn-on-sql-debug-logging-for-activerecord/
Last updated: 2016-09-09T06:33:43.000Z
If you want to see the SQL queries that your apps are running and want o optimize them or tune them, then it is a nice idea to log them.
You can either log it to your log file or even to STDOUT.
You can set the log level in your environment file to `debug` so that you can get maximum data out of your application and can use the same for tuning.
```
config.log_level = :debug
```
To log it to STDOUT, you can add the following snippet to your specific environment file.
```
ActiveRecord::Base.logger = Logger.new(STDOUT)
```
References:
- Rails [Guide](http://guides.rubyonrails.org/debugging%5Frails%5Fapplications.html?ref=til.codes) about debugging
- ActiveRecord logger [class](http://apidock.com/rails/ActiveRecord/Base/logger/class?ref=til.codes)
### How to fix Npm install failed with "cannot run in wd"
URL: https://til.codes/npm-install-failed-with-cannot-run-in-wd-2/
Last updated: 2018-02-21T06:35:10.000Z
I was trying to upgrade my blogs ghost version to 0.9(which btw has some cool features) and I stumbled upon an issue when trying to upgrade the packages.
Every time I run
```
sudo npm install --production
```
on my server, I get the following error:
```
npm WARN cannot run in wd ghost@0.9.0 node core/server/utils/npm/preinstall.js (wd=/var/www/ghost)
```
On digging a bit deep, I found that NPM tries to downgrade its privileges when it runs scripts. That downgrading the privileges causes this error.
**TL;DR:**
So the workarounds are:
1. Run `sudo npm run postinstall` manually. OR
2. Run `npm install --unsafe-perm` OR
3. Run `sudo chown -R my_name /usr/local`
References:
1.Fixing npm permissions:[https://docs.npmjs.com/getting-started/fixing-npm-permissions](https://docs.npmjs.com/getting-started/fixing-npm-permissions?ref=til.codes)
2.[https://docs.npmjs.com/misc/scripts#user](https://docs.npmjs.com/misc/scripts?ref=til.codes#user)
### Copy file from host machine to docker container
URL: https://til.codes/copy-file-from-host-machine-to-docker-container/
Last updated: 2016-12-16T06:14:05.000Z
The `docker cp` utility copies the contents of `SRC_PATH` to the `DEST_PATH`. You can copy from the container’s file system to the local machine or the reverse, from the local filesystem to the container. If `-` is specified for either the `SRC_PATH` or `DEST_PATH`, you can also stream a tar archive from STDIN or to STDOUT. The CONTAINER can be a running or stopped container. The SRC\_PATH or DEST\_PATH can be a file or directory.
```
Usage: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH | -
docker cp [OPTIONS] SRC_PATH | - CONTAINER:DEST_PATH
Copy files/folders between a container and the local filesystem
-L, --follow-link Always follow symbol link in SRC_PATH
--help Print usage
```
For example:
```
docker cp foo.txt mycontainer:/foo.txt
docker cp mycontainer:/foo.txt foo.txt
```
Reference: [Docker CLI docs for cp](https://docs.docker.com/engine/reference/commandline/cp/?ref=til.codes)
### How to load rake task from a custom file or directory
URL: https://til.codes/load-rake-files-and-run-tasks-from-other-files/
Last updated: 2016-07-12T12:58:12.000Z
If you are wondering how you can load a rake task from a custom file, then this is guide will help you to accomplish your task.
Lets assume you have a rake task named `hello.rake` under your project directory's lib folder like:
```
/lib/tasks/hello.rake
```
Then you can create a simple `Makefile` in your directory to load it like this:
```
Dir.glob('lib/tasks/*.rake').each { |r| load r}
```
Of course, this will load all files ending with the rake extension. You can simply load `hello.rake` like this:
```
load './lib/tasks/hello.rake'
```
To see all the tasks that have been loaded use
```
rake -T
```
Note that we've used lib/tasks since that's the standard approach taken by Rails applications. You could use assets or whatever you prefer, though I prefer lib/tasks even in non-Rails projects.
Alternatively, you can either put your tasks into `rakelib/` folder which rake loads by default or add a specific folder in your Rakefile via:
```
Rake.add_rakelib 'lib/tasks'
```
### docker-compose up is slow on docker for mac os beta
URL: https://til.codes/docker-compose-slow-on-docker-for-mac-os-beta/
Last updated: 2016-12-16T06:12:18.000Z
I have been trying with Docker beta on Mac OS and was facing an issue with docker-compose.
It was taking ages for the docker-compose commands to get executed. After digging into a while I figured out that the dns lookup was causing the issues.
docker-compose is trying to resolve `localunixsocket.local`. You can get insight into the dns lookup by running
```
sudo tcpdump -A -s0 -nni en0 port 53
```
For now I've pointed `localunixsocket.local` to localhost in my `/etc/hosts`. Now everything is speedy again. To do the same, you need to edit `/etc/hosts` file and add the contents:
```
127.0.0.1 localunixsocket.local
```
Hope someone finds this useful
### Injecting auth-headers into angular.js application using http.config vz using interceptors.
URL: https://til.codes/injecting-auth-headers-into-angular-js-application-using-http-config-vz-using-interceptors/
Last updated: 2016-12-16T06:11:50.000Z
We have been building a client app in Angular.js
and decided on using token auth with JWTs, pretty much the normal choice.
We got everything set up on the server side and am receiving the token on the client side, but now we just need to send the token with every request.
At this point, our front-end developer bought an interesting point to debate. Should we be using an interceptor or should we add headers using $httpProvider config
Most resources out there say to use an $http interceptor to transform every outgoing request, but doesn't specify the reason as to why the approach is better than the other. I thought of writing it to give some insight on the internals of the same:
###### default headers vz $http interceptors.
The big difference between the two is that the providers are only executed once, during the config phase of the module `( .config() )`
Interceptors are called on the fly and are much more flexible with what you can do with them.
###### When to use providers
Use providers to set global config options where these options are static, never changing during the lifecycle of your app.
An example use case would be in a situation where you could use $httpProvider to set a token header, say for example if you're using a third-party API and they require an API\_KEY on every request.
Generally, API\_KEY's don't change, so it would make sense that your application config phase would set the API\_KEY in the provider, again abiding by the "static only settings" idea.
###### When to use interceptors
Use interceptors, to apply values that may dynamically change through the life cycle of your application.
The best illustration of interceptors would be to use and set Authentication headers or tokens that need to be sent along with each request. These tokens can change, and also might expire after a certain time.
An example code for injecting an interceptor for sending an authentication token along with each request is as follows:
```
module.factory('authInjector', ['AuthService', function(AuthService) {
var authInjector = {
request: function(config) {
if (!AuthService.isAnonymus) {
config.headers['Authentication-token'] = AuthService.token;
}
return config;
}
};
return authInjector;
}]);
module.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('authInjector');
}]);
```
###### TL;DR
The best way to do it is through the interceptor. Doing the setup in the `.config()` or `.run()` should be preferred for values that don't change over the lifecycle of the app.
### How to enable support for CORS with custom headers like authentication in Rails
URL: https://til.codes/how-to-enable-support-for-cors-with-custom-headers-like-authentication-in-rails/
Last updated: 2016-12-16T06:11:17.000Z
I was building a client side application for my API that I built using Rails/Grape. So in order to access the resources using the API from the client application the first thing that I need to do was to enable CORS support in the API.
### Enabling CORS using rack-cors gem
I did everything as was said in [README](https://github.com/cyu/rack-cors?ref=til.codes), that is updated Gemfile accordingly and updated application.rb like this:
```
module YourApp
class Application < Rails::Application
# ...
config.middleware.use Rack::Cors do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
end
end
```
It was pretty much straight forward, and now I have the CORS support enabled. My client side app should be able to access the API easily.
### Problem: Custom Headers like Authorization.
Now that I had the CORS setup, I tried to authenticate the user using JWT, and the authorization header. I was stumped to see that the server is not returning the authorization headers.
After some dabbling with the code, I figured out that the authorization headers were not accessible only from another domain - Something wrong with the CORS setup.
###### Reason: Custom headers were not exposed by default with the rack-cors gem.
By default, the rack-cors gem only exposes certain values like `Content-Type`, `Last-Modified` etc.
So the authorization header that I was setting wasn't being exposed over to the cross-origin requests.
###### Expose custom headers.
To expose any custom headers, we need to explicitly specify the keys in our configuration.
```
config.middleware.use Rack::Cors do
allow do
origins '*'
resource '*',
:headers => :any,
:expose => ['access-token', 'expiry', 'token-type', 'Authorization'],
:methods => [:get, :post, :options, :delete, :put]
end
end
```
So adding the `expose` key to the rack-cors configuration now exposes any custom headers like Authorization header
### How to install a specific package version in Alpine and Docker?
URL: https://til.codes/how-to-install-a-specific-package-version-in-alpine-and-docker/
Last updated: 2016-12-16T06:10:20.000Z
I was building a docker image for a backend API application that I was working on, so that my colleague, who is a front-end guy can easily setup the docker container and get it up and running.
I chose Alpine Linux to build the Docker image bcos its light weight. I started adding dependencies to the Dockerfile and I came across a situation where I needed to use a specific version of the package.
So this was what I had in my Dockerfile:
```
RUN apk update && \
apk upgrade && \
apk add ruby
```
And I needed Ruby 2.2.4 version to be installed in the image.
With the above code, it installs the latest version of the Ruby which is 2.3.
After some googling, I figured out that we can specify the version and lock it down so that the package manager will use that specific version of the package.
So here is the same code now:
```
RUN apk update && \
apk upgrade && \
apk add ruby=2.2.4
```
Exploring the options, we can set a minimum or maximum version to any package using
```
apk add 'packagename<1.2.3-suffix'
```
or
```
apk add 'packagename>1.2.3-suffix'
```
Hope this helps someone or even me in future. :)
### TDD in Elixir with ExUnit and Doctest
URL: https://til.codes/tdd-in-elixir-with-exdoc-and-doctests/
Last updated: 2016-12-16T06:09:25.000Z
###### ExUnit & DocTest
Elixir has it's own test framework built in natively, called ExUnit. ExUnit is a core component of Elixir itself, as much as the task runner and dependency manager mix. When you start a new project with mix, everything is directly set up for you, including basic unit tests for your first module and preconfigured tasks to do TDD right away.
In addition to traditional test suites, there is also another (often overlooked) feature, called DocTests. This means that you can copy a sample IEx call of your function, including the result, and paste it directly into a documentation block above the function in your code. When you run your test suite, these snippets are picked up by ExUnit and executed along with your tests! Using these DocTests you can ensure that comments will say the truth, even if someone changes the code of the function (because a test error will pop up that wants to be fixed).
###### When not to use doctest
In general, doctests are not recommended when your code examples contain side effects. For example, if a doctest prints to standard output, doctest will not try to capture the output.
Similarly, doctests do not run in any kind of sandbox. So any module defined in a code example is going to linger throughout the whole test suite run.
Example:
An example app can be found [here](https://github.com/manusajith/schizo%5Fexample%5Felixir?ref=til.codes):
```
defmodule SchizoTest do
use ExUnit.Case
doctest Schizo
test "uppercase doesnt change the first word" do
assert(Schizo.uppercase("foo") === "foo")
end
test "uppercase converts the second word to uppercase" do
assert(Schizo.uppercase("foo bar") == "foo BAR")
end
test "uppercase converts every other word to uppercase" do
assert(Schizo.uppercase("foo bar baz whee") == "foo BAR BAZ WHEE")
end
test "unvowel doesnt change the first word" do
assert(Schizo.unvowel("foo") === "foo")
end
test "unvowel removes the second words vowels" do
assert(Schizo.unvowel("foo bar") == "foo br")
end
test "unvowel removes every other words vowels" do
assert(Schizo.unvowel("foo bar baz whee") == "foo br bz wh")
end
end
```
and the accompanying code for the above test:
```
defmodule Schizo do
@moduledoc """
A nice module that lets you upcase or unvowel from every other word in a sentence
"""
@doc """
Uppercase every other word in a sentence, Example:
iex> Schizo.uppercase("you are awesome")
"you ARE AWESOME"
"""
def uppercase(string) do
transformer(string, &upcaser/1)
end
@doc """
Removes vowels from every other word in a sentence. Example:
iex> Schizo.unvowel("you are silly")
"you r slly"
"""
def unvowel(string) do
transformer(string, &unvoweler/1)
end
defp transformer(string, transformation) do
string
|> String.split()
|> Stream.with_index
|> Enum.map(transformation)
|> Enum.join(" ")
end
defp upcaser(input) do
transform(input, &String.upcase/1)
end
defp unvoweler(input) do
transform(input, fn (word) -> Regex.replace(~r/[aeiou]/, word, "") end)
end
defp transform({word, index}, transformation) do
case {word, index} do
{word, 0} -> word
_ -> transformation.(word)
end
end
end
```
### How to fix Incomplete response received from application from nginx / passenger in a rails application
URL: https://til.codes/how-to-fix-incomplete-response-received-from-application-from-nginx-passenger-in-a-rails-application/
Last updated: 2016-12-16T06:08:06.000Z
I was trying to deploy a simple rails application( stack is Ruby 2.2.4, Rails 4.2.5, with passenger/Nginx as application/web server) to AWS EC2 and I was getting a weird error.
```
Incomplete response received from application
```
And looking at the Nginx/passenger logs I wasn't able to figure out the issue first hand. Then == I tried to debug in detail and changed the `passenger_app_env` to development == so that I can see the debug logs in details and voila.!! I figured out how stupid I was.
Checking the logs, I see:
```
app error: Missing `secret_token` and `secret_key_base` for 'production' environment
```
\== Yep, you got it right, I forgot to set the `secret_token` in my env, and it caused the error. ==
After generating the `secret_token` using
```
RAILS_ENV=production rake secret
```
and exporting it to the bash env using:
```
export SECRET_KEY_BASE=secret_token
```
and restarting Nginx using
```
touch tmp/restart.txt
```
I was able to bring my rails app online.
As they say:
> Making mistakes simply mean you are learning faster. \~Weston H. Agor
Hope I save someone's time in future. :)
### Tail Call Optimisation
URL: https://til.codes/tail-call-optimisation-eplained/
Last updated: 2016-05-27T19:31:53.000Z
Tail Call Optimization is the process by which a smart compiler can make a call to a function and take no additional stack space.
The only situation in which this happens is if the last instruction executed in a function is a call to another function or the function itself.
The most common use is tail-recursion, where a recursive function written to take advantage of tail-call optimization can use constant stack space.
Normally during a recursion, the runtime needs to keep track of all the recursive calls, so that when one returns it can resume at the previous call and so on.
Keeping track of all the calls takes up space, which gets significant when the function calls itself a lot. But with tail call optimization, it can just say "go back to the beginning, only this time change the parameter values to these new ones." It can do that because nothing after the recursive call refers to those values.
Note first of all that not all languages support it.
Scheme is one of the few programming languages that guarantee in the spec that any implementation must provide this optimization (JavaScript will also, once ES6 is finalized), so here are two examples of the factorial function in Scheme:
In plain terms, TCO applies to a special case of recursion. If the last thing you do in a function is call itself (e.g. it is calling itself from the "tail" position), this can be optimized by the compiler to act like iteration instead of standard recursion.
The following example of calculating Factorial in elixir explain how Tail Call Optimization can be done.
```
defmodule Factorial do
def of(0), do: 1
def of(n) when n > 0 do
# Not tail call optimized
# because recursion needs to
# occur before multiplication
n * of(n - 1)
end
end
```
```
defmodule Factorial do
def of(0), do: 1
def of(n), do: of(n, 1)
def of(1, acc), do: acc
def of(n, acc) when n > 1 do
# Tail call optimized
# because recursion is the
# last calculation
of(n - 1, acc * n)
end
end
```
### Active Model Serializer vz Jbuilder vz Rabl vz Grape-entity for rendering JSON
URL: https://til.codes/active-model-serializer-vz-jbuilder-vz-rabl-vz-grape-entity-vz-roar/
Last updated: 2016-05-25T13:14:08.000Z
When architecting an API only application one the of the most important points of discussion among the team members is which framework to use ?
- Should we be using Rails and render JSON ?
- Should we be using Grape ?
- Should we be using Rails-API ?
Also, how are we gonna format the JSON responses? Options that usually pop up include:
- Jbuilder
- ActiveModelSerializer
- Rabl
- Grape-Entity
Anyways I am not gonna favour one over the other in this article, the choice of these options entirely depend on the use case, but instead, I will run via each of the options quickly to give a basic idea of each.
###### Jbuilder
Jbuilder is bundled with Rails, and so it's one of the most popular choices. Jbuilder provides a nice DSL to format and structure your JSON response. It provide us with an easy way to define exactly what attributes are included in and how the response is formatted and nested. For generating json responses we need to create correspon corresponding `/app/views/` directories just like you would with view templates but with the extension `.json.jbuilder`
```
# app/views/article/show.json.jbuilder
json.content format_content(@article.content)
json.(@article, :created_at, :updated_at)
json.author do
json.name @article.author.name.familiar
json.url url_for(@article.author, format: :json)
end
```
###### RABL
Another alternative is RABL, it also provides a custom DSL for generating JSON responses. It works by creating a view with the extension `.rabl`, and defining which attributes, nodes, and relations you wish to include in the JSON response.
```
# app/views/posts/index.rabl
collection @posts
attributes :id, :title, :subject
child(:user) { attributes :full_name }
node(:read) { |post| post.read_by?(@user) }
```
###### Active Model Serializer
Active Model Serializer is a great way to build JSON responses using an object oriented approach. It separates the serialization concern into its own folder /app/serializers, comes with its own Rails generator, and it behaves more like ActiveRecord in that you can define associations in the serializer.
It also allows you to choose your adapter-to decide what type of JSON structure is produced-or to build your own. Popular supported formats are JSON-API and JSON-HAL. It can also act as a presenter where you can define custom methods to display extra information or override how it’s displayed in your JSON.
###### ActiveModelSerializer and Rails 5 - API mode
With Rails 5, rails-api comes in bundled and when you generate a API only Rails app with ActiveModelSerializer is the default choice.
```
class PostSerializer < ActiveModel::Serializer
attributes :title, :body
has_many :comments
url :post
end
```
###### Grape Entity
Grape Entity was extracted from Grape, which is a popular gem used for building RESTful APIs. Similarly to RABL and Jbuilder, it provides a DSL for defining entities which are the structure of your JSON response.
```
module API
module Entities
class Article < Grape::Entity
expose :title
expose :content, documentation: { type: "Text", desc: "Blog post." }
expose :author_info do
expose :email
expose :full_name
end
end
end
end
```
###### ROAR
ROAR allows you to build presenter classes to represent your data. It also supports JSON and XML responses.
```
require 'roar/json'
module PostRepresenter
include Roar::JSON
property :title
end
```
###### ActiveModel or Plain Ruby Hash
This may seem like a strange thing to point out, but for very simple cases, you can simply call the to\_json method on either an ActiveModel object or a native Ruby Hash.
```
# Using an @organization model
respond_to do |format|
format.json do
render json: @organization.to_json
end
end
# Using a plain Ruby Hash
respond_to do |format|
format.json do
render json: {
name: @user.name,
email: @user.email
}.to_json
end
end
```
###### Benchmarks
[Kirill Platonov](https://twitter.com/platonov%5Fkd?ref=til.codes) has an interesting benchmark with ActiveModelSerializer vz Jbuilder. The following is an excerpt from his [article](http://kirillplatonov.com/2014/11/04/active%5Fmodel%5Fserializer%5Fvs%5Fjbuilder/?ref=til.codes)
> You can see everything by yourself. Jbuilder wins ActiveModel::Serializers only in the standalone variant of usage and only when use transform only single AR object, not an array. But the difference between Jbuilder and AMS in this case only 1.06x, it's very close to calculating error.
> And from opposite you can see, that in all other cases Jbuilder is much slower than ActiveModel::Serializers. And it's the real world cases because Jbuilder is mostly used with render method. And the results with render method are extremely bad for Jbuilder:
> 11.95x slower than AMS with a single object
> 8.94x slower than AMS with array of objects
> I think for now there is really no reason to use Jbuilder. It's very slow, too verbose and too complex for such simple task as transforming objects to JSON. You can use ActiveModel::Serializers and it will be handy and will cover all of your usage cases.
###### Conclusion
Now that you have various options at hand, I leave you to decide what is the best suited for your app.
> Already know you that which you need.
> \-- Yoda
### Error handling with Grape, Rails and ActiveRecord CanCan
URL: https://til.codes/error-handling-with-grape-rails-and-activerecord-cancan/
Last updated: 2016-05-05T07:33:52.000Z
I have been working on a project developing the backend API using Rails and Grape. One fine morning I pulled the latest code from the git repo that my colleague wrote, and was going to review the code. As usual, the first thing I did was to run the Integrations specs and to my surprise, some of the specs were failing.
The failing specs were mostly around the Sad path, and looking deeper I realized that the exceptions were not being handled properly in the code and was causing the specs to fail.
So, given the scenario, I wanted to handle the exceptions generated by the Grape API in a much clean and DRY way as these exceptions are ought to happen in the API any time.
So I decided to write a concern, by extending the ActiveSupport::Concern to handle all the exceptions that the app generates. So here is an abstract of the code that I came up with.
```
module API
module V1
module ExceptionsHandler
extend ActiveSupport::Concern
included do
rescue_from :all do |e|
# When required params are missing or validation fails
if e.class.name == 'Grape::Exceptions::ValidationErrors'
error!(e.message, status: 406)
# Bad token
elsif e.class.name == 'RuntimeError' && e.message == 'Invalid base64 string'
error!('401 Unauthorized', status: 401)
# AccessDenied - Authorization failure
elsif e.class.name == 'CanCan::AccessDenied'
error!('You don\'t have permissions.', status: 403)
# Record not found
elsif e.class.name == ActiveRecord::RecordNotFound do |e|
error!(e.message, status: 404)
# When all hell broke loose
else
Rails.logger.error "\n#{e.class.name} (#{e.message}):"
e.backtrace.each { |line| Rails.logger.error line }
Rack::Response.new({
error: '400 Bad Request',
errors: e.errors
}.to_json, 400)
end
end
end
end
end
end
```
You can add your own custom exceptions to the case. Some of the exceptions that Grape supports can be found [here](http://www.rubydoc.info/github/intridea/grape/Grape/Exceptions/ValidationErrors?ref=til.codes)
Hope someone finds this helpful.
### Using helper methods and helper modules in Rails Grape to keep the code DRY
URL: https://til.codes/using-helper-methods-and-helper-modules-in-rails-grape-to-keep-the-code-dry/
Last updated: 2016-05-05T08:42:49.000Z
I was working with a Grape API and got into a situation where I was kind of reimplementing some methods on more than one mounted API. So naturally, I wanted to refactor the code, keep it DRY and extract it as helper methods and eventually into helper module.
So here is what my base API class looks like:
```
# /app/api/api.rb
class API < Grape::API
format :json
version 'v1', using: :path
mount V1::A
mount V1::B
end
```
and here goes my helper module, nothing fancy, just pretty basic stuff:
```
# /app/api/v1/helpers/authentication_helpers.rb
module V1
module Helpers
module AuthenticationHelpers
extend Grape::API::Helpers
def current_operator
@current_operator ||= authenticate!
end
def authenticate!
# Handle the authentication stuff
end
end
end
end
```
So now we have our AuthenticationHelpers available, we can just go ahead and include them in any or every API that is mounted.
###### Loading helpers for every mounted API
We can include and load our AuthenticationHelper across all the mounted APIs by just including them in our base class and then making all other classes inherit from the base class API.
```
# /app/api/api.rb
class API < Grape::API
include V1::Helpers
format :json
version 'v1', using: :path
mount V1::A
mount V1::B
end
class A < API
# ...
end
class B < API
# ...
end
```
###### Loading helpers for a single mounted API
If we just want to include our AuthenticationHelper for one or two APIs only, we can go ahead and just include them on the individual classes.
```
# /app/api/v1/a.rb
module V1
class A < Grape::API
helpers V1::Helpers
# ...
end
end
# /app/api/v1/B.rb
module V1
class B < Grape::API
helpers V1::Helpers
#...
end
end
```
### JSON Web Tokens explained and how to use JWT in authentication with APIs
URL: https://til.codes/json-web-tokens-explained-and-how-to-use-jwt-in-authentication-with-apis/
Last updated: 2016-05-25T16:18:58.000Z
### Introduction
Over the last few years web application development has seen drastic changes, with the front-end frameworks coming to the scene, the popularity of hybrid applications, mobile first strategy, rising demand for SPAs, Microservices etc.
In older times, both the frontend and the backend would be in a single place, but this has changed over the years now. Using separate client-side applications is a common choice now. It definitely has a lot of advantages, but it also has brought significant changes on the architecture as well.
The RESTful API service model has been used a great amount recently in applications. Nowadays our back-end is more about complex business logic and data while presentation logic is moved exclusively to the front-end or mobile applications using frameworks like Angular/React/Ember etc
Also in most cases the application would need to interface with 3rd party services for fetching data. Interfacing with the 3rd party apps are often done using the APIs.
With these changes in the architecture, sharing data securely has also changed a lot. Previously cookies and server-based authentication was the easiest and go to solution.
However, with the client side frameworks in place handling authentication in modern Mobile and Single Page Applications can be tricky and needs to be addressed carefully. The best-known approaches for implementing authenticated endpoints for the APIS are either using OAuth 2.0 or the token based authentication using JSON Web Token (JWT).
### What are JSON Web Tokens?
The official draft of the JSON Web Tokens (JWT) is as below:
###### Abstract from the draft specification:
> JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.
###### Or in plain terms:
A JSON Web Token, or JWT, is a cryptographically signed token which can be used to send information that can be verified and trusted by means of a digital signature. This token can be verified against the signature to verify its authenticity. Since the token is encrypted we can include sensitive information like authorization headers in the payload,
###### Characteristics of JWT:
JWTs are self-contained: A JWT mainly has 3 parts, basic information about the token itself, a payload which can be sensitive information, and a signature. All these information are passed along with the JWT itself.
JWTs can be passed around easily: Since JWTs are self-contained, and encrypted they can be easily transmitted inside a HTTP header.
### What is the JSON Web Token structure?
JSON Web Tokens are self-contained and consist of three parts separated by dots (.), which are:
- Header
- Payload
- Signature
Therefore, a typical JWT looks like the following.
```
header.payload.signature
```
Let's break down the different parts.
##### Header
The header part of a JWT mainly consists of information related to the token itself. It has two parts:
- the type of the token, which is JWT,
- the hashing algorithm being used, such as HMAC SHA256 or RSA.
For example:
```
{
"alg": "HS256",
"typ": "JWT"
}
```
The above details are Base64Url encoded to form the header of a JWT
##### Payload
Payload is the second part of the JWT. It may include confidential information like user details, any other additional metadata etc. These are also called claims.
There are three types of claims: reserved, public, and private claims.
###### Reserved claims:
The standard defines a set of predefined claims. These are are not mandatory but hightly recommended.
Some of them are:
```
- iss: The issuer of the token
- sub: The subject of the token
- aud: The audience of the token
- exp: This will probably be the registered claim most often used. This will define the expiration in NumericDate value. The expiration MUST be after the current date/time.
- nbf: Defines the time before which the JWT MUST NOT be accepted for processing
- iat: The time the JWT was issued. Can be used to determine the age of the JWT
- jti: Unique identifier for the JWT. Can be used to prevent the JWT from being replayed. This is helpful for a one time use token.
```
###### Public claims:
Any custom claims can be defined in the public claims section.
###### Private claims:
These are the custom claims created to share information between parties that agree on using them.
Example Payload
Our example payload has two registered claims (iss, and exp) and two public claims (name, admin).
```
{
"iss": "til.codes",
"exp": 1464178005,
"name": "Manu S Ajith",
"admin": true
}
```
Payloads are also Base64Url encoded to form the second part of the JWT.
##### Signature
To create the signature for a JWT, we first need to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and using that sign that.
The commonly used algorithm is HMAC SHA256.
We can create the signature using the above header, payload, secret, and HMAC SHA256 algorithm in the following way:
```
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
```
This signature is used to verify the authenticity of the sender, and also makes sure that the token hasn't tampered.
##### Combining all the parts:
We can get our final JWT by combining the three Base64 strings separated by dots
The following shows a JWT that has the previous header and payload encoded, and it is signed with a secret.
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0aWwuY29kZXMiLCJleHAiOjE0NjQxNzgwMDUsIm5hbWUiOiJNYW51IFMgQWppdGgiLCJhZG1pbiI6dHJ1ZX0.fr2Vf8CzYzZ6swM0GRgmh3M_6VPYDnSBwlIJS99Bkf8
```
### When should you use JSON Web Tokens?
Some of the most common use case of JWT are authentication and information exchange.
Authentication: This is the most common use case for JWT. The authentication would be done using token based strategy, and with each subsequent request a JWT is passed back to the server. This JWT is used to permit or deny access to routes, services, and resources for that user. Applications using the Single Sign On strategy heavily leverges JWT because of its small overhead and its ability to be easily used across different domains.
Information Exchange: JWT are a good way of securely exchanging confidential information between applications because they are signed and ecrypted. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn't been tampered with.
### Advantages of Token-Based Authentication and JWT
**Stateless, easier to scale:** The JWT contains all the necessary information to identify a particular user. It can be sent to any server among a cluster of servers under a load balancer, not necessarily to the server that issued the token, or the server that the user logged in initially with.
**Reusability:** We can reuse the token generated across multiple servers and multiple platforms and domains. Applications using Single Sign On (SSO) are typical examples.
**Security:** Since the tokens are signed we can transmit the information securely over HTTP. Additionally, we can encrypt the tokens using JWE and also use an SSL and transmit over HTTPS
**Performance:** We can completely avoid deserializing the sessions back on the server on each request. We can use any of the servers to authenticate the token, validate it and parse the contents
### How do JSON Web Tokens work with authentication ?
Upon successfully authenticating a user using his credentials(email/password combinication), the server issues a JWT. This token is used to authenticate the user in all further requests. This can be saved on the client side
either in local storage, or cookies.
Whenever the user wants to access a authenticated/authorized route or resource, the client app should send the JWT that was issued previously, typically in the Authorization header using the Bearer schema. The content of the header should look like the following:
```
Authorization: Bearer
```
Since token based authenticate is stateless the user state is never saved in server memory. Each time the server gets a request to a protected route, it will check the validity of the JWT and the Authorization Header. Upon successfully decoding the token it will grant access to the resource if the user has permission to the same.
As JWTs are self-contained, it can even be used to store access levels for a particular user, reducing the need to query the database multiple times.
### Conclusion
The JSON Web Token standard can be used across multiple languages, frameworks and is quickly and easily interchangeable.
You can use the token in a URL, POST parameter, or an HTTP header. The versatility of the JSON Web Token lets us authenticate an API quickly and easily by passing information through the token.
### Docker difference between run, cmd, entrypoint commands
URL: https://til.codes/docker-run-vs-cmd-vs-entrypoint/
Last updated: 2016-11-09T10:33:22.000Z
If you have built a docker image, you would be familiar with the commands RUN, CMD, ENTRYPOINT. While some of you know what these means, where to use those and when to use those, there are some who might not know the exact difference between those commands. These commands are quite similar and can cause confusion to the newbies. So I thought of scribbling it down to give a clear idea of what these commands are and when to use what.
### TL;DR: In short
- RUN executes the command(s) that you give in a new layer and creates a new image. This is mainly used for installing a new package.
- CMD sets default command and/or parameters, however, we can overwrite those commands or pass in and bypass the default parameters from the command line when docker runs
- ENTRYPOINT is used when yo want to run a container as an executable.
If you are interested in the longer version, describing the details in detail, please read on. Before I explain the commands in detail, it would be good to mention a few basics about docker.
### Docker images and layers
When Docker runs a container, it runs an image inside it. This image is usually built by executing a series of Docker instructions, which add layers on top of existing image or OS distribution. OS distribution is the initial image and every package is added as a new layer on top of that.
### Shell and Exec forms
Commands in docker can be specified either in shell form or the Exec form.
All three instructions (RUN, CMD, and ENTRYPOINT) too can be specified in shell form or exec form.
###### Shell form
```
```
Examples:
```
RUN apk --update add install ruby
CMD echo "Hello world"
ENTRYPOINT echo "Hello world"
```
When an instruction is executed in shell form it calls `/bin/sh -c ` under the hood and normal shell processing happens. For example, the following snippet in Dockerfile
```
ENV name Manu
ENTRYPOINT echo "Hello, $name"
```
when container runs as `docker run -it ` will produce output
```
Hello, Manu
```
Note that variable name is replaced with its value.
###### Exec form
This is the preferred form for CMD and ENTRYPOINT instructions.
```
["executable", "param1", "param2", ...]
```
Examples:
```
RUN ["apk", "add", "ruby"]
CMD ["/bin/echo", "Hello world"]
ENTRYPOINT ["/bin/echo", "Hello world"]
```
When an instruction is executed in exec form it calls executable directly, and shell processing does not happen. For example, the following snippet in Dockerfile
```
ENV name Manu
ENTRYPOINT ["/bin/echo", "Hello, $name"]
```
when container runs as `docker run -it ` will produce output
```
Hello, $name
```
Note that variable name is not substituted.
###### How to run bash/zsh?
If you need to run bash (or any other interpreter like zsh but sh), use exec form with `/bin/bash` as executable. In this case, normal shell processing will take place. For example, the following snippet in Dockerfile
```
ENV name Manu
ENTRYPOINT ["/bin/bash", "-c", "echo Hello, $name"]
```
when container runs as `docker run -it ` will produce output
```
Hello, Manu
```
So hope you now have a clear idea of the 2 forms that can be used for specifying our commands. Now let us see the different commands and how to specify those using the 2 forms shell and exec.
#### RUN
As mentioned above, the RUN command is mainly used to install a new package on top of the main OS distribution. When you use the RUN command, it will execute the instruction and will create a new layer.
RUN command can be used in two forms:
```
1. Shell form
RUN
2. Exec form
RUN ["executable", "param1", "param2"]
```
A good example demonstrating the RUN instruction would be to install multiple system packages that are needed for your image.
```
RUN apk --update && \
apt add ruby \
ruby-json \
ruby-nokogiri \
git
```
Note that `apk --update` and `apt add` are executed in a single RUN instruction. This is done to make sure that the latest packages will be installed. If `apk add` were in a separate RUN instruction, then it would reuse a layer added by `apt --update`, which could had been created a long time ago.
#### CMD
CMD instruction allows you to set a default command and default parameters which will be executed when docker is run. But these commands and parameters can be overwritten by passing the values over the command line.
CMD can be specified in three forms:
```
1. exec form, preferred way
CMD ["executable","param1","param2"]
2. (sets additional default parameters for ENTRYPOINT in exec form)
CMD ["param1","param2"]
3. Shell form
CMD command param1 param2
```
Again, the first and third forms should look familar to you as they were already covered above. The second one is used together with ENTRYPOINT instruction in exec form. It sets default parameters that will be added after ENTRYPOINT parameters if container runs without command line arguments.
Let's have a look how CMD instruction works. The following snippet in Dockerfile
```
CMD echo "Hello world"
```
when container runs as `docker run -it ` will produce output
```
Hello world
```
but when container runs with a command, e.g., `docker run -it /bin/bash`, CMD is ignored and bash interpreter runs instead:
```
root@7de4bed89922:/#
```
#### ENTRYPOINT
ENTRYPOINT instruction should be used when you need your container to be run as an executable.
I might look similar to CMD, but in fact, it is different and should be used in a different context
The difference is ENTRYPOINT is that unlike CMD, the command and parameters are not ignored when Docker container runs with command line parameters. (There is a way to ignore ENTTRYPOINT, but it is unlikely that you will do it.)
ENTRYPOINT instructions too can be written in two forms:
```
1. Executable form preferred way
ENTRYPOINT ["executable", "param1", "param2"]
2. Shell form
ENTRYPOINT command param1 param2
```
###### Exec form
Exec form of ENTRYPOINT allows you to set commands and parameters and then use either form of CMD to set additional parameters that are more likely to be changed. ENTRYPOINT arguments are always used while CMD ones can be overwritten by command line arguments provided when Docker container runs. For example, the following snippet in Dockerfile
```
ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world"]
```
when container runs as `docker run -it ` will produce output
```
Hello world
```
but when container runs as `docker run -it ` Manu will result in
```
Hello Manu
```
###### Shell form
Shell form of ENTRYPOINT ignores any CMD or docker run command line arguments.
### Conclusion
Use RUN instructions to build your image by adding layers on top of the initial image.
Prefer ENTRYPOINT to CMD when building executable Docker image and you need a command always to be executed, and use CMD if you need to provide extra default arguments that could be overwritten from the command line when docker container runs.
Choose CMD if you need to provide a default command and/or arguments that can be overwritten from the command line when docker container runs.
### Behaviours in Elixir explained
URL: https://til.codes/behaviours-in-elixir-explained/
Last updated: 2016-05-17T19:24:23.000Z
Behaviours provide a way to define an interface which a module can implement. A module declares that it implements the Behaviour with the `@behaviour` annotation. The functions in the modules implementing the behaviour will be checked at compile time to see if they match the function specifications in the behaviour and if it doesn't it throws an error.
Behaviours provide a way to:
- define a set of functions that have to be implemented by a module;
- ensure that a module implements all the functions in that set.
###### Defining behaviours
If a module adopts the behaviour of another module, then it will have to define all the functions defined in the module that is said to behave.
So in order to define the function specifications that a module needs to implement the `@callback` directive is used
```
defmodule Greeter do
@callback shen_says_hello(String.t) :: any
@callback po_replies(String.t) :: any
end
```
###### Adopting a behaviour from another module
Modules adopting a behaviour will have to implement all the functions defined with the `@callback` directive.
```
# A module uses the @behaviour annotation to indicate that it implements a behaviour
defmodule LordShenGreetsPo do
@behaviour Greeter
def shen_says_hello(name) do
IO.puts "Greetings, #{name}, we meet at last !!"
end
def po_replies(name) do
IO.puts "Hey, how ya doin'?, #{name}"
end
end
# Since the following module does not implement po_replies/1 a compile time warning will occur: "warning: undefined behaviour function po_replies/1 (for behaviour Greeter)"
defmodule LordShenGreetsPo do
@behaviour Greeter
def shen_says_hello(name) do
IO.puts "Greetings, #{name}, we meet at last !!"
end
end
```
### require vz import vz use vz alias directives in Elixir
URL: https://til.codes/require-vz-import-vz-use-vz-alias-directives-in-elixir/
Last updated: 2016-05-17T18:41:12.000Z
One of an essential feature of a language when developing software is to reuse the code or the modules.
###### What are directives ?
So directives are a way via which we can reuse our code, import it and use it with other modules.
###### What are the available directives in Elixir
When it comes to elixir, we are given 4 options or directives:
- require
- import
- alias
- use
###### Require directive
We will be using macros across our code and there is a high chance that we would need to share these macros too.
So let's say we have a module named `Foo` and we have a macro `a_macro`
Now, in order to use that macro, we need to guarantee its module and implementation are available during compilation. This is done with the require directive.
```
iex> Foo.a_macro(1)
** (CompileError) iex:1: you must require Foo before invoking the macro Foo.a_macro/1
iex> require Foo
nil
iex> Foo.a_macro(1)
true
```
An attempt to call a macro that was not loaded will raise an error.
###### Import directive
import directive is used for easily accessing functions or macros from other modules without using the fully-qualified name. For instance, if we want to use the `duplicate/2` function from the List module several times, we can simply import it:
```
iex> import List, only: [duplicate: 2]
nil
iex> duplicate :ok, 3
[:ok, :ok, :ok]
```
In this case, we are importing only the function duplicate (with arity 2) from List. Although `:only` is optional, its usage is recommended in order to avoid importing all the functions of a given module inside the namespace. `:except` could also be given as an option in order to import everything in a module except a list of functions.
import also supports `:macros` and `:functions` to be given to `:only`. For example, to import all macros, one could write:
```
import Integer, only: :macros
```
Or to import all functions, you could write:
```
import Integer, only: :functions
```
Note that import is lexically scoped too. This means that we can import specific macros or functions inside function definitions:
```
defmodule Math do
def some_function do
import List, only: [duplicate: 2]
duplicate(:ok, 10)
end
end
```
In the example above, the imported List.duplicate/2 is only visible within that specific function. duplicate/2 won’t be available in any other function in that module (or any other module for that matter).
Note that importing a module automatically requires it.
###### use directive
Although not a directive, use is a macro tightly related to require that allows you to use a module in the current context. The use macro is frequently used by developers to bring external functionality into the current lexical scope, often modules.
For example, in order to write tests using the ExUnit framework, a developer should use the ExUnit.Case module:
```
defmodule AssertionTest do
use ExUnit.Case, async: true
test "always pass" do
assert true
end
end
```
Behind the scenes, use requires the given module and then calls the **using**/1 callback on it allowing the module to inject some code into the current context. Generally speaking, the following module:
```
defmodule Example do
use Feature, option: :value
end
is compiled into
defmodule Example do
require Feature
Feature.__using__(option: :value)
end
```
With this we are almost finishing our tour about Elixir modules. The last topic to cover is module attributes.
###### Aliases directive
At this point you may be wondering: what exactly an Elixir alias is and how is it represented?
An alias in Elixir is a capitalized identifier (like String, Keyword, etc) which is converted to an atom during compilation. For instance, the String alias translates by default to the atom `:"Elixir.String":`
```
iex> is_atom(String)
true
iex> to_string(String)
"Elixir.String"
iex> :"Elixir.String" == String
true
```
By using the `alias/2` directive, we are simply changing the atom the alias expands to.
Aliases expand to atoms because in the Erlang VM (and consequently Elixir) modules are always represented by atoms. For example, that’s the mechanism we use to call Erlang modules:
```
iex> :lists.flatten([1, [2], 3])
[1, 2, 3]
```
This is also the mechanism that allows us to dynamically call a given function in a module:
```
iex> mod = :lists
:lists
iex> mod.flatten([1, [2], 3])
[1, 2, 3]
```
We are simply calling the function flatten on the atom `:lists`.
###### Summary
alias to more conveniently reference modules
```
#Alias the module so it can be called as Bar instead of Foo.Bar
alias Foo.Bar, as: Bar
```
require to ensure macros are available and compiled
```
#Ensure the module is compiled and available (usually for macros)
require Foo
```
import to more conveniently reference functions
```
# Import functions from Foo so they can be called without the `Foo.` prefix
import Foo
```
use to give module opportunity to "hook" into your code
```
# Invokes the custom code defined in Foo as an extension point
use Foo
```
and all directives are lexically scoped.
### Install, configure and use git hooks to automate your workflow with distributed team
URL: https://til.codes/install-configure-and-use-git-hooks-to-automate-your-workflow-with-distributed-team/
Last updated: 2016-05-05T14:03:08.000Z
[My team](https://redpanthers.co/?ref=til.codes) uses Git as the center of our development process, leveraging all those cool features git provides us - git workflow, feature branching, switching branches for code reviews, Pull Requests and all such cool stuff. Using git is an integral part of our workflow, which means all the development happens over git branches, creating a Pull Request when you need a review, merging them into staging branch so that our CI servers can pick them up and get it deployed and so on.
Tl;DR: I am not here to explain the benefits of git driven workflow(you already are aware of that). This article explains some use cases of git hooks to automate some of those redundant tasks that you just hate doing or completely forget about.
##### So where does git hooks comes in ?
On any typical day, we work on our branch, switch to another branch for code review when someone in the team says - Hey can you hop in and see if this implementation can be optimized ?
By using git, it helps us to do this branch switching. But switching git branches in between your work also brings in some downsides.
This means we switch branches a lot, either to see someone’s code and review it or to kick off a new branch for a new feature. Over time this scenario seemed to happen a quite a few times:
###### Use case 1: Installing newly added dependencies, Running migrations, Generating new assets.
> Switch to master and pull in updates
>
> Start working on a new feature in a new branch
>
> Write something and run tests
> OMG!! the tests are failing..!!
> Turn to the team in slack: "Guys, I’m getting an error on the stuff you added, did you get it?"
> The team says: "No. Did you install the Gems and ran the migration ?"
> Me: "Ah my bad! you got me there, did not run `bundle install`" or "Ah dammit, I forgot to migrate the Db"
Developers often need to perform a set of tasks or operations when they pull a branch or checkout to a new branch, and if by any case these steps are missed you might end up having unexpected behavior. For the experienced pals, it is easy to debug, but for the inexperienced guys, it might take some time trying to figure out that they missed some basic steps that should have been done.
###### Use case 2: Prevent the developers from accidentally committing code which were used for testing or debugging.
Developers often have the habit of leaving behind some of the debug statements that they wrote while developing or testing the code in the final branch, not intentionally!. Some of the debug statements just puts/emits some information like `console.log(), Rails.logger.info(), IO.puts` etc while some others can expose confidential information regarding the stack itself `puts caller`, and in worse case it might even have a full REPL code like `debugger, binding.pry, IEx.pry ` .
And imagine the worse case when one of your developers leaves behind a `binding.pry` REPL, just like the one below to the final code and your CI is trying to run those tests.!!
```
# ...
it 'should return status 422' do
binding.pry
expect(response.status).to eq(422)
end
# ...
```
BOOM!! - Your CI servers end up in a limbo waiting for someone to get itself out of that debug statement.
##### Git hooks to the rescue.!
While there are many approaches preventing the above scenarios from happening, I chose to use a bunch of git hooks to achieve the objective. The benefit of using git hooks is that it can distribute to your teammates and can be reused.
###### What is a git hook?
A git hook is basically a bash script that runs on certain occasions in the execution process when you are working with git. They will take out some of those redundant tasks that you just hate doing or completely forget about.
They can do a bunch of tasks like check code style guide violations, security audits, check if debugger statements are present and a whole lot of useful stuff.
###### Different types of Git hooks.
Git supports custom script triggers through hooks. These hooks give you a chance to inject functionality at particular points in the standard pipeline:
Here are the basic available git hooks:
- Before committing ("pre-commit")
- Before writing a commit message ("prepare-commit-msg")
- After writing a commit message ("commit-msg")
- After committing ("post-commit")
- Before a rebase ("pre-rebase")
- After a checkout ("post-checkout")
- After a merge ("post-merge")
- Before receiving a push ("pre-receive")
- After receiving a push ("post-receive")
- Before receiving a push, run once per branch ("update")
###### Creating a Git Hook
Git comes with a lot of pre-available hooks. These default available hooks are included in every repo that you create by default and these can be found inside your `.git/hooks` dir.
To create a new hook, all we need to do is to create a file in the .git/hooks folder with the name of the hook you want to attach to, in my case `pre-commit`, since I want this to happen every time I am about to commit something.
So here is what one of my `pre-commit` hooks looks like for a typical Rails project
```
#!/bin/bash
# Grep through modified files for forbidden words and reject commit if found
# Separate more file types with pipes here
FILE_PATTERN='\.(js|html|rb|yml)(\..+)?$'
# Separate more forbidden strings with spaces here
FORBIDDEN=( console.log puts logger debugger binding.pry )
for i in "${FORBIDDEN[@]}"
do
git diff --cached --name-only | \
grep -E $FILE_PATTERN | \
GREP_COLOR='4;5;37;41' xargs grep --color --with-filename -n $i && \
echo 'Debugger code found:' $i 'Please remove them before commiting' && exit 1
done
exit 0
```
###### Gotchas
Note: Permissions of Hooks to Executable
When you’ve written a git hook, don’t forget to make it executable. Git will not tell you why it’s skipped and go ahead and skip the hook altogether.
Solution:
```
chmod ug+x .git/hooks/*
```
###### Wrap up
Git Hooks are pretty cool if your workflow is built around git like lots of teams do nowadays the hooks are a cool place to tie in your day to day stuff that tends to be forgotten and generate unneeded debugging and such. Take a look at available hooks and think about your routine, I’m pretty sure you will find something you can delegate out to git and stop worrying about it every day.
As they say:
> Anything that can be automated should be automated.!!
###### Further Reading:
1. [Git-scm Book](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks?ref=til.codes)
2. [Git-scm docs](https://git-scm.com/docs/githooks?ref=til.codes)
3. [Atlassian Tutorial](https://www.atlassian.com/git/tutorials/git-hooks?ref=til.codes)
### Rails : Devise : Send different Emails for Confirmation based on the presence of attribute or parameter
URL: https://til.codes/rails-devise-send-different-emails-for-confirmation-based-on-the-presence-of-attribute-or-parameter/
Last updated: 2016-05-05T09:51:07.000Z
So what am I up to today? - I thought of scribbling down some pieces of code that I wrote to help one of my interns in my company to help complete a task.
I was juggling with my daily work and I suddenly got a ping in our slack team
> Hey can you please advise me on how to use separate mailer templates for devise confirmation instructions just based on the presence/absence of a parameter/attribute value ?
I thought for a second and said,
TL;DR: you need to tell devise to your custom mailer, override the `confirmation_instructions` method in the same and you can pass in the template you want to use as options to that method.
##### Now the long story for who needs step by step instructions.
If you have a requirement that demands to send email when every time a user signup by his own or a user is invited into the system by an existing user and you may also want to send two different email template for two scenarios.
By default Devise do not support multiple email template so you need to define your new Mailer inherited from `Devise::Mailer` and configure Devise to use the Mailer you defined.
###### Configuring devise to use custom Mailer
```
# in config/initializers/devise.rb
# Configure the class responsible to send e-mails.
# config.mailer = 'Devise::Mailer'
config.mailer = 'CustomDeviseMailer'
```
and go ahead and create your `CustomMailer` inherited from `Devise::Mailer`
```
# in app/mailers/custom_devise_mailer.rb
class CustomDeviseMailer < Devise::Mailer
layout 'mailers'
# To make sure that your mailer uses the devise views
default template_path: 'devise/mailer'
def confirmation_instructions(record, token, options={})
# Use different e-mail templates for normal signup e-mail confirmation
# and for when a user is invited into the system by an existing user.
if record.invited?
options[:template_name] = 'invited_confirmation_instructions'
else
options[:template_name] = 'confirmation_instructions'
end
super
end
end
```
I hope someone finds this useful.
### Share button not working in Safari on OSX El-Capitan
URL: https://til.codes/safari-share-button-not-working-on-osx-el-capitan/
Last updated: 2016-04-26T07:42:26.000Z
## Share button not working in Safari on OSX El-Capitan
Since upgrading to the new El Capitain I have not been able to use the share button, one of the features that I liked the most with Safari. The strange thing was that it was working on my mac mini, while only my Macbook pro had the issue.
So, I did the next obvious thing, Google to rescue!
And here are some of the suggestions that I came across:
> `Might be corrupted Safari preferences after the upgrade to El Capitan`.
>
> Quit Safari if it's open.
>
> Open a Finder window. From the Finder menu bar click Go > Go to Folder
>
> Type or copy paste the following:
>
> `~/Library/Preferences/com.apple.Safari.plist`
>
> Click Go then move the com.apple.Safari.plist file to the trash.
>
> Relaunch Safari then try the Share button.
Another one:
> As for the spinning beach ball when trying to load a web page. Try troubleshooting Safari plugins and extensions. `You may have third party software installed that's not compatible with Safari `.
From the Safari menu bar `click Safari > Preferences` then select the `Extensions` tab. `Turn that OFF`, quit and relaunch Safari to test. If that helped, turn one extension on then quit and relaunch Safari to test until you find the incompatible extension then click uninstall.
`If it's not an extensions issue, try troubleshooting third party plug-ins`.
Back to Safari > Preferences. This time select the Security tab. Deselect: Allow all other plug-ins. Quit and relaunch Safari to test.
If that made a difference, instructions for troubleshooting plugins here.
None of the above were working for me and finally, I came across a thread:
> `The bug is caused by System Integrity Protection, a new feature of El Capitan`.
Just disable SIP, restart, check your system (everything should be back to normal), and then enable it again.
And in-case you are wondering how to get that done:
> Restart your machine and hold Cmd + R until you hear the chime. You'll enter recovery mode.
Once there open a terminal and type the following:
`csrutil disable`
This will disable the System Integrity Protection. After that just restart the machine.
All the widgets should be back.
Repeat the process again but this time type in the Terminal:
`csrutil enable`
And restart. You should be good to go now.
And finally I have the sharing option back in my Safari. And if you were wondering why the sharing feature was working on my mac mini - I was running the Apple Developer Program Beta Testing Mac OSx on my mac mini.
Hope someone finds this helpful.
### Testing carrierwave file uploads with RSpec and FactoryGirl.
URL: https://til.codes/testing-carrierwave-file-uploads-with-rspec-and-factorygirl/
Last updated: 2016-04-26T10:10:16.000Z
TLDR; In this blog post, I am gonna focus only on testing carrierwave. So if you are looking for instruction on installing/setting up carrierwave in your project I would suggest you looking at the carrierwave's wiki over [here](https://github.com/carrierwaveuploader/carrierwave/wiki?ref=til.codes).
So let's assume we have everything setup, in our rails application, We have a model named `Attachment` which uses the Carrierwave uploader(`FileUploader`) and the following code within it:
```
# app/models/attachment.rb
class Attachment < ActiveRecord::Base
mount_uploader :file, FileUploader
end
```
So to get started with testing, we need to create records which belong to the Attachment. So let's go ahead and create/update our factory to include the file.
```
# spec/factories/attachments.rb
FactoryGirl.define do
factory :attachment do
photo Rack::Test::UploadedFile.new(File.open(File.join(Rails.root, '/spec/fixtures/myfiles/myfile.jpg')))
end
end
```
So here I am attaching a file located in my `/spec/fixtures/myfiles/` folder as a photo. The above code just attaches the photo lazily to the factory when we build a new one. If you are using `create` method and creating records that are actually persisted in the DB, you want to update the above code to:
```
FactoryGirl.define do
factory :attachment do
after :create do |b|
b.update_column(:photo, "foo/bar/baz.png")
end
end
end
```
With the above code in our factory, we can use the same for testing with RSpec.
While the above code is enough to get to get started with the specs, I would suggest doing the following things to speed up and optimize your test suites.
1. Set storage to local file system in test environment.
2. Disable file process in test environment.
3. Separate out the upload folders for test environment.
4. Clean uploaded files after each request.
###### Setup Carrierwave to use local storage and disable file processing in test env
We can do that by adding following piece of code to `Carrierwave initializer`:
```
if Rails.env.test? || Rails.env.cucumber?
CarrierWave.configure do |config|
config.storage = :file
config.enable_processing = false
end
end
```
###### Separate out the upload folders for test environment.
Next, we should separate test uploads from any other uploads. We can do that by modifying `cache_dir` and `store_dir` methods for all Carrierwave models (i.e. all models that are descendants of CarrierWave::Uploader::Base).
```
# config/initializers/carrierwave.rb
CarrierWave::Uploader::Base.descendants.each do |klass|
next if klass.anonymous?
klass.class_eval do
def cache_dir
"#{Rails.root}/spec/support/uploads/tmp"
end
def store_dir
"#{Rails.root}/spec/support/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
end
```
###### Clean uploaded files after each request.
Adding the following code to our `spec_helper.rb` will make sure that we don't have stale images hanging around there after each request.
```
# spec_helper.rb
RSpec.configure do |config|
config.after(:each) do
if Rails.env.test? || Rails.env.cucumber?
FileUtils.rm_rf(Dir["#{Rails.root}/spec/support/uploads"])
end
end
end
```
###### Settting asset\_host
You also would want to set the asset\_host option for the carrierwave. For that add the following lines to the initializer.
```
CarrierWave.configure do |config|
config.asset_host = ActionController::Base.asset_host
end
```
So this is how your carrierwave initializer would like finally:
```
if Rails.env.test? || Rails.env.cucumber?
CarrierWave.configure do |config|
config.storage = :file
config.enable_processing = false
end
# make sure uploader is auto-loaded
FileUploader
CarrierWave::Uploader::Base.descendants.each do |klass|
next if klass.anonymous?
klass.class_eval do
def cache_dir
"#{Rails.root}/spec/support/uploads/tmp"
end
def store_dir
"#{Rails.root}/spec/support/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
end
end
CarrierWave.configure do |config|
config.asset_host = ActionController::Base.asset_host
end
```
Hope I have detailed enough pointers here to get started with carrierwave testing.
### fizzbuzz in elixir using OTP and GenServer
URL: https://til.codes/fizzbuzz-in-elixir-using-otp-and-genserver/
Last updated: 2016-04-25T17:57:57.000Z
Speaking of Erlang/Elixir the first thing that comes to mind is OTP. The erlang veterans would definitely playing around with it on a daily basis, but to the novice, it would sound a relatively strange term, and would be wondering what this is. So I thought of scribbling down something around this topic, to give a general idea on OTP and GenServer.
### What is OTP?
So if we go by the official words, OTP — the Open Telecom Platform can be defined as:
> “a complete development environment for concurrent programming”,
usually consisting of an Erlang compiler and interpreter, a database server (Mnesia), an analysis tool (Dyalizer).
### Behaviours
One of the central design principles of Erlang/OTP are application patterns, or `behaviours` as the grey-beards calls them. A set of common tasks would be defined as a generic implementation, and we just need to add implementation specific code into a callback module which exports a set of specific functions. With Elixir most of these implementations comes in built in, which makes the developers life easy. so we just need to override only those which matters for us.
### A FizzBuzz server using GenServer
FizzBuzz is an easy piece of code to get started with something, and I am gonna use the same here.
Elixir comes with a really cool build tool named `mix` that provides tasks for creating, compiling, testing your application, managing its dependencies.
Lets use `mix` to create a new project.
```
$ mix new fizzbuzz --module FizzBuzz
```
Running mix new creates a whole application using the default template for us.
So the next thing to do is, use GenServer in our application. So add the following to your
`lib/fizzbuzz.ex` file. I am also gonna use the `Logger` in later parts for debugging the code, so lets just add that too.
use GenServer
require Logger
So once we have everything in place, the next thing we would want is to have an API for our clients via which they can communicate to the server. So let's go ahead and write our APIs
Next we define the API for our clients.
```
def start_link do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
def get(n) do
GenServer.call(__MODULE__, {:print, n})
end
def print(n) do
GenServer.cast(__MODULE__, {:print, n})
end
```
###### Explanation:
`FizzBuzz.start_link/0` is just a wrapper around `GenServer.start_link/3` which starts the server as a linked process. Usually, the other functions refer to our server using the PID, but it's a bit odd to use the PID in every case. Alternatively we can start our server by passing the name option. In our case we will pass the name of the module `(__MODULE__)`
Our server mainly has 2 interfaces, namely, `FizzBuzz.get/1` and `FizzBuzz.print/1`. The input for these is a number and would return the value of the FizzBuzz as the output.
A GenServer mainly supports 2 request types: `calls` and `casts`.
`calls` is synchronous, which means it is supposed to send something back to the client (our get function), on the other hand `casts` is asynchronous and doesn’t necessarily return anything to the client (our print function).
It's usually considered as a best practice to wrap the GenServer interface in our own client APIs.
So moving on, we now need callbacks for the GenServer.
```
def init(:ok) do
Logger.debug "FizzBuzz server started"
{:ok, %{}}
end
def handle_call({:print, n}, _from, state) do
{:ok, fb, state} = fetch_or_calculate(n, state)
{:reply, fb, state}
end
def handle_cast({:print, n}, state) do
{:ok, fb, state} = fetch_or_calculate(n, state)
IO.puts fb
{:noreply, state}
end
```
`init/1` gets called by `GenSever.start_link/3` and returns a tuple of the form `{:ok, state}`. In our specific case the state is a simple Elixir map `(%{})`.
`handle_call/2` and `handle_cast/2` are the core of our application. We use pattern matching on the first argument to specify that we handle messages of the form {:print, n}. The private function fetch\_or\_calculate/2 retrieves or calculates the value, and we then return the appropriate response. In the case of a call it will have the form {:reply, response, state}, whereas for a cast it will be {:noreply, state}. These are GenServer conventions, the documentation lists all possible answer types for every request type.
This is what the private helper looks like:
```
defp fetch_or_calculate(n, state) do
if Dict.has_key?(state, n) do
Logger.debug "Fetching #{n}"
{:ok, fb} = Dict.fetch(state, n)
else
Logger.debug "Calculating #{n}"
fb = fizzbuzz(n)
state = Dict.put(state, n, fb)
end
{:ok, fb , state}
end
```
`fetch_or_calculate/2` checks if the FizzBuzz value for n has been calculated before. If it has, we fetch it from the dictionary. If the value hasn’t been computed before, we do so and update the state by adding the newly computed value to it `(Dict.put(state, n, fb))`. Finally, we return a tuple of the form `{:ok, value, state}` which we pattern match against in the handler functions.
That’s it, our FizzBuzz server is now ready for action! Here’s the complete code:
```
defmodule FizzBuzz do
use GenServer
require Logger
## Client API
def start_link do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
def get(n) do
GenServer.call(__MODULE__, {:print, n})
end
def print(n) do
GenServer.cast(__MODULE__, {:print, n})
end
## Server Callbacks
def init(:ok) do
Logger.debug "FizzBuzz server started"
{:ok, %{}}
end
def handle_call({:print, n}, _from, state) do
{:ok, fb, state} = fetch_or_calculate(n, state)
{:reply, fb, state}
end
def handle_cast({:print, n}, state) do
{:ok, fb, state} = fetch_or_calculate(n, state)
IO.puts fb
{:noreply, state}
end
defp fetch_or_calculate(n, state) do
if Dict.has_key?(state, n) do
Logger.debug "Fetching #{n}"
{:ok, fb} = Dict.fetch(state, n)
else
Logger.debug "Calculating #{n}"
fb = fizzbuzz(n)
state = Dict.put(state, n, fb)
end
{:ok, fb , state}
end
defp fizzbuzz(n) do
case {rem(n, 3), rem(n, 5)} do
{0, 0} -> :FizzBuzz
{0, _} -> :Fizz
{_, 0} -> :Buzz
_ -> n
end
end
end
```
Time to use our code. In the project directory, fire up an `iex` session in the context of our application with the following command:
```
iex -S mix
```
Now we can start a server and compute some values:
```
FizzBuzz.start_link
1..100 |> Enum.map(&FizzBuzz.print/1)
```
Here’s the output generated by that command. Due to the asynchronous nature of the requests the outout, log messages and the function’s return value are interleaved:
```
4
10:54:58.026 [debug] Calculating 4
Buzz
[:ok, :ok, :ok]
10:54:58.028 [debug] Calculating 5
Fizz
```
Note how despite running in a separate process, the output of `IO.puts` happened in our iex session, since that’s the current group leader.
If we now try to fetch an already computed value `(FizzBuzz.get(5))`, we can see that it’s actually retrieved from the cache:
```
10:58:56.774 [debug] Fetching 5
:Buzz
```
### Summary
This blog post explores the concepts of OTP, and how to leverage those concepts and build server applications.
Now our FizzBuzz application can be extended offering features like supervision and hot code swapping or can be deployed as part of a bigger Elixir application
### Some best practices while developing meteor.js apps
URL: https://til.codes/meteor-js-best-practices-and-techniques/
Last updated: 2016-12-16T06:04:15.000Z
Recently I was working as a consultant for a meteor.js app, reviewing the entire codebase, and came across some of the common mistakes the developer makes when writing his/her first meteor.js app. Though some of them are trivial, some others can have bigger consequences on the security of the application itself, and some others can affect the performance.
So I thought of scribbling down some of the best practices, do's and dont's in writing a metoer.js. Some of the points are just best-practices(maybe opinionated), and your app will work totally fine even if you don't follow those.
- Don't re-invent the wheel; use packages.
- Choice of router? - iron-router vz flow-router. iron-router was once the de facto choice, but time has changed and flow-router has taken over the reins now.
- Data modeling: Choosing between a normalized schema or embedding everything into the same document possibly creating duplicates. The choice depends on how often you want to read/write the data and how often the collection would be updated.
- Schema for collections and validation: Use collection2 package for attaching schema and validating the inputs.
- Use collection-hooks package for managing the before-*, after-* hooks in your code.
- Use meteor-autoform package to keep your forms clean.
- Use check package for in your app for advanced security.
- Try to cache the data that is subscribed, so that you don’t need to hit the database each time.
- Use pagination, won’t be an issue in the initial stages, but when the data grows, you wouldn’t want to load all the data in the initial load.
- Try to avoid the usage of Sessions whenever possible; Query the data from the server instead unless you really want the data to be there in multiple sessions or hot reloads.
- Have control of what data you expose and who can access what. Publish only those data that is needed.
- Never trust the user, and don't allow the client to update the data.
- Components - This can be debated - Blaze vz React, turns out that Blaze is now meteor's ex and React is its new crush.
- Remove auto publish and insecure from your packages before you deploy to production.
- Organize your code into directories, so that when the codebase grows, it can be maintained.
Hope the above best practices turns out to be helpful for you. Let me know of any best practice that you follow as comments.
### RVM error when starting zsh __rvm_cleanse_variables: function definition file not found
URL: https://til.codes/rvm-error-when-starting-zsh-rvm_cleanse_variables-function-definition-file-not-found/
Last updated: 2016-12-16T06:04:35.000Z
I was getting this error when opening new zshell:
```
__rvm_cleanse_variables: function definition file not found
command not found: rvm_error
```
Running the following solved the problem:
```
rm -f ~/.zcompdump*
```
*Note: The \* is incase there are multiple .zcompdump files.*
###### So what goes behind the scenes:
ZSH uses `compinit` to initialize completion for the current session. To speed up the running of compinit, it can be made to produce a dumped configuration which will be read in on future invocations. This dumped file is `.zcompdump` in the same directory as the startup files (i.e. `$ZDOTDIR` or `$HOME`)
### Run the last shell command with sudo
URL: https://til.codes/run-the-last-shell-command-with-sudo/
Last updated: 2016-02-16T09:59:15.000Z
I often an into the situation where I type in a long command, hit enter and then figure out that I needed to run that command as root user. Instead of typing the same command with sudo prefixed we can do the same thing using a shortcut.
To run the last command 'as is', you can just do
```
$ !!
```
If you want to run it as root, with sudo; just do
```
$ sudo !!
```
Hope you find it useful.
### How do I get a process to run in the background?
URL: https://til.codes/how-do-i-get-a-process-to-run-in-the-background/
Last updated: 2016-02-09T09:30:38.000Z
###### Simple / Usable things first
If you want a start script without much effort, you could use the upstart service. See the corresponding manual page and `/etc/init/*.conf` for examples. After creating such a process you can start your server by calling
```
service my server start
```
If you want more features, like specific limitations or permission management, you could try `xinetd`.
###### Using the shell
You could start your process like this:
```
nohup ./myexecutable &
```
The `&` tells the shell to start the command in the background, keeping it in the job list. On some shells, the job is killed if the parent shell exits using the `HANGUP` signal. To prevent this, you can launch your command using the nohup command, which discards the HANGUP signal.
However, this does not work, if the called process reconnects the HANGUP signal.
To be really sure, you need to remove the process from the shell's joblist. For two well known shells this can be achieved as follows:
```
bash:
./myexecutable &
disown
zsh:
./myexecutable &!
```
###### Killing your background job
Normally, the shell prints the PID of the process, which then can be killed using the kill command, to stop the server. If your shell does not print the PID, you can get it using
```
echo $!
```
directly after execution. This prints the PID of the forked process.
*Curated from [this](http://stackoverflow.com/questions/12486691/how-do-i-get-my-golang-web-server-to-run-in-the-background?ref=til.codes) answer in SO.*
### Remove Untagged Images From Docker
URL: https://til.codes/remove-untagged-images-from-docker/
Last updated: 2016-01-29T07:00:41.000Z
To delete all untagged images:
```
docker rmi $(docker images -q --filter "dangling=true")
```
### Docker: Remove all images and containers
URL: https://til.codes/docker-remove-all-images-and-containers/
Last updated: 2016-01-18T08:31:54.000Z
To delete all the containers we have created so far:
```
docker rm $(docker ps -a -q)
```
To delete all the images in docker:
```
docker rmi $(docker images -q)
```
NB: Deleting docker containers and images is not reversible. Make sure you know what you are upto.
Ref: [Docker Issue](https://github.com/docker/docker/issues/928?ref=til.codes#issuecomment-23538307)
### Restricting users signup to a particular domain in meteor.js
URL: https://til.codes/restricting-users-signup-to-a-particular-domain-in-meteor-js/
Last updated: 2016-01-08T19:10:01.000Z
If you want to restrict the user registration to a particular domain only, say for e.g.: `codingarena.in`, then you can do the same by adding the following code:
```
Accounts.config({restrictCreationByEmailDomain:'codingarena.in'});
```
### Git fatal: remote origin already exists
URL: https://til.codes/git-fatal-remote-origin-already-exists/
Last updated: 2016-01-07T19:01:52.000Z
One of my colleagues was facing an issue with git, trying to add a remote to the git repo.
```
➜ repo_name git:(master) git remote add origin git@github.com:username/repo_name.git
fatal: remote origin already exists.
```
As the error message indicates, there is already a remote configured with the name `origin`. So you can either add the new remote with a different name say `github` or update the existing one if you don't need it:
To add a new remote with an alternate name, called for example github instead of origin (which obviously already exists in your system), do the following:
```
$ git remote add github git@github.com:username/repo_name.git
```
Alternatively, you can update the existing remote `origin` using the following command:
```
$ git remote set-url origin git@github.com:username/repo_name.git
```
If you want to list the current remotes, you can check the same using
```
git remote -v
```
### How to Fix [ERROR] Unknown/unsupported storage engine: InnoDB
URL: https://til.codes/how-to-fix-error-unknownunsupported-storage-engine-innodb/
Last updated: 2016-01-07T18:47:57.000Z
After playing around with my MySQL configuration file in my docker container, MySQL was throwing a weird error, and was failing to start.
I checked the error logs and found an entry in the error log.
```
[ERROR] Plugin ‘InnoDB’ init function returned error.
[ERROR] Plugin ‘InnoDB’ registration as a STORAGE ENGINE failed.
[ERROR] Unknown/unsupported storage engine: InnoDB
[ERROR] Aborting
```
After googling and searching SO for a while, I realised that the solution is to rename or delete some of the log files of InnoDB. In case you are concerned about the data, it would be wise to have a backup of those files, in my case I encountered the error on a fresh docker MariaDB container. Hence I chose to remove the files.
```
rm /var/lib/mysql/ib_logfile0
rm /var/lib/mysql/ib_logfile1
```
and then restart MySQL.
```
root@docker# /etc/init.d/mysql start
Starting MySQL database server: mysqld . ..
Checking for tables which need an upgrade, are corrupt or were
not closed cleanly..
root@docker#
```
And thats it, I now have my MySQL server up and running once again.
### Format time using moment.js in meteor
URL: https://til.codes/format-time-using-moment-js-in-meteor/
Last updated: 2016-01-07T17:18:06.000Z
If you want to format a time field from you database, say for e.g.: createdAt, the following helper can be used.
```
UI.registerHelper('formatTime', function(context, options) {
if(context)
return moment(context).format('MM/DD/YYYY');
});
```
An alternate way would be to write a helper for one particular view, but creating a global helper would help us to re-use the helper elsewhere too and keep the code DRY.
### Masonry in meteor.js
URL: https://til.codes/masonry-in-meteor-js/
Last updated: 2016-01-07T17:04:22.000Z
Code snippet to make masonry work with meteor.js
```
Template.activity_feed.rendered = function () {
$('.masonry-container').isotope({
itemSelector: '.item',
layoutMode: 'masonry',
masonry: {
columnWidth: 200,
gutterWidth: 5
}
})
};
```
### Visualise your Gemfile dependencies
URL: https://til.codes/visualize-your-gemfile-dependencies/
Last updated: 2016-01-03T20:34:00.000Z
If you ever wanted to visualise the gem dependencies of in your ruby/rails app, then bundler is there for rescue.
Type in the following from your terminal:
```
bundle viz
```
Viz generates a PNG file of the current Gemfile as a dependency graph. Viz requires the `ruby-graphviz` gem (and its dependencies) to be installed on the system.
### Connecting Ruby & Active Record Without Rails
URL: https://til.codes/connecting-a-ruby-app-to-active-record-without-rails/
Last updated: 2016-01-01T17:06:41.000Z
```
require 'active_record'
require 'mysql2' # or 'pg' or 'sqlite3'
# Change the following to reflect your database settings
ActiveRecord::Base.establish_connection(
adapter: 'mysql2', # or 'postgresql' or 'sqlite3'
host: 'localhost',
database: 'your_database',
username: 'your_username',
password: 'your_password'
)
# Define your classes based on the database, as always
class YourModel < ActiveRecord::Base
end
```
### Best way to make a shell script daemon?
URL: https://til.codes/best-way-to-make-a-shell-script-daemon/
Last updated: 2015-12-31T17:55:33.000Z
I wanted to run a shell script as a daemon, and I was exploring SO as usual, and one of the answers that I found interesting and that fits my use case was:
```
(./install.sh &) &
```
Ref: to the original question [here](http://stackoverflow.com/questions/3430330/best-way-to-make-a-shell-script-daemon?ref=til.codes).
### Postgresql: How to find pg_hba.conf file using Mac OS X
URL: https://til.codes/postgresql-how-to-find-pg_hba-conf-file-using-mac-os-x/
Last updated: 2015-12-29T18:39:04.000Z
To find the postgresql config file we can use the `locate` command.
Type the following in your terminal:
```
locate pg_hba.conf
```
Or else:
If you have a postgres server running on your machine, you can find the config directory using the following command
```
ps aux | grep postgres
```
which would show something similar to:
```
user 3391 0.0 0.0 2615032 804 ?? S 18Dec15 1:01.04 /usr/local/opt/postgresql/bin/postgres -D /usr/local/var/postgres -r /usr/local/var/postgres/server.log
```
The `-D` option in the above command show the directory of the postgres, where you would be able to locate the `pg_hba.conf` file
or else:
if you can connect to your postgres server, then the following command show the config files.
```
SHOW hba_file;
SHOW config_file;
```
Hope that helps.
### Dump PostgreSQL without owner and privileges
URL: https://til.codes/dump-postgresql-without-owner-and-privileges/
Last updated: 2015-12-29T16:29:34.000Z
If you ever wanted to dump your postgres development database without the owner and the privileges, then you just need to run the following command:
```
pg_dump database_name -O -x > output_file
```
### Start Phoenix app with cowboy server on different port
URL: https://til.codes/start-phoenix-app-with-cowboy-server-on-different-port/
Last updated: 2015-11-23T04:12:47.000Z
To run phoenix app on a custom port other than port 4000, tweak your config file for respective environment(dev/prod/test) to the following:
```
config :my_app, MyApp.Endpoint,
http: [port: {:system, "PORT"}],
```
Then from the terminal:
```
$ PORT=4001 mix phoenix.server
$ PORT=4002 mix phoenix.server
```
Enjoy.!
### Problem installing puma on OS X with openssl
URL: https://til.codes/problem-installing-puma-on-os-x-with-openssl/
Last updated: 2015-11-17T19:12:22.000Z
When installing puma on OSX 10.11 El Capitan, if you are facing issues compiling mini\_ssl.c
```
fatal error: 'openssl/bio.h' file not found.
```
all you need to do is to specify
```
--with-opt-dir
```
You can make this applicable for all your Gemfiles:
```
bundle config build.puma --with-opt-dir=/usr/local/opt/openssl
```
Thanks to [Jeremy](https://github.com/jeremy?ref=til.codes) for [this](https://github.com/puma/puma/issues/718?ref=til.codes#issuecomment-139624081)
### Run Multiple Skype clients on Mac OS X?
URL: https://til.codes/run-multiple-skype-clients-on-mac-os-x/
Last updated: 2015-11-16T18:45:33.000Z
Just run the following command in terminal:
```
open -na /Applications/Skype.app --args -DataPath /Users/$(whoami)/Library/Application\ Support/Skype2
```
### Creating tables and problems with primary key in Rails
URL: https://til.codes/creating-tables-and-problems-with-primary-key-in-rails/
Last updated: 2015-11-13T01:22:53.000Z
If you run into the following error when running a migration
in your legacy Rails app with MySQL 5.7 or above
```
rake aborted!
"Mysql2::Error: All parts of a PRIMARY KEY must be NOT NULL:"
```
the fix is by monkey patching the MySQL Adapter using the following code.
```
# lib/patches/abastract_mysql_adapter.rb
class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter
NATIVE_DATABASE_TYPES[:primary_key] = 'int(11) auto_increment PRIMARY KEY'
end
```
and then require it from your `environment.rb`
```
require File.expand_path('../../lib/patches/abstract_mysql_adapter', __FILE__)
```
This issue is fixed in the latest version of Rails, but your legacy apps would need to be patched manually.
If you are interested in learning more about change that caused this issue, you can refer [this](http://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-3.html?ref=til.codes) link
### Easy way pull latest of all git-submodules
URL: https://til.codes/easy-way-pull-latest-of-all-git-submodules/
Last updated: 2015-11-08T14:20:43.000Z
Often large projects have dependencies on many other 3rd party libraries. Each library can be a separate repo that can be brought into the dependant project as a submodule. During development, if ever you want to just go grab the latest version of every dependant submodule, type in the following command:
```
git pull origin master --recurse-submodules
```
### Hibernate not working 15.04
URL: https://til.codes/hibernate-not-working-15-04/
Last updated: 2015-10-30T01:33:21.000Z
To know your swap partition, run `swapon -s`. Let's say it reports `/dev/sda5`.
Open `/etc/default/grub` and find the line with `GRUB_CMDLINE_LINUX_DEFAULT=`. This is the list of kernel command line options GRUB will pass to Linux. Add `resume=/dev/sda5`, so the line
`GRUB_CMDLINE_LINUX_DEFAULT="nosplash enable_mtrr_cleanup=1"`
will now look like this
```
GRUB_CMDLINE_LINUX_DEFAULT="nosplash enable_mtrr_cleanup=1 resume=/dev/sda6"
```
Save the file and run this to enable the new configuration:
```
sudo update-grub2
```
And that's it..!!
### Pundit for authorization with Rspec Rails
URL: https://til.codes/pundit-for-authorization-with-rspec-rails/
Last updated: 2015-10-21T01:02:28.000Z
Authorization is one of the important feature of any web app.
With rails you can leverage the power of all those wonderful open source gems that are available to you or you can code your own authorization module.
The most commonly used gems for authorization are [Pundit](http://github.com/elabs/pundit?ref=til.codes) and `Cancan` (now [cancancan](https://github.com/CanCanCommunity/cancancan?ref=til.codes), since the community took over the development of the gem. One reason for which I love the Ruby community the most :))
Now since we have those 2 popular gem, the next big question is which to chose from
### Pundit or Cancan ?
#### Cancan
- Popular among the two.
- More star gazers in github.
- Now being maintained by the community.
- Custom DSL
#### Pundit
- Plain ruby classes and Object Oriented code design patterns.
- No DSL to master
- PORO.
### Basic usage
The setup and install instructions are documented in detailed in the gem's wiki itself.
The main principle is to extract the authorization rules into policy files, which are POROs:
For eg:, an Article plolicy might look like:
```
class ArticlePolicy
attr_reader :user, :article
def initialize(user, article)
@user = user
@article = article
end
def new?
user.has_roles?('author')
end
alias_method :create?, :new?
def edit?
user.has_roles?('author') && article.is_draft?
end
alias_method :update?, :edit?
end
```
And your corresponding controller will be something like :
```
class ArticleController < ApplicationController
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
...
def edit
@article = Article.find(params[:id])
authorize @article
...
end
...
private
def user_not_authorized
flash[:error] = 'You are not authorized to perform this action.'
redirect_to(request.referrer || root_path)
end
end
```
### Testing with Rspec.
Pundit works well with rspec. Thunderboltlabs has a nice [article](http://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/?ref=til.codes) written on testing pundit policies with rspec.
Going ahead and adding the matchers for pundit:
```
RSpec::Matchers.define :permit do |action|
match do |policy|
policy.public_send("#{action}?")
end
failure_message_for_should do |policy|
"#{policy.class} does not permit #{action} on #{policy.record} for #{policy.user.inspect}."
end
failure_message_for_should_not do |policy|
"#{policy.class} does not forbid #{action} on #{policy.record} for #{policy.user.inspect}."
end
end
```
to `spec/pundit_matcher.rb` and including that in our `spec_helper` using `Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}`.
Once we have the custom matchers and the support files loaded into spec helper we can go ahead and write our test cases our article policy.
So our rspec test will be having a following pattern:
```
require 'spec_helper'
describe ArticlePolicy do
subject { ArticlePolicy.new(user, article) }
let(:article) { FactoryGirl.create(:article) }
context 'for a visitor' do
let(:user) { nil }
it { should_not permit(:create) }
it { should_not permit(:new) }
it { should_not permit(:update) }
it { should_not permit(:edit) }
end
context "for an author" do
let(:user) { FactoryGirl.create(:user, role: 'author') }
it { should permit(:create) }
it { should permit(:new) }
it { should permit(:update) }
it { should permit(:edit) }
end
end
```
### Tweaks with shoulda matchers.
In case your application is using shoulda matchers there is a chance that the above wont work, as a result of conflicting namespace. You can read more about the same [here](https://github.com/elabs/pundit/issues/142?ref=til.codes).
So the work around would be to tweak your support file. Instead of using the conflicting `permit` we just rename it to `permitted` a little bit to the following:
```
RSpec::Matchers.define :permitted_to do |action|
match do |policy|
policy.public_send("#{action}?")
end
failure_message_for_should do |policy|
"#{policy.class} does not permit #{action} on #{policy.record} for #{policy.user.inspect}."
end
failure_message_for_should_not do |policy|
"#{policy.class} does not forbid #{action} on #{policy.record} for #{policy.user.inspect}."
end
end
```
Updating our test case for the above workaround,
```
require 'spec_helper'
describe ArticlePolicy do
subject { ArticlePolicy.new(user, article) }
let(:article) { FactoryGirl.create(:article) }
context 'for a visitor' do
let(:user) { nil }
it { should_not permitted_to(:create) }
it { should_not permitted_to(:new) }
it { should_not permitted_to(:update) }
it { should_not permitted_to(:edit) }
end
context "for an author" do
let(:user) { FactoryGirl.create(:user, role: 'author') }
it { should permitted_to(:create) }
it { should permitted_to(:new) }
it { should permitted_to(:update) }
it { should permitted_to(:edit) }
end
end
```
Another possible work around is not to load the shoulda matchers in your policies specs. You can restrict this by loading them only to your models, controllers etc.
Hope you find this helpful.
### Manually insert users from seed file with accounts-password
URL: https://til.codes/seeding-users-in-meteor-js-and-account-password/
Last updated: 2015-09-30T01:05:30.000Z
One of the easiest way to seed users/admin-user into the system is by running the following on the server when it starts:
```
Meteor.startup(function() {
if (Meteor.users.find().count() === 0) {
Accounts.createUser({
username: 'test',
email: 'me@til.codes',
password: 'password'
});
}
});
```
### Postgres could not connect to server
URL: https://til.codes/postgres-could-not-connect-to-server/
Last updated: 2015-09-22T13:50:52.000Z
```
$ psql
psql: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
```
The reason for the issue is because a pid file was blocking postgres from starting up. To fix it:
```
rm /usr/local/var/postgres/postmaster.pid
```
and then all is well.
### Ruby: delete multiple hash keys
URL: https://til.codes/ruby-delete-multiple-hash-keys/
Last updated: 2015-07-24T09:16:19.000Z
Returns a hash that includes everything but the given keys.
```
hash = { a: true, b: false, c: nil}
hash.except(:c) # => { a: true, b: false}
hash # => { a: true, b: false, c: nil}
```
This is useful for limiting a set of parameters to everything but a few known toggles:
```
@person.update(params[:person].except(:admin))
```
### “bin/rails: No such file or directory” w/ Ruby 2 & Rails 4 on Heroku
URL: https://til.codes/binrails-no-such-file-or-directory-w-ruby-2-rails-4-on-heroku/
Last updated: 2015-07-20T06:30:34.000Z
Rails apps with version 4 or above has some files under the `bin` folder namely `bundle`, `rails`, `rake`, `setup`, `spring`. But since I had `bin` folder gitignored, these files dint make it to heroku.
To fix this:
Remove bin from \~/.gitignore
Run `bundle install` or `rake rails:update:bin`
Commit your changes with `git add .` and `git commit -m "Add bin back"`
Push your changes to Heroku with git push heroku master
Heroku has a detailed article on the same which can be found [here](https://devcenter.heroku.com/articles/rails4?ref=til.codes).
### SET GOPATH environment variable on Ubuntu?
URL: https://til.codes/how-do-i-set-the-gopath-environment-variable-on-ubuntu/
Last updated: 2015-07-17T15:41:40.000Z
Just add the following lines to `~/.bashrc`
```
export GOROOT=/usr/lib/go
export GOPATH=$HOME/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
```
### Calling View helper methods from Controller / Model in Rails
URL: https://til.codes/calling-view-helper-methods-from-controller-model-in-rails/
Last updated: 2015-07-17T11:55:20.000Z
Recently I was researching a way to use `link_to` inside my Rails 3 controller, and learned about the method `view_context`.
So if you ever want to access view helper methods from controller / models in rails 3 you have to use view\_context method.
Example
```
view_context.link_to 'Link', link_path(@link)}.
```
PS:
Just a note that you should avoid calling these functions within the controllers to follow mvc pattern conventions.
### Email notification when someone logs in via SSH
URL: https://til.codes/email-notification-when-someone-logs-in-via-ssh/
Last updated: 2015-07-13T19:06:22.000Z
To setup email notification, login to your server as root.
Edit `.bashrc`
```
vim .bashrc
```
add the following line at the end, changing `"ServerName"` to the host-name of your server and `"me@til.codes"` to your own email address.
```
echo 'ALERT - Root Shell Access (Server-name) on:' `date` `who` | mail -s "Alert: Root Access from `who | cut -d"(" -f2 | cut -d")" -f1`" me@til.codes
```
Save and exit.
Next time someone (hopefully you) logs on as root, you will get an email about this.
### How do I make --no-ri --no-rdoc the default for gem install?
URL: https://til.codes/how-do-i-make-no-ri-no-rdoc-the-default-for-gem-install/
Last updated: 2015-07-13T15:43:15.000Z
If you are deploying to a server, or you do not want to wait around for rdoc and ri to install for each gem, you can disable them for gem installs and updates.
Just add the following line to your `~/.gemrc` or `/etc/gemrc`:
```
gem: --no-rdoc --no-ri
```
or
```
gem: --no-document
```
or if want to be more specific,
```
install: --no-document
update: --no-document
```
### How to update git remotes
URL: https://til.codes/how-to-update-git-remote/
Last updated: 2015-07-13T10:26:42.000Z
To list the existing remotes, we can use the following command:
```
git remote -v
#View existing remotes
origin https://github.com/user/repo.git (fetch)
origin https://github.com/user/repo.git (push)
```
Use the following command to set the remote to a new end point.
```
git remote set-url origin https://github.com/user/repo2.git
# Change the 'origin' remote's URL
```
Making sure that worked ;)
```
git remote -v
# Verify new remote URL
# origin https://github.com/user/repo2.git (fetch)
# origin https://github.com/user/repo2.git (push)
```
Reference: [Github](https://help.github.com/articles/changing-a-remote-s-url/?ref=til.codes)