Skip to content

Instantly share code, notes, and snippets.

@mckeed
mckeed / pre-commit
Last active January 24, 2025 17:47
Run rubocop on only staged files in git pre-commit
#!/bin/sh
STAGED_FILES=$(git diff-index HEAD --name-only --cached)
if [[ -z $STAGED_FILES ]]
then
exit # no staged files, no need to run rubocop
fi
# Checks if any staged files have unstaged changes
# otherwise rubocop isn't running on what is actually
@borkdude
borkdude / api_diff.clj
Last active September 30, 2021 19:37
Print API breakage warnings
#!/usr/bin/env bash
#_" -*- mode: clojure; -*-"
#_(
"exec" "clojure" "-Sdeps" "{:deps {clj-kondo/clj-kondo {:mvn/version \"2020.12.12\"} org.clojure/tools.deps.alpha {:mvn/version \"0.9.857\"} org.slf4j/slf4j-nop {:mvn/version \"1.7.30\"} lambdaisland/deep-diff2 {:mvn/version \"2.0.108\"} juji/editscript {:mvn/version \"0.5.4\"}}}" "-M" "$0" "$@"
)
;; Example usage:
;; api_diff.clj org.clojure/clojure "1.8.0" "1.10.1" > /tmp/diff.txt
(require '[clj-kondo.core :as clj-kondo])
@mauricioszabo
mauricioszabo / core.clj
Created November 5, 2020 17:14
VCR in Clojure
(ns example.core
(:require [vcr-clj.core :as vcr]
[vcr-clj.clj-http :as vcr-http]
[clj-http.client :as client]))
(defn random [n]
{:number (+ 10 (rand-int n))
:username "admin"
:password "Lol, Ima Password!"})
@borkdude
borkdude / script.clj
Last active October 29, 2020 02:23
Spec grep: find usages or reify in clojure.core with two or more interfaces. This idea has been implemented in a library now: https://github.com/borkdude/grasp
;; see https://github.com/borkdude/grasp for a more elaborate implementation
(ns script
(:require [clojure.java.io :as io]
[clojure.pprint :refer [pprint]]
[edamame.core :as e]))
(def clojure-core (slurp (io/resource "clojure/core.clj")))
(def parsed (e/parse-string-all clojure-core
{:all true :auto-resolve '{:current clojure.core}}))
@mauricioszabo
mauricioszabo / with_code.clj
Last active April 18, 2022 04:25
Open Socket REPL on CLR or Clojerl
#Clojerl
./bin/clje \
-e "(do (require 'clojure.core.server) \
(clojure.core.server/start-server \
{:name \"socket-repl\" \
:port 4444 \
:accept 'clojure.main/repl \
:address \"localhost\"}))" -r
#CLR
@edisonywh
edisonywh / pre-commit
Last active April 15, 2024 22:58
Run Rubocop in Git's pre-commit hook
```
#!/bin/sh
echo "\nRunning rubocop 🚓 💨 💨 💨\n"
declare -a ERRORS=()
for file in $(git diff --cached --name-only | grep -E '.rb')
do
ERRORS+=("$(rubocop $file | grep -e 'C:' -e 'E:')")
done
@levand
levand / data-modeling.md
Last active January 1, 2025 10:49
Advice about data modeling in Clojure

Since it has come up a few times, I thought I’d write up some of the basic ideas around domain modeling in Clojure, and how they relate to keyword names and Specs. Firmly grasping these concepts will help us all write code that is simpler, cleaner, and easier to understand.

Clojure is a data-oriented language: we’re all familiar with maps, vectors, sets, keywords, etc. However, while data is good, not all data is equally good. It’s still possible to write “bad” data in Clojure.

“Good” data is well defined and easy to read; there is never any ambiguity about what a given data structure represents. Messy data has inconsistent structure, and overloaded keys that can mean different things in different contexts. Good data represents domain entities and a logical model; bad data represents whatever was convenient for the programmer at a given moment. Good data stands on its own, and can be reasoned about without any other knowledge of the codebase; bad data is deeply and tightly coupled to specific generating and

Scaling your API with rate limiters

The following are examples of the four types rate limiters discussed in the accompanying blog post. In the examples below I've used pseudocode-like Ruby, so if you're unfamiliar with Ruby you should be able to easily translate this approach to other languages. Complete examples in Ruby are also provided later in this gist.

In most cases you'll want all these examples to be classes, but I've used simple functions here to keep the code samples brief.

Request rate limiter

This uses a basic token bucket algorithm and relies on the fact that Redis scripts execute atomically. No other operations can run between fetching the count and writing the new count.

WITH
-- write the new values
n(ip,visits,clicks) AS (
VALUES ('192.168.1.1',2,12),
('192.168.1.2',6,18),
('192.168.1.3',3,4)
),
-- update existing rows
upsert AS (
UPDATE page_views o
@zchee
zchee / actionlist.vim
Last active April 14, 2025 23:20
IdeaVim actionlist
--- Actions ---
$Copy <M-C>
$Cut <M-X> <S-Del>
$Delete <Del> <BS> <M-BS>
$LRU
$Paste <M-V>
$Redo <M-S-Z> <A-S-BS>
$SearchWeb <A-S-G>
$SelectAll <M-A>
$Undo <M-Z>