{"id":10033,"date":"2025-10-18T19:04:40","date_gmt":"2025-10-18T19:04:40","guid":{"rendered":"https:\/\/pokecon.jp\/job\/?p=10033"},"modified":"2025-10-18T19:04:40","modified_gmt":"2025-10-18T19:04:40","slug":"ruby-blocks-stonecharioteer-on-tech","status":"publish","type":"post","link":"https:\/\/pokecon.jp\/job\/10033\/","title":{"rendered":"Ruby Blocks | Stonecharioteer on Tech"},"content":{"rendered":"\n<\/p>\n<div>\n<p>I think I\u2019m really starting to <em>get<\/em> Ruby. At least I can read Ruby and tell you what\u2019s happening.<\/p>\n<p>I haven\u2019t read a single tutorial on RSpec, the testing framework we use at<br \/>\nChatwoot for the Rails backend. I didn\u2019t want to spend too much time in<br \/>\ntutorial hell, and I\u2019m sure that I <em>should<\/em> read more about it soon.<\/p>\n<p>I\u2019ve written about Ruby blocks <a target=\"_blank\" href=\"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-block-return\/\">before<\/a>, but I think it bears repeating.<br \/>\nThis is a method call with a block as an input.<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\">1\n<\/span><span class=\"lnt\">2\n<\/span><span class=\"lnt\">3\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"n\">perform<\/span> <span class=\"s2\">\"input_value\"<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"nb\">puts<\/span> <span class=\"s2\">\"I'll get called with that function\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>Don\u2019t worry about how the function is <em>implemented<\/em> for now. I\u2019m hand-waving this so that you can<br \/>\nnotice something.<\/p>\n<p>This is also a method call with a block as an input.<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\">1\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"n\">it<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"can do something\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"nb\">puts<\/span> <span class=\"s2\">\"The cake is a lie\"<\/span> <span class=\"p\">}<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>But here\u2019s something else that\u2019s a method call with a block as an input.<\/p>\n<p>In <code>lib\/calculator.rb<\/code>:<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\">1\n<\/span><span class=\"lnt\">2\n<\/span><span class=\"lnt\">3\n<\/span><span class=\"lnt\">4\n<\/span><span class=\"lnt\">5\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"k\">class<\/span> <span class=\"nc\">Calculator<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def<\/span> <span class=\"nf\">add<\/span><span class=\"p\">(<\/span><span class=\"n\">a<\/span><span class=\"p\">,<\/span> <span class=\"n\">b<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">a<\/span> <span class=\"o\">+<\/span> <span class=\"n\">b<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>In <code>spec\/calculator_spec.rb<\/code>:<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\">1\n<\/span><span class=\"lnt\">2\n<\/span><span class=\"lnt\">3\n<\/span><span class=\"hl\"><span class=\"lnt\">4\n<\/span><\/span><span class=\"hl\"><span class=\"lnt\">5\n<\/span><\/span><span class=\"hl\"><span class=\"lnt\">6\n<\/span><\/span><span class=\"hl\"><span class=\"lnt\">7\n<\/span><\/span><span class=\"lnt\">8\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"n\">require_relative<\/span> <span class=\"s2\">\"..\/lib\/calculator\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"no\">RSpec<\/span><span class=\"o\">.<\/span><span class=\"n\">describe<\/span> <span class=\"no\">Calculator<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line hl\"><span class=\"cl\">  <span class=\"n\">it<\/span> <span class=\"s2\">\"adds two numbers\"<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line hl\"><span class=\"cl\">    <span class=\"n\">calc<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Calculator<\/span><span class=\"o\">.<\/span><span class=\"n\">new<\/span>\n<\/span><\/span><span class=\"line hl\"><span class=\"cl\">    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">calc<\/span><span class=\"o\">.<\/span><span class=\"n\">add<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">3<\/span><span class=\"p\">))<\/span><span class=\"o\">.<\/span><span class=\"n\">to<\/span> <span class=\"n\">eq<\/span><span class=\"p\">(<\/span><span class=\"mi\">5<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line hl\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>The highlighted lines include a method call to <code>it<\/code> with a block.<\/p>\n<p>Look at that again. It\u2019s a <em>method<\/em> call.<\/p>\n<p>That is crazy. It is so sublime that I can\u2019t explain how excited this makes me.<br \/>\nIf I have to teach <a target=\"_blank\" href=\"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby\/\">Ruby to a Pythonista<\/a> I\u2019d ask them<br \/>\nto ensure they <em>see<\/em> what this is. Until you grok this, it won\u2019t matter how<br \/>\nmuch you try to understand Ruby. Ruby\u2019s readability comes from this feature.<br \/>\nI\u2019m still not sold on RSpec though, but I <em>am<\/em> open to learning it because it<br \/>\nis, ultimately, Ruby.<\/p>\n<h2 id=\"block-magic\">Block Magic<a target=\"_blank\" hidden=\"\" class=\"anchor\" aria-hidden=\"true\" href=\"#block-magic\">#<\/a><\/h2>\n<p>Let\u2019s <em>really<\/em> see what you can do with blocks.<\/p>\n<h3 id=\"building-your-own-language\">Building Your Own Language<a target=\"_blank\" hidden=\"\" class=\"anchor\" aria-hidden=\"true\" href=\"#building-your-own-language\">#<\/a><\/h3>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\">1\n<\/span><span class=\"lnt\">2\n<\/span><span class=\"lnt\">3\n<\/span><span class=\"lnt\">4\n<\/span><span class=\"lnt\">5\n<\/span><span class=\"lnt\">6\n<\/span><span class=\"lnt\">7\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"mi\">3<\/span><span class=\"o\">.<\/span><span class=\"n\">times<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"nb\">puts<\/span> <span class=\"s2\">\"Hello\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"mi\">5<\/span><span class=\"o\">.<\/span><span class=\"n\">times<\/span> <span class=\"p\">{<\/span> <span class=\"nb\">puts<\/span> <span class=\"s2\">\"World\"<\/span> <span class=\"p\">}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"mi\">10<\/span><span class=\"o\">.<\/span><span class=\"n\">downto<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"o\">|<\/span><span class=\"n\">i<\/span><span class=\"o\">|<\/span> <span class=\"nb\">puts<\/span> <span class=\"n\">i<\/span> <span class=\"p\">}<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>These are <em>all<\/em> method calls on <em>integers<\/em>. <code>times<\/code> is a method. <code>downto<\/code> is a method. And every<br \/>\nmethod takes blocks.<\/p>\n<p>But we can also take this to the monke.<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\"> 1\n<\/span><span class=\"lnt\"> 2\n<\/span><span class=\"lnt\"> 3\n<\/span><span class=\"lnt\"> 4\n<\/span><span class=\"lnt\"> 5\n<\/span><span class=\"lnt\"> 6\n<\/span><span class=\"lnt\"> 7\n<\/span><span class=\"lnt\"> 8\n<\/span><span class=\"lnt\"> 9\n<\/span><span class=\"lnt\">10\n<\/span><span class=\"lnt\">11\n<\/span><span class=\"lnt\">12\n<\/span><span class=\"lnt\">13\n<\/span><span class=\"lnt\">14\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"k\">class<\/span> <span class=\"nc\">Integer<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def<\/span> <span class=\"nf\">seconds<\/span> \n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nb\">self<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def<\/span> <span class=\"nf\">minutes<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nb\">self<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">60<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def<\/span> <span class=\"nf\">from_now<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"no\">Time<\/span><span class=\"o\">.<\/span><span class=\"n\">now<\/span> <span class=\"o\">+<\/span> <span class=\"nb\">self<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"n\">meeting_time<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">30<\/span><span class=\"o\">.<\/span><span class=\"n\">minutes<\/span><span class=\"o\">.<\/span><span class=\"n\">from_now<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"nb\">puts<\/span> <span class=\"s2\">\"Meeting is in 30 minutes: <\/span><span class=\"si\">#{<\/span><span class=\"n\">meeting_time<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>That line is <em>readable<\/em>, not because Ruby is magically more readable than other languages,<br \/>\nbut because we\u2019re daisy-chaining methods we implemented <em>on the built-in type<\/em>. We gave <code>Integer<\/code><br \/>\nwings.<\/p>\n<p>We created a mini language that looks like it somehow isn\u2019t Ruby but, sweet God in Vaikuntha, it <em>really<\/em><br \/>\nis.<\/p>\n<h3 id=\"resource-management\">Resource Management<a target=\"_blank\" hidden=\"\" class=\"anchor\" aria-hidden=\"true\" href=\"#resource-management\">#<\/a><\/h3>\n<p>In Python I\u2019m used to doing this.<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\">1\n<\/span><span class=\"lnt\">2\n<\/span><span class=\"lnt\">3\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-python\" data-lang=\"python\"><span class=\"line\"><span class=\"cl\"><span class=\"k\">with<\/span> <span class=\"nb\">open<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"data.txt\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"w\"<\/span><span class=\"p\">)<\/span> <span class=\"k\">as<\/span> <span class=\"n\">file<\/span><span class=\"p\">:<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">file<\/span><span class=\"o\">.<\/span><span class=\"n\">write<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"This is some data<\/span><span class=\"se\">\\n<\/span><span class=\"s2\">\"<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">file<\/span><span class=\"o\">.<\/span><span class=\"n\">write<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"This is some more data<\/span><span class=\"se\">\\n<\/span><span class=\"s2\">\"<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>But you\u2019d be surprised <em>how much production code<\/em> is in the wild that doesn\u2019t use this.<br \/>\nYou <em>should<\/em> be writing it like this in Python, but <code>with<\/code> is a language keyword in Python.<\/p>\n<p>What would I do in Ruby?<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\">1\n<\/span><span class=\"lnt\">2\n<\/span><span class=\"lnt\">3\n<\/span><span class=\"lnt\">4\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"no\">File<\/span><span class=\"o\">.<\/span><span class=\"n\">open<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"data.txt\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"w\"<\/span><span class=\"p\">)<\/span> <span class=\"k\">do<\/span> <span class=\"o\">|<\/span><span class=\"n\">file<\/span><span class=\"o\">|<\/span> \n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">file<\/span><span class=\"o\">.<\/span><span class=\"n\">puts<\/span> <span class=\"s2\">\"This is some data\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">file<\/span><span class=\"o\">.<\/span><span class=\"n\">puts<\/span> <span class=\"s2\">\"This is some more data\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p><code>File.open<\/code> is a regular old Ruby method. It takes block. <em>THEY ALL TAKE BLOCKS<\/em>.<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\"> 1\n<\/span><span class=\"lnt\"> 2\n<\/span><span class=\"lnt\"> 3\n<\/span><span class=\"lnt\"> 4\n<\/span><span class=\"lnt\"> 5\n<\/span><span class=\"lnt\"> 6\n<\/span><span class=\"lnt\"> 7\n<\/span><span class=\"lnt\"> 8\n<\/span><span class=\"lnt\"> 9\n<\/span><span class=\"lnt\">10\n<\/span><span class=\"lnt\">11\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"k\">def<\/span> <span class=\"nf\">with_timer<\/span><span class=\"p\">(<\/span><span class=\"nb\">name<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">start_time<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Time<\/span><span class=\"o\">.<\/span><span class=\"n\">now<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">yield<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">end_time<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Time<\/span><span class=\"o\">.<\/span><span class=\"n\">now<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"nb\">puts<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"nb\">name<\/span><span class=\"si\">}<\/span><span class=\"s2\"> took <\/span><span class=\"si\">#{<\/span><span class=\"n\">end_time<\/span> <span class=\"o\">-<\/span> <span class=\"n\">start_time<\/span><span class=\"si\">}<\/span><span class=\"s2\"> seconds\"<\/span> \n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"n\">with_timer<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"Database query\"<\/span><span class=\"p\">)<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"c1\"># Some expensive operation<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"nb\">sleep<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>That just added a neat side-effect to the database operation.<\/p>\n<h3 id=\"building-a-dsl\">Building a DSL<a target=\"_blank\" hidden=\"\" class=\"anchor\" aria-hidden=\"true\" href=\"#building-a-dsl\">#<\/a><\/h3>\n<p>Now let\u2019s really turn things up.<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\"> 1\n<\/span><span class=\"lnt\"> 2\n<\/span><span class=\"lnt\"> 3\n<\/span><span class=\"lnt\"> 4\n<\/span><span class=\"lnt\"> 5\n<\/span><span class=\"lnt\"> 6\n<\/span><span class=\"lnt\"> 7\n<\/span><span class=\"lnt\"> 8\n<\/span><span class=\"lnt\"> 9\n<\/span><span class=\"lnt\">10\n<\/span><span class=\"lnt\">11\n<\/span><span class=\"lnt\">12\n<\/span><span class=\"lnt\">13\n<\/span><span class=\"lnt\">14\n<\/span><span class=\"lnt\">15\n<\/span><span class=\"lnt\">16\n<\/span><span class=\"lnt\">17\n<\/span><span class=\"lnt\">18\n<\/span><span class=\"lnt\">19\n<\/span><span class=\"lnt\">20\n<\/span><span class=\"lnt\">21\n<\/span><span class=\"lnt\">22\n<\/span><span class=\"lnt\">23\n<\/span><span class=\"lnt\">24\n<\/span><span class=\"lnt\">25\n<\/span><span class=\"lnt\">26\n<\/span><span class=\"lnt\">27\n<\/span><span class=\"lnt\">28\n<\/span><span class=\"lnt\">29\n<\/span><span class=\"lnt\">30\n<\/span><span class=\"lnt\">31\n<\/span><span class=\"lnt\">32\n<\/span><span class=\"lnt\">33\n<\/span><span class=\"lnt\">34\n<\/span><span class=\"lnt\">35\n<\/span><span class=\"lnt\">36\n<\/span><span class=\"lnt\">37\n<\/span><span class=\"lnt\">38\n<\/span><span class=\"lnt\">39\n<\/span><span class=\"lnt\">40\n<\/span><span class=\"lnt\">41\n<\/span><span class=\"lnt\">42\n<\/span><span class=\"lnt\">43\n<\/span><span class=\"lnt\">44\n<\/span><span class=\"lnt\">45\n<\/span><span class=\"lnt\">46\n<\/span><span class=\"lnt\">47\n<\/span><span class=\"lnt\">48\n<\/span><span class=\"lnt\">49\n<\/span><span class=\"lnt\">50\n<\/span><span class=\"lnt\">51\n<\/span><span class=\"lnt\">52\n<\/span><span class=\"lnt\">53\n<\/span><span class=\"lnt\">54\n<\/span><span class=\"lnt\">55\n<\/span><span class=\"lnt\">56\n<\/span><span class=\"lnt\">57\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"k\">class<\/span> <span class=\"nc\">TodoList<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def<\/span> <span class=\"nf\">initialize<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"vi\">@tasks<\/span> <span class=\"o\">=<\/span> <span class=\"o\">[]<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def<\/span> <span class=\"nf\">task<\/span><span class=\"p\">(<\/span><span class=\"n\">description<\/span><span class=\"p\">,<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">block<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">task_obj<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Task<\/span><span class=\"o\">.<\/span><span class=\"n\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">description<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">task_obj<\/span><span class=\"o\">.<\/span><span class=\"n\">instance_eval<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">block<\/span><span class=\"p\">)<\/span> <span class=\"k\">if<\/span> <span class=\"n\">block<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"vi\">@tasks<\/span> <span class=\"o\"> <span class=\"n\">task_obj<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def<\/span> <span class=\"nf\">show<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"vi\">@tasks<\/span><span class=\"o\">.<\/span><span class=\"n\">each<\/span> <span class=\"p\">{<\/span> <span class=\"o\">|<\/span><span class=\"n\">t<\/span><span class=\"o\">|<\/span> <span class=\"nb\">puts<\/span> <span class=\"n\">t<\/span><span class=\"p\">}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">class<\/span> <span class=\"nc\">Task<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"kp\">attr_accessor<\/span> <span class=\"ss\">:priority<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:due_date<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:description<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def<\/span> <span class=\"nf\">initialize<\/span><span class=\"p\">(<\/span><span class=\"n\">description<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"vi\">@description<\/span> <span class=\"o\">=<\/span> <span class=\"n\">description<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def<\/span> <span class=\"nf\">priority<\/span><span class=\"p\">(<\/span><span class=\"n\">level<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"vi\">@priority<\/span> <span class=\"o\">=<\/span> <span class=\"n\">level<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def<\/span> <span class=\"nf\">due<\/span><span class=\"p\">(<\/span><span class=\"n\">date<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"vi\">@due_date<\/span> <span class=\"o\">=<\/span> <span class=\"n\">date<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def<\/span> <span class=\"nf\">to_s<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"vi\">@description<\/span><span class=\"si\">}<\/span><span class=\"s2\"> (Priority: <\/span><span class=\"si\">#{<\/span><span class=\"vi\">@priority<\/span><span class=\"si\">}<\/span><span class=\"s2\">, Due: <\/span><span class=\"si\">#{<\/span><span class=\"vi\">@due_date<\/span><span class=\"si\">}<\/span><span class=\"s2\">)\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"c1\"># let's use this<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">def<\/span> <span class=\"nf\">todo<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">block<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">list<\/span> <span class=\"o\">=<\/span> <span class=\"no\">TodoList<\/span><span class=\"o\">.<\/span><span class=\"n\">new<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">list<\/span><span class=\"o\">.<\/span><span class=\"n\">instance_eval<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">block<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">list<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"n\">my_todos<\/span> <span class=\"o\">=<\/span> <span class=\"n\">todo<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">task<\/span> <span class=\"s2\">\"Write a blog post\"<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">priority<\/span> <span class=\"s2\">\"high\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">due<\/span> <span class=\"s2\">\"2025-10-15\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  \n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">task<\/span> <span class=\"s2\">\"Review PR\"<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">priority<\/span> <span class=\"s2\">\"medium\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">due<\/span> <span class=\"s2\">\"2025-10-14\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"n\">my_todos<\/span><span class=\"o\">.<\/span><span class=\"n\">show<\/span>\n<\/span><\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>Just stop reading and look at that syntax.<\/p>\n<p>I had a problem when I first tried learning Ruby in 2021. I had tried, because I was trying to just<br \/>\nlearn a new programming language (as one should definitely do annually), and I was a little gob-smacked<br \/>\nbecause I didn\u2019t understand the <code>config.rb<\/code> file from Rails. It had a bunch of things like this.<\/p>\n<p>It looked like a damned configuration file.<\/p>\n<p>Django <em>tries<\/em> to do this with the <code>settings.py<\/code> file, but it doesn\u2019t succeed.<\/p>\n<p>This is <em>exactly<\/em> why Rails routing looks like this.<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\"> 1\n<\/span><span class=\"lnt\"> 2\n<\/span><span class=\"lnt\"> 3\n<\/span><span class=\"lnt\"> 4\n<\/span><span class=\"lnt\"> 5\n<\/span><span class=\"lnt\"> 6\n<\/span><span class=\"lnt\"> 7\n<\/span><span class=\"lnt\"> 8\n<\/span><span class=\"lnt\"> 9\n<\/span><span class=\"lnt\">10\n<\/span><span class=\"lnt\">11\n<\/span><span class=\"lnt\">12\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"no\">Rails<\/span><span class=\"o\">.<\/span><span class=\"n\">application<\/span><span class=\"o\">.<\/span><span class=\"n\">routes<\/span><span class=\"o\">.<\/span><span class=\"n\">draw<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">resources<\/span> <span class=\"ss\">:users<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">member<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"n\">get<\/span> <span class=\"ss\">:profile<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"n\">post<\/span> <span class=\"ss\">:activate<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">namespace<\/span> <span class=\"ss\">:admin<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">resources<\/span> <span class=\"ss\">:posts<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>That\u2019s not something special from Rails. That\u2019s just a bunch of <em>Ruby methods taking blocks!<\/em> The <code>draw<\/code>, <code>resources<\/code>, <code>member<\/code>, <code>namespace<\/code>, they\u2019re <em>all just regular methods.<\/em><\/p>\n<p>All of this looked like some magical DSL to me. But it was <strong>not<\/strong>. It was just regular old Ruby.<\/p>\n<h3 id=\"custom-control-flow\">Custom Control Flow<a target=\"_blank\" hidden=\"\" class=\"anchor\" aria-hidden=\"true\" href=\"#custom-control-flow\">#<\/a><\/h3>\n<p>Okay let\u2019s make our own <code>unless<\/code> or <code>if<\/code> syntax. Just because I\u2019m feeling like it.<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\">1\n<\/span><span class=\"lnt\">2\n<\/span><span class=\"lnt\">3\n<\/span><span class=\"lnt\">4\n<\/span><span class=\"lnt\">5\n<\/span><span class=\"lnt\">6\n<\/span><span class=\"lnt\">7\n<\/span><span class=\"lnt\">8\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"k\">def<\/span> <span class=\"nf\">only_on_weekdays<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">yield<\/span> <span class=\"k\">unless<\/span> <span class=\"o\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">6<\/span><span class=\"o\">].<\/span><span class=\"n\">include?<\/span><span class=\"p\">(<\/span><span class=\"no\">Time<\/span><span class=\"o\">.<\/span><span class=\"n\">now<\/span><span class=\"o\">.<\/span><span class=\"n\">wday<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"n\">only_on_weekdays<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"nb\">puts<\/span> <span class=\"s2\">\"Let's get to work!\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>Or maybe a <code>retry<\/code> function?<\/p>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\"> 1\n<\/span><span class=\"lnt\"> 2\n<\/span><span class=\"lnt\"> 3\n<\/span><span class=\"lnt\"> 4\n<\/span><span class=\"lnt\"> 5\n<\/span><span class=\"lnt\"> 6\n<\/span><span class=\"lnt\"> 7\n<\/span><span class=\"lnt\"> 8\n<\/span><span class=\"lnt\"> 9\n<\/span><span class=\"lnt\">10\n<\/span><span class=\"lnt\">11\n<\/span><span class=\"lnt\">12\n<\/span><span class=\"lnt\">13\n<\/span><span class=\"lnt\">14\n<\/span><span class=\"lnt\">15\n<\/span><span class=\"lnt\">16\n<\/span><span class=\"lnt\">17\n<\/span><span class=\"lnt\">18\n<\/span><span class=\"lnt\">19\n<\/span><span class=\"lnt\">20\n<\/span><span class=\"lnt\">21\n<\/span><span class=\"lnt\">22\n<\/span><span class=\"lnt\">23\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"k\">def<\/span> <span class=\"nf\">with_retry<\/span><span class=\"p\">(<\/span><span class=\"ss\">max_attempts<\/span><span class=\"p\">:<\/span> <span class=\"mi\">3<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">attempts<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">begin<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">attempts<\/span> <span class=\"o\">+=<\/span> <span class=\"mi\">1<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"k\">yield<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">rescue<\/span> <span class=\"no\">StandardError<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"n\">e<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"k\">if<\/span> <span class=\"n\">attempts<\/span> <span class=\"o\"> <span class=\"n\">max_attempts<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nb\">puts<\/span> <span class=\"s2\">\"Attempt <\/span><span class=\"si\">#{<\/span><span class=\"n\">attempts<\/span><span class=\"si\">}<\/span><span class=\"s2\"> failed, retrying...\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"k\">retry<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"k\">else<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nb\">puts<\/span> <span class=\"s2\">\"Max attempts reached, giving up\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"k\">raise<\/span> <span class=\"n\">e<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"n\">with_retry<\/span><span class=\"p\">(<\/span><span class=\"ss\">max_attempts<\/span><span class=\"p\">:<\/span> <span class=\"mi\">3<\/span><span class=\"p\">)<\/span> <span class=\"k\">do<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"c1\"># some unreliable API<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"nb\">puts<\/span> <span class=\"s2\">\"Attempting connection...\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">raise<\/span> <span class=\"s2\">\"Connection failed\"<\/span> <span class=\"k\">if<\/span> <span class=\"nb\">rand<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"o\">.<\/span><span class=\"mi\">7<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"nb\">puts<\/span> <span class=\"s2\">\"Success!\"<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end<\/span>\n<\/span><\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<h3 id=\"putting-this-all-together\">Putting this all together<a target=\"_blank\" hidden=\"\" class=\"anchor\" aria-hidden=\"true\" href=\"#putting-this-all-together\">#<\/a><\/h3>\n<div class=\"highlight\">\n<div class=\"chroma\">\n<div class=\"s_table\"><table class=\"lntable\">\n<tr>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\">1\n<\/span><span class=\"lnt\">2\n<\/span><span class=\"lnt\">3\n<\/span><\/code><\/pre>\n<\/td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"line\"><span class=\"cl\"><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"o\">..<\/span><span class=\"mi\">5<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">select<\/span> <span class=\"p\">{<\/span> <span class=\"o\">|<\/span><span class=\"n\">n<\/span><span class=\"o\">|<\/span> <span class=\"n\">n<\/span><span class=\"o\">.<\/span><span class=\"n\">even?<\/span> <span class=\"p\">}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"o\">.<\/span><span class=\"n\">map<\/span> <span class=\"p\">{<\/span> <span class=\"o\">|<\/span><span class=\"n\">n<\/span><span class=\"o\">|<\/span> <span class=\"n\">n<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">2<\/span> <span class=\"p\">}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"o\">.<\/span><span class=\"n\">reduce<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"o\">|<\/span><span class=\"n\">sum<\/span><span class=\"p\">,<\/span> <span class=\"n\">n<\/span><span class=\"o\">|<\/span> <span class=\"n\">sum<\/span> <span class=\"o\">+<\/span> <span class=\"n\">n<\/span> <span class=\"p\">}<\/span>\n<\/span><\/span><\/code><\/pre>\n<\/td>\n<\/tr>\n<\/table><\/div>\n<\/div>\n<\/div>\n<p>Each and every one of those was a method call <strong>that took a block!<\/strong><\/p>\n<p>It\u2019s all a block. Once I saw this pattern, I could not <em>unsee it!<\/em><\/p>\n<p>And why would I want to unsee it? It\u2019s beautiful. It sparkles, damn it.<\/p>\n<div class=\"admonition tip\">\n<p>\n        <span class=\"admonition-icon\">\ud83d\udca1<\/span><br \/>\n        <span class=\"admonition-text\">The Real Magic<\/span>\n    <\/p>\n<div class=\"admonition-content\">\n<p>The magic isn\u2019t just that you can do this. It\u2019s that Ruby\u2019s syntax makes it so<br \/>\nnatural that blocks become invisible. When you write 5.times { puts \u201cHello\u201d },<br \/>\nyou don\u2019t think \u201cI\u2019m calling the times method and passing it a block.\u201d You<br \/>\nthink \u201cI\u2019m doing something 5 times.\u201d You read RSpec code and think \u201cYeah, that<br \/>\nreads like English.\u201d<\/p>\n<p>That\u2019s the genius of Ruby. The language gets out of your way and lets you think<br \/>\nabout the problem, not the syntax.<\/p>\n<\/p><\/div>\n<\/div><\/div>\n\n<br \/><a href=\"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/\">\u5143\u306e\u8a18\u4e8b\u3092\u78ba\u8a8d\u3059\u308b <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"I think I\u2019m really starting to get Ruby. At least I can read Ruby and tell you what\u2019s happening. I haven\u2019t rea [&hellip;]","protected":false},"author":1,"featured_media":10034,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[],"class_list":["post-10033","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hatena-blog"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Ruby Blocks | Stonecharioteer on Tech - \u30dd\u30b1\u30b3\u30f3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/\" \/>\n<meta property=\"og:locale\" content=\"ja_JP\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ruby Blocks | Stonecharioteer on Tech - \u30dd\u30b1\u30b3\u30f3\" \/>\n<meta property=\"og:description\" content=\"I think I\u2019m really starting to get Ruby. At least I can read Ruby and tell you what\u2019s happening. I haven\u2019t rea [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/\" \/>\n<meta property=\"og:site_name\" content=\"\u30dd\u30b1\u30b3\u30f3\" \/>\n<meta property=\"article:published_time\" content=\"2025-10-18T19:04:40+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/blocks-everywhere.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"1024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"info@pokecon.jp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u57f7\u7b46\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"info@pokecon.jp\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u63a8\u5b9a\u8aad\u307f\u53d6\u308a\u6642\u9593\" \/>\n\t<meta name=\"twitter:data2\" content=\"6\u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/tech.stonecharioteer.com\\\/posts\\\/2025\\\/ruby-blocks\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/10033\\\/\"},\"author\":{\"name\":\"info@pokecon.jp\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\"},\"headline\":\"Ruby Blocks | Stonecharioteer on Tech\",\"datePublished\":\"2025-10-18T19:04:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/10033\\\/\"},\"wordCount\":716,\"image\":{\"@id\":\"https:\\\/\\\/tech.stonecharioteer.com\\\/posts\\\/2025\\\/ruby-blocks\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/blocks-everywhere.png\",\"articleSection\":[\"\u306f\u3066\u306a\u30d6\u30ed\u30b0\"],\"inLanguage\":\"ja\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/10033\\\/\",\"url\":\"https:\\\/\\\/tech.stonecharioteer.com\\\/posts\\\/2025\\\/ruby-blocks\\\/\",\"name\":\"Ruby Blocks | Stonecharioteer on Tech - \u30dd\u30b1\u30b3\u30f3\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/tech.stonecharioteer.com\\\/posts\\\/2025\\\/ruby-blocks\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/tech.stonecharioteer.com\\\/posts\\\/2025\\\/ruby-blocks\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/blocks-everywhere.png\",\"datePublished\":\"2025-10-18T19:04:40+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/tech.stonecharioteer.com\\\/posts\\\/2025\\\/ruby-blocks\\\/#breadcrumb\"},\"inLanguage\":\"ja\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/tech.stonecharioteer.com\\\/posts\\\/2025\\\/ruby-blocks\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ja\",\"@id\":\"https:\\\/\\\/tech.stonecharioteer.com\\\/posts\\\/2025\\\/ruby-blocks\\\/#primaryimage\",\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/blocks-everywhere.png\",\"contentUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/blocks-everywhere.png\",\"width\":1024,\"height\":1024},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/tech.stonecharioteer.com\\\/posts\\\/2025\\\/ruby-blocks\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u30db\u30fc\u30e0\",\"item\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ruby Blocks | Stonecharioteer on Tech\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#website\",\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/\",\"name\":\"\u30dd\u30b1\u30b3\u30f3\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ja\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\",\"name\":\"info@pokecon.jp\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ja\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"caption\":\"info@pokecon.jp\"},\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/author\\\/infopokecon-jp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Ruby Blocks | Stonecharioteer on Tech - \u30dd\u30b1\u30b3\u30f3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/","og_locale":"ja_JP","og_type":"article","og_title":"Ruby Blocks | Stonecharioteer on Tech - \u30dd\u30b1\u30b3\u30f3","og_description":"I think I\u2019m really starting to get Ruby. At least I can read Ruby and tell you what\u2019s happening. I haven\u2019t rea [&hellip;]","og_url":"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/","og_site_name":"\u30dd\u30b1\u30b3\u30f3","article_published_time":"2025-10-18T19:04:40+00:00","og_image":[{"width":1024,"height":1024,"url":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/blocks-everywhere.png","type":"image\/png"}],"author":"info@pokecon.jp","twitter_card":"summary_large_image","twitter_misc":{"\u57f7\u7b46\u8005":"info@pokecon.jp","\u63a8\u5b9a\u8aad\u307f\u53d6\u308a\u6642\u9593":"6\u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/#article","isPartOf":{"@id":"https:\/\/pokecon.jp\/job\/10033\/"},"author":{"name":"info@pokecon.jp","@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997"},"headline":"Ruby Blocks | Stonecharioteer on Tech","datePublished":"2025-10-18T19:04:40+00:00","mainEntityOfPage":{"@id":"https:\/\/pokecon.jp\/job\/10033\/"},"wordCount":716,"image":{"@id":"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/#primaryimage"},"thumbnailUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/blocks-everywhere.png","articleSection":["\u306f\u3066\u306a\u30d6\u30ed\u30b0"],"inLanguage":"ja"},{"@type":"WebPage","@id":"https:\/\/pokecon.jp\/job\/10033\/","url":"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/","name":"Ruby Blocks | Stonecharioteer on Tech - \u30dd\u30b1\u30b3\u30f3","isPartOf":{"@id":"https:\/\/pokecon.jp\/job\/#website"},"primaryImageOfPage":{"@id":"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/#primaryimage"},"image":{"@id":"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/#primaryimage"},"thumbnailUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/blocks-everywhere.png","datePublished":"2025-10-18T19:04:40+00:00","author":{"@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997"},"breadcrumb":{"@id":"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/#breadcrumb"},"inLanguage":"ja","potentialAction":[{"@type":"ReadAction","target":["https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/"]}]},{"@type":"ImageObject","inLanguage":"ja","@id":"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/#primaryimage","url":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/blocks-everywhere.png","contentUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/blocks-everywhere.png","width":1024,"height":1024},{"@type":"BreadcrumbList","@id":"https:\/\/tech.stonecharioteer.com\/posts\/2025\/ruby-blocks\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u30db\u30fc\u30e0","item":"https:\/\/pokecon.jp\/job\/"},{"@type":"ListItem","position":2,"name":"Ruby Blocks | Stonecharioteer on Tech"}]},{"@type":"WebSite","@id":"https:\/\/pokecon.jp\/job\/#website","url":"https:\/\/pokecon.jp\/job\/","name":"\u30dd\u30b1\u30b3\u30f3","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/pokecon.jp\/job\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ja"},{"@type":"Person","@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997","name":"info@pokecon.jp","image":{"@type":"ImageObject","inLanguage":"ja","@id":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","caption":"info@pokecon.jp"},"url":"https:\/\/pokecon.jp\/job\/author\/infopokecon-jp\/"}]}},"_links":{"self":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/10033","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/comments?post=10033"}],"version-history":[{"count":1,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/10033\/revisions"}],"predecessor-version":[{"id":10035,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/10033\/revisions\/10035"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/media\/10034"}],"wp:attachment":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/media?parent=10033"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/categories?post=10033"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/tags?post=10033"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}