惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

云风的 BLOG
云风的 BLOG
M
MIT News - Artificial intelligence
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V2EX - 技术
V2EX - 技术
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
GbyAI
GbyAI
aimingoo的专栏
aimingoo的专栏
腾讯CDC
C
CERT Recently Published Vulnerability Notes
J
Java Code Geeks
WordPress大学
WordPress大学
博客园 - Franky
V
Vulnerabilities – Threatpost
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
有赞技术团队
有赞技术团队
The Hacker News
The Hacker News
T
The Blog of Author Tim Ferriss
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Martin Fowler
Martin Fowler
Webroot Blog
Webroot Blog
Attack and Defense Labs
Attack and Defense Labs
Google Online Security Blog
Google Online Security Blog
S
Securelist
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Troy Hunt's Blog
Scott Helme
Scott Helme
Project Zero
Project Zero
T
Tailwind CSS Blog
The Register - Security
The Register - Security
A
About on SuperTechFans
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
The GitHub Blog
The GitHub Blog
Security Latest
Security Latest
L
LangChain Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
H
Hackread – Cybersecurity News, Data Breaches, AI and More
大猫的无限游戏
大猫的无限游戏
Cloudbric
Cloudbric
S
Security Affairs
博客园 - 叶小钗
Microsoft Security Blog
Microsoft Security Blog
H
Heimdal Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
PCI Perspectives
PCI Perspectives
The Cloudflare Blog
Last Week in AI
Last Week in AI
阮一峰的网络日志
阮一峰的网络日志
AI
AI

Stonecharioteer on Tech

I Traced My Traffic Through a Home Tailscale Exit Node What Was I Reading Last? In Three Not-So-Easy Pieces Dogfooding Is Hard Code blocks in your books, finally GoForGo v0.9.0 Merrilin - We built an app to read books I use a Macbook now Data Structures & Algorithms - Preparing for Interviews Using a local DNS namespace for local service discovery Direction KOllector - Publishing KOReader Highlights gbt: branches touched in the last 24 hours A Soiree into Symbols in Ruby Some Smalltalk about Ruby Loops Ruby Blocks Returning from Ruby Blocks, Procs and Lambdas My Linux Laptop Finally Works: How Claude Helped Me Fix Years of Annoyances TIL: Watchexec - Modern File Watching for Development Workflows A Less Busy Mind GoForGo - Learn Go through live examples Migrating My Old Blog to Hugo with Claude The Qtile Window Manager: A Python-Powered Tiling Experience Read the RFCs that Built the Internet Py-x-Protobuf - Or How I Learned to Stop Worrying and Love Protocol Buffers Python Reverse a List New Beginnings Leaving ChainSafe Systems Screen Lock for Cinnamon Desktop using Zenity and Terminal Commands Crews Not Teams A System for Getting Better at LeetCode So Far So Rust Retrying HTTP Requests with Rust A Primer on Control Charts Learning Rust Explicit is Better than Implicit: Rust for Pythonistas Using Custom Delimiters in Jinja Templates TIL: Creating Fixed Length Iterables in Python Documentation Without Assumption Vagrant Python - A Reflection in 2022 Learning Golang No, A Virtual Machine Is Not Enough: Why Developers Need Native Linux Empathy in Tech For Those Who Came in Late A Weekend With PostgreSQL TIL: Gooey and Python Fire for Quick GUIs and CLIs TIL: 2ality - Dr. Axel Rauschmayer's JavaScript Blog TIL: MassDNS - High-Performance Bulk DNS Lookups TIL: Matomo Analytics, Google Tech Writing, Memory Programming, and NES TV Signals TIL: MontyDB - MongoDB Implemented in Python Returning to the Craft of Programming TIL: CPUFetch, OneFetch, and Learn CSS TIL: DNS Performance Testing and Pi-hole with Unbound TIL: Eli Bendersky's Blog, Awesome By Example, NoCoDB, and Martin Kleppmann TIL: CRDTs, Extreme HTTP Performance, and BYTEPATH Game TIL: AutoInvent, ASGI, Python Packaging, RAPIDS GPU Computing, and FlaskCon TIL: MangaDesk - Terminal Client for MangaDex TIL: McFly - Smart Shell History Search TIL: Siege Load Testing and Awesome FastAPI Resources TIL: Ventoy Bootable USB and Justniffer Network Analysis TIL: CLI Code Review, Git Split Diffs, and Internal Combustion Engine TIL: Benford's Law, Web Security Headers, Event Sourcing, and Mozilla Security Guidelines How to Write Documentation - The README.md File The Importance of Documentation TIL: NNgroup UX Research, SponsorBlock, and Labella Python Library TIL: The Little Book of Rust Macros and Rust Performance Book TIL: Git-Bug Distributed Issue Tracker and Omni Kubernetes Monitoring TIL: Zellij - Modern Terminal Multiplexer TIL: How Discord Handles 2.5 Million Concurrent Voice Users TIL: Volumio - The Audiophile Music Player TIL: Areopagitica - Milton's Defense of Free Speech TIL: Fast Node Manager, Zoxide Smart CD, Technical Writing, PyO3, and Qubes OS TIL: Slurm Workload Manager for HPC Clusters TIL: Data Visualization Guide and Oso Authorization Academy TIL: CORS Deep Dive, Piku Tiny PaaS, Rust Strings, and Deno Standard Library TIL: Raspberry Pi OS Development, Vim Beginner Guide, Password Management, and QueryBook TIL: uBlock Origin Performance Optimization on Firefox TIL: Breaking PostgreSQL at Scale and LeetCode Problem Patterns TIL: Awesome Tmux Resources for Terminal Multiplexing TIL: Grit - A Multitree-Based Personal Task Manager TIL: Lens 4.2 Kubernetes IDE, Shell Scripting Guide, and Dark HTTP Server Do The Job You Hate So You Won't Hate The Job You Love TIL: Innernet VPN Solution and NoteCalc Calculator App TIL: Argo CD for GitOps and Lens Kubernetes IDE TIL: Modern Rust CLI Tools - System Monitoring, HTTP Requests, and DNS TIL: tz - A Time Zone Helper Tool TIL: Distributed Systems Education, Fallacies, and Self-Hosted Internet Archiving TIL: Real-Time Voice Cloning Technology TIL: ChartMuseum for Helm, AMD's Corporate Journey, and Kubernetes Pod Scaling TIL: Docker and Kubernetes Tools - Whaler, Descheduler, and Dive TIL: Post-Mortem Collection, Terminal Plotting, and Technical Twitter TIL: Dark Mode Toggle Web Component by Google Chrome Labs TIL: Python eval(), exec(), and compile() Functions TIL: Camelot PDF Tables, PostgreSQL Row Level Security, Zerodha Varsity, and Write Yourself a Git TIL: fuser Command for Process and File Investigation TIL: i Hate Regex - The Ultimate Regex Cheat Sheet TIL: Dolt - Git for Data and Database Version Control TIL: x86 Assembly Programming and SafeEyes Break Reminder TIL: Comprehensive Distributed Systems Reading List TIL: Cosmopolitan C Library, Distributed Systems Book, High Performance Browser Networking, and Rust Roguelike Tutorial
Ruby Blocks
2025-10-14 · via Stonecharioteer on Tech

I think I’m really starting to get Ruby. At least I can read Ruby and tell you what’s happening.

I haven’t read a single tutorial on RSpec, the testing framework we use at Chatwoot for the Rails backend. I didn’t want to spend too much time in tutorial hell, and I’m sure that I should read more about it soon.

I’ve written about Ruby blocks before, but I think it bears repeating. This is a method call with a block as an input.

1
2
3
perform "input_value" do
  puts "I'll get called with that function"
end

Don’t worry about how the function is implemented for now. I’m hand-waving this so that you can notice something.

This is also a method call with a block as an input.

1
it("can do something") { puts "The cake is a lie" }

But here’s something else that’s a method call with a block as an input.

In lib/calculator.rb:

1
2
3
4
5
class Calculator
  def add(a, b)
    a + b
  end
end

In spec/calculator_spec.rb:

1
2
3
4
5
6
7
8
require_relative "../lib/calculator"

RSpec.describe Calculator do
  it "adds two numbers" do
    calc = Calculator.new
    expect(calc.add(2, 3)).to eq(5)
  end
end

The highlighted lines include a method call to it with a block.

Look at that again. It’s a method call.

That is crazy. It is so sublime that I can’t explain how excited this makes me. If I have to teach Ruby to a Pythonista I’d ask them to ensure they see what this is. Until you grok this, it won’t matter how much you try to understand Ruby. Ruby’s readability comes from this feature. I’m still not sold on RSpec though, but I am open to learning it because it is, ultimately, Ruby.

Block Magic

Let’s really see what you can do with blocks.

Building Your Own Language

1
2
3
4
5
6
7
3.times do
  puts "Hello"
end

5.times { puts "World" }

10.downto(1) { |i| puts i }

These are all method calls on integers. times is a method. downto is a method. And every method takes blocks.

But we can also take this to the monke.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Integer
  def seconds
    self
  end
  def minutes
    self * 60
  end
  def from_now
    Time.now + self
  end
end

meeting_time = 30.minutes.from_now
puts "Meeting is in 30 minutes: #{meeting_time}"

That line is readable, not because Ruby is magically more readable than other languages, but because we’re daisy-chaining methods we implemented on the built-in type. We gave Integer wings.

We created a mini language that looks like it somehow isn’t Ruby but, sweet God in Vaikuntha, it really is.

Resource Management

In Python I’m used to doing this.

1
2
3
with open("data.txt", "w") as file:
  file.write("This is some data\n")
  file.write("This is some more data\n")

But you’d be surprised how much production code is in the wild that doesn’t use this. You should be writing it like this in Python, but with is a language keyword in Python.

What would I do in Ruby?

1
2
3
4
File.open("data.txt", "w") do |file|
  file.puts "This is some data"
  file.puts "This is some more data"
end

File.open is a regular old Ruby method. It takes block. THEY ALL TAKE BLOCKS.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def with_timer(name)
  start_time = Time.now
  yield
  end_time = Time.now
  puts "#{name} took #{end_time - start_time} seconds"
end

with_timer("Database query") do
  # Some expensive operation
  sleep(2)
end

That just added a neat side-effect to the database operation.

Building a DSL

Now let’s really turn things up.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class TodoList
  def initialize
    @tasks = []
  end

  def task(description, &block)
    task_obj = Task.new(description)
    task_obj.instance_eval(&block) if block
    @tasks << task_obj
  end

  def show
    @tasks.each { |t| puts t}
  end
end

class Task
  attr_accessor :priority, :due_date, :description

  def initialize(description)
    @description = description
  end

  def priority(level)
    @priority = level
  end

  def due(date)
    @due_date = date
  end

  def to_s
    "#{@description} (Priority: #{@priority}, Due: #{@due_date})"
  end
end


# let's use this
def todo(&block)
  list = TodoList.new
  list.instance_eval(&block)
  list
end

my_todos = todo do
  task "Write a blog post" do
    priority "high"
    due "2025-10-15"
  end

  task "Review PR" do
    priority "medium"
    due "2025-10-14"
  end
end

my_todos.show

Just stop reading and look at that syntax.

I had a problem when I first tried learning Ruby in 2021. I had tried, because I was trying to just learn a new programming language (as one should definitely do annually), and I was a little gob-smacked because I didn’t understand the config.rb file from Rails. It had a bunch of things like this.

It looked like a damned configuration file.

Django tries to do this with the settings.py file, but it doesn’t succeed.

This is exactly why Rails routing looks like this.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Rails.application.routes.draw do
  resources :users do
    member do
      get :profile
      post :activate
    end
  end

  namespace :admin do
    resources :posts
  end
end

That’s not something special from Rails. That’s just a bunch of Ruby methods taking blocks! The draw, resources, member, namespace, they’re all just regular methods.

All of this looked like some magical DSL to me. But it was not. It was just regular old Ruby.

Custom Control Flow

Okay let’s make our own unless or if syntax. Just because I’m feeling like it.

1
2
3
4
5
6
7
8
def only_on_weekdays
  yield unless [0, 6].include?(Time.now.wday)
end

only_on_weekdays do
  puts "Let's get to work!"

end

Or maybe a retry function?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def with_retry(max_attempts: 3)
  attempts = 0
  begin
    attempts += 1
    yield
  rescue StandardError => e
    if attempts < max_attempts
      puts "Attempt #{attempts} failed, retrying..."
      retry
    else
      puts "Max attempts reached, giving up"
      raise e
    end
  end
end

with_retry(max_attempts: 3) do
  # some unreliable API

  puts "Attempting connection..."
  raise "Connection failed" if rand > 0.7
  puts "Success!"
end

Putting this all together

1
2
3
(1..5).select { |n| n.even? }
  .map { |n| n * 2 }
  .reduce(0) { |sum, n| sum + n }

Each and every one of those was a method call that took a block!

It’s all a block. Once I saw this pattern, I could not unsee it!

And why would I want to unsee it? It’s beautiful. It sparkles, damn it.

The Real Magic

The magic isn’t just that you can do this. It’s that Ruby’s syntax makes it so natural that blocks become invisible. When you write 5.times { puts “Hello” }, you don’t think “I’m calling the times method and passing it a block.” You think “I’m doing something 5 times.” You read RSpec code and think “Yeah, that reads like English.”

That’s the genius of Ruby. The language gets out of your way and lets you think about the problem, not the syntax.