<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>aesthetikx.info</title>
    <link>http://aesthetikx.info</link>
    <description>The aesthetikx.info blog</description>
    <language>en</language>
    <lastBuildDate>Tue, 19 May 2026 23:59:00 +0000</lastBuildDate>
    <atom:link href="http://aesthetikx.info/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>What is Date::ITALY?</title>
      <link>http://aesthetikx.info/blog/date_italy.html</link>
      <description>&lt;p&gt;The other day I was perusing a Ruby backtrace and paused as something caught my eye: &lt;code&gt;Date::ITALY&lt;/code&gt;. What could that be?&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;001&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ITALY&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2299161&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Allrighty, not exactly self-explanatory. Upon visiting the documentation for class Date, I was greeted by a few other unusual sounding constants, including &lt;code&gt;ENGLAND&lt;/code&gt;, &lt;code&gt;GREGORIAN&lt;/code&gt;, and &lt;code&gt;JULIAN&lt;/code&gt;. What do the docs have to say about these?&lt;/p&gt;

&lt;p&gt;ENGLAND&lt;br /&gt;
&lt;em&gt;The Julian day number of the day of calendar reform for England and her colonies.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;GREGORIAN&lt;br /&gt;
&lt;em&gt;The Julian day number of the day of calendar reform for the proleptic Gregorian calendar.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ITALY&lt;br /&gt;
&lt;em&gt;The Julian day number of the day of calendar reform for Italy and some catholic countries.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;JULIAN&lt;br /&gt;
&lt;em&gt;The Julian day number of the day of calendar reform for the proleptic Julian calendar.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First of all, I think it is humorous that the Ruby source code mentions &lt;em&gt;England and her colonies&lt;/em&gt; as well as &lt;em&gt;some catholic countries&lt;/em&gt;. Second, I learned the term &lt;a href="https://en.wiktionary.org/wiki/proleptic"&gt;&lt;em&gt;proleptic&lt;/em&gt;&lt;/a&gt;, which refers to extrapolating calendar dates outside the time of their adoption or use. But OK, the question on everyone’s mind – what is a Julian day number? Well, not so fast, because first we have to cover the catholicism part.&lt;/p&gt;

&lt;h2 id="the-gregorian-switchover"&gt;The Gregorian Switchover&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Julian_calendar"&gt;Julian calendar&lt;/a&gt;, established by the eponymous &lt;a href="https://en.wikipedia.org/wiki/Julius_Caesar"&gt;Caesar&lt;/a&gt;, had been cooking along fairly accurately for quite some time. But, it wasn’t perfect, losing a day about every 128 years. By the time of &lt;a href="https://en.wikipedia.org/wiki/Pope_Gregory_XIII"&gt;Pope Gregory XIII&lt;/a&gt; in the 1580s, the date of Easter had unacceptably moved about two weeks towards the Summer. In 1582, the Papal bull &lt;a href="https://en.wikipedia.org/wiki/Inter_gravissimas"&gt;Inter gravissimas&lt;/a&gt; declared that the day following Thursday, 4 October 1582 would be Friday, 15 October 1582. Indeed, Ruby conforms, raising an exception if you attempt to instantiate a date within that ten day period:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;001&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1582&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="ss"&gt;:in&lt;/span&gt; &lt;span class="s1"&gt;'Date#initialize'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;invalid&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and helpfully hops right over them when iterating, like it never happened:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;001&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1582&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;next_day&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Date: 1582-10-15 ((2299161j,0s,0n), +0s,2299161j)&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Wait a moment, where have we seen that number before? Yes, Date::ITALY encodes the Julian day on which Italy switched from the Julian calendar to the Gregorian calendar – Julian day 2,299,161. If you were ever wondering what those weird numbers were in &lt;code&gt;Date#inspect&lt;/code&gt;, those are &lt;a href="https://en.wikipedia.org/wiki/Julian_day"&gt;Julian Day numbers&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="julian-days"&gt;Julian Days&lt;/h2&gt;

&lt;p&gt;Like all good stories, this one starts over six thousand years ago. On a very special Monday, New Year’s day in 4713 BC, at exactly noon UTC, the three most important multi-year cycles of humankind were perfectly synchronized: the 28 year &lt;a href="https://en.wikipedia.org/wiki/Solar_cycle_(calendar)"&gt;solar cycle&lt;/a&gt;, the 19 year &lt;a href="https://en.wikipedia.org/wiki/Metonic_cycle"&gt;lunar cycle&lt;/a&gt;, and of course the 15 year Roman tax collection cycle, commonly referred to as the &lt;a href="https://en.wikipedia.org/wiki/Indiction"&gt;indiction&lt;/a&gt; cycle. Indeed, the Julian day cycle is a period of 28 x 19 x 15 = 7980 years, which will roll over once again in the year 3268 AD.&lt;/p&gt;

&lt;p&gt;Why do we need this? As we saw earlier, there are some ‘gaps’ in the accounting of days in human history. To add to the confusion, not all countries adopted the Gregorian calendar at the same time – England for example, waited until 1752, as the Protestants were hesitant to adopt Catholic innovation (hence, &lt;code&gt;Date::ENGLAND&lt;/code&gt;). Therefore, a sort of ‘universal intermediary’ was required to compute back and forth unambiguously between various calendar systems. Thus a simple count of days from a somewhat arbitrary epoch was created. Literally 1 year after the introduction of the Gregorian calendar, scholar &lt;a href="https://en.wikipedia.org/wiki/Joseph_Justus_Scaliger"&gt;Joseph Scaliger&lt;/a&gt; proposed the Julian Period method. Unbelievably confusingly, this Period was not named for the Julian calendar, or Julius Caesar that &lt;em&gt;it&lt;/em&gt; was named after – it was named after his father &lt;a href="https://en.wikipedia.org/wiki/Julius_Caesar_Scaliger"&gt;Julius Caesar Scaliger&lt;/a&gt;, who was himself named after Julius Caesar. This is not unlike the Caesar salad, famously named after &lt;a href="https://en.wikipedia.org/wiki/Caesar_Cardini"&gt;Caesar Cardini&lt;/a&gt; (famously named after Julius Caesar (whose name is famously actually Gaius.))&lt;/p&gt;

&lt;p&gt;Ok, back to Ruby. We now know that &lt;code&gt;Date::ITALY&lt;/code&gt; and &lt;code&gt;Date::ENGLAND&lt;/code&gt; define the Julian day number that Italy and England respectively adopted the Gregorian calendar. That leaves &lt;code&gt;Date::GREGORIAN&lt;/code&gt; and &lt;code&gt;Date::JULIAN&lt;/code&gt;. I bet you’ll never guess:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;001&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;GREGORIAN&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;Infinity&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;002&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;JULIAN&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Infinity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alrighty, not exactly self-explanatory. To make sense of this, we will have to understand the &lt;code&gt;Date&lt;/code&gt; initializer:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4712&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mday&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ITALY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Two things here: first, the default date is equivalent to &lt;code&gt;Date.jd(0)&lt;/code&gt;. If you have ever wondered why &lt;code&gt;Date.new.to_s&lt;/code&gt; gives &lt;code&gt;"-4712-01-01"&lt;/code&gt;, now you know. Second, the optional &lt;code&gt;start&lt;/code&gt; argument is the ‘start of the Gregorian calendar’, expressed in Julian Days.&lt;/p&gt;

&lt;p&gt;If you were working on a SaaS product in England in the 1700s, you would express &lt;a href="https://en.wikipedia.org/wiki/Isaac_Newton"&gt;Sir Isaac Newton’s&lt;/a&gt; DOB as &lt;code&gt;Date.new(1642, 12, 25, Date::ENGLAND)&lt;/code&gt; rather than &lt;code&gt;Date.new(1643, 1, 4)&lt;/code&gt;. This also means that &lt;code&gt;Date.new(1582, 10, 5, Date::ENGLAND)&lt;/code&gt; does not raise an exception like it does for &lt;code&gt;Date::ITALY&lt;/code&gt;. In English parlance, Isaac’s birthday expressed as 1642/12/25 would be called the ‘old style’, and 1643/1/4 the ‘new style’ date. This is why Ruby’s &lt;code&gt;date_core.c&lt;/code&gt; often mentions &lt;code&gt;os&lt;/code&gt; and &lt;code&gt;ns&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you always want to use the Julian calendar, you could kick the ‘Gregorian switchover’ can infinitely down the road. This is why &lt;code&gt;Date::JULIAN&lt;/code&gt; is &lt;code&gt;Float::INFINITY&lt;/code&gt;. Passing &lt;code&gt;Date::GREGORIAN&lt;/code&gt; (&lt;code&gt;-Float::INFINITY&lt;/code&gt;) implies that the switchover happened ‘infinitely long ago’, or in other words, ‘we have always been using the Gregorian calendar’.&lt;/p&gt;

&lt;p&gt;Because these values are assumed to be Julian Days, you can also provide your own arbitrary values. For example, if you wanted to model dates in Russia, where the Gregorian calendar was adopted on 14 February, 1918, you would:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;001&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1918&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2421639&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;next_day&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Date: 1918-02-14 ((2421639j,0s,0n),+0s,2421639j)&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;God help us if we ever switch to a new calendar system, because a single &lt;code&gt;start&lt;/code&gt; argument won’t cut it anymore!&lt;/p&gt;

&lt;h2 id="closing-thoughts"&gt;Closing Thoughts&lt;/h2&gt;

&lt;p&gt;If you are wondering if Isaac Newton actually was born on Christmas or rather January 4th, well, that is exactly the issue that Gregory XIII was out to solve!&lt;/p&gt;

&lt;p&gt;Because the Julian Period is a synchronization of three other cycles, it is referred to as a &lt;em&gt;tricyclic system&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The indiction cycle may have been chosen as a third cycle because historical records often were linked not to a date but rather an indiction number.&lt;/p&gt;

&lt;p&gt;Contrary to what I said above, it is contested as to whether the Julian Period was originally referring to the Julian calendar or rather named after Joseph’s father.&lt;/p&gt;

&lt;p&gt;Conceptually, you can think of a &lt;code&gt;Date&lt;/code&gt; as a &lt;code&gt;(julian date, gregorian switchover)&lt;/code&gt; tuple, combined with methods that compute answers based on those two values. In the &lt;code&gt;inspect&lt;/code&gt; format of a date, for example &lt;code&gt;#&amp;lt;Date: 1582-10-15 ((2299161j,0s,0n), +0s,2299161j)&amp;gt;&lt;/code&gt;, you are seeing the date expressed as a Julian day number, plus the seconds and nanoseconds of a time component, then a time zone offset, and finally the provided Julian day of the Gregorian switchover. A &lt;code&gt;DateTime&lt;/code&gt; will use the &lt;code&gt;0s, 0ns&lt;/code&gt; portion for the time component.&lt;/p&gt;

&lt;p&gt;Left as an exercise for the reader, there are a few fun methods in &lt;code&gt;class Date&lt;/code&gt; as well:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;#gregorian_leap?&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;#julian_leap?&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;#jisx0301&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;#rfc2822&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;#rfc3339&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="further-reading"&gt;Further Reading&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;https://docs.ruby-lang.org/en/master/language/calendars_rdoc.html#argument-start&lt;/li&gt;
  &lt;li&gt;https://github.com/ruby/ruby/blob/master/ext/date/date_core.c&lt;/li&gt;
  &lt;li&gt;https://quasar.as.utexas.edu/BillInfo/JulianDatesG.html&lt;/li&gt;
  &lt;li&gt;https://en.wikipedia.org/wiki/Julian_day&lt;/li&gt;
&lt;/ul&gt;
</description>
      <guid>http://aesthetikx.info/blog/date_italy.html</guid>
      <pubDate>Mon, 20 Apr 2026 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Safely Adding Columns to Rails Applications</title>
      <link>http://aesthetikx.info/blog/safely_adding_columns_in_rails.html</link>
      <description>&lt;p&gt;ActiveRecord has two behaviors by default that, when combined, can make it challenging to safely add a column to an existing table in high traffic applications.&lt;/p&gt;

&lt;p&gt;First, it leverages a prepared statement cache. This allows the database to reuse queries of the same shape where only variables change, so that the query planner doesn’t have to re-evaluate a SQL statement each time, if only the value &lt;code&gt;3&lt;/code&gt; changes in a query like:&lt;/p&gt;

&lt;div class="language-sql highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When you see something in your logs that looks like&lt;/p&gt;

&lt;div class="language-sql highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;this is Rails using prepared statements.&lt;/p&gt;

&lt;p&gt;Second, by default, all columns from a table are selected (&lt;code&gt;SELECT users.*&lt;/code&gt;), which makes SQL logs smaller (possibly a lot smaller for tables with lots of columns) and is sort of the de facto presumption that your ActiveRecord model always needs all columns on the underlying table.&lt;/p&gt;

&lt;p&gt;With these defaults, if you run a migration that adds a column to an existing table, you may see a sudden blip of &lt;code&gt;PreparedStatementCacheExpired&lt;/code&gt; exceptions. This is because your running application has existing database connections leveraging the prepared statement cache, and because we added a column, the arity or shape of &lt;code&gt;SELECT table.*&lt;/code&gt; has changed, which is unexpected. Rails handles these exceptions to some extent by updating the statement cache, so you may only see one exception per thread or worker (per connection), however, this can still result in some user-facing 500s or retried background jobs, which is not ideal.&lt;/p&gt;

&lt;h2 id="working-around-this-issue"&gt;Working Around This Issue&lt;/h2&gt;

&lt;p&gt;The easiest way to do this historically has been to add an entry to the &lt;code&gt;ignored_columns&lt;/code&gt; array on your model. For example:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ignored_columns&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a_new_setting'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you deploy this version of your application, Rails will no longer select all columns from your table, but rather select each individual column (with the exception of the ignored ones). So, your SQL statement may instead look like &lt;code&gt;SELECT users.id, users.email, users.first_name, users.last_name&lt;/code&gt; anywhere you are using the &lt;code&gt;User&lt;/code&gt; model. Once you have confirmed this version of your application is running in production, you can safely run your migration to add your column, because the prepared statement cache will not be broken by the addition of the new column. After the migration completes, you can deploy another version of your application with the &lt;code&gt;ignored_columns&lt;/code&gt; removed.&lt;/p&gt;

&lt;h2 id="another-option"&gt;Another Option&lt;/h2&gt;

&lt;p&gt;While the above works fine, it can be cumbersome to have a pair of deployments every time you want to add a column with zero downtime (one to add the ignored column entry, and a second to run the migration and remove the ignored column entry). For tables that have frequent additions (perhaps a settings or configuration table), we can instead leverage the relatively recent &lt;code&gt;enumerate_columns_in_select_statements&lt;/code&gt; option. While this can be configured globally, I think it is sufficient to use it sparingly. For example:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Settings&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enumerate_columns_in_select_statements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See &lt;a href="https://api.rubyonrails.org/classes/ActiveRecord/Core.html#method-c-enumerate_columns_in_select_statements"&gt;the documentation&lt;/a&gt; for more details, or &lt;a href="https://github.com/rails/rails/pull/41718"&gt;this pull request&lt;/a&gt; for the original discussion.&lt;/p&gt;
</description>
      <guid>http://aesthetikx.info/blog/safely_adding_columns_in_rails.html</guid>
      <pubDate>Fri, 27 Feb 2026 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>The Cat's Pajamas</title>
      <link>http://aesthetikx.info/blog/the_cats_pajamas.html</link>
      <description>&lt;p&gt;&lt;em&gt;A review of The Cat’s Pajamas by Ray Bradbury&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One down, many to go! This is the first book I finished this year, and because of the format it was a pretty easy read.&lt;/p&gt;

&lt;p&gt;The back of the book says there are twenty-two stories, but by my count there were only twenty? Overall, it was a pretty mixed bag. Originally most of these stories hadn’t previously been published, and I can kind of see why – unlike e.g. the Martian Chronicles, the stories don’t fit a cohesive theme, and some of them, while interesting, seem to have been written just to test a small idea.&lt;/p&gt;

&lt;p&gt;One thing that I did notice, and I didn’t go back to prove this, but I believe every story has either the word Summer, Autumn, or Winter in it – Bradbury often introduces a story with a description including the time of year, which clearly has a nostalgic element to it. Although sometimes repetitive, this occasionally produces some delightful prose, for example:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;He would watch the details of this dying summer, and it would give him much to think of. He would try to understand the summer all the way to the end of it. Autumn rose in a tidal wave, poised over him, ready to drop, suspended.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another good one:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Or a snowball, thrown by some winter-haunted child, soundless in the night, on his way nowhere….&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There wasn’t a lot of Martianchroniclesque Sci-Fi in here, but there was one that I found rather interesting where humans arrive at an alien planet with a very advanced and peaceful alien species. The humans try their best to learn from and fraternize with the species, but despite their best efforts and intentions they are unable to get over the fact that the aliens look like big spiders.&lt;/p&gt;

&lt;p&gt;As usual Bradbury also hits on themes of racism and colonization, in unique ways. In one story, a group of drunk senators gamble away the entire United States at a Native American casino. It’s funny, and well written.&lt;/p&gt;

&lt;p&gt;Overall, this was not my favorite Bradbury collection, but it was worth the read. In some ways, it makes me want to reread Martian Chronicles, but for now I’m going to move on.&lt;/p&gt;
</description>
      <guid>http://aesthetikx.info/blog/the_cats_pajamas.html</guid>
      <pubDate>Mon, 12 Jan 2026 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Books to Read in 2026</title>
      <link>http://aesthetikx.info/blog/books_in_2026.html</link>
      <description>&lt;p&gt;This year, I am going to make a more organized effort to read books. I already read a lot; however, my unstructured approach has me starting lots of books without finishing them. Pair that with my bias for highly technical or otherwise ‘impossible’ reads, and overall I didn’t do a lot of successful reading last year. I’m starting with a list ahead of time, rather than choosing randomly.&lt;/p&gt;

&lt;h2 id="the-cats-pajamas-by-ray-bradbury"&gt;The Cat’s Pajamas by Ray Bradbury&lt;/h2&gt;
&lt;p&gt;I am already a big fan of Ray Bradbury, having really resonated with The Martian Chronicles back in high school. This one is a collection of 22 stories published in 2004, wherein each individual story was written sometime between the mid 1940s through the early 2000s. I think this will be a good starting place because each story is only 10-15 pages.&lt;/p&gt;

&lt;p&gt;Edit: &lt;a href="/blog/the_cats_pajamas.html"&gt;finished&lt;/a&gt; this one.&lt;/p&gt;

&lt;h2 id="game-theory---davis"&gt;Game Theory - Davis&lt;/h2&gt;
&lt;p&gt;I don’t know anything about this, other than my surfaise knowledge of game theory from that one movie. I’m not sure if this is a cornerstone work in the area, or just a one-off, but it looked interesting and not overly-long.&lt;/p&gt;

&lt;h2 id="the-three-stigmata-of-palmer-eldritch---philip-k-dick"&gt;The Three Stigmata of Palmer Eldritch - Philip K Dick&lt;/h2&gt;
&lt;p&gt;Similar to Bradbury, I have been a fan of PKD for a while, because the movie adaptations were the sort of thing I liked to watch with my friends in high school (Bladerunner, a Scanner Darkly, Minority Report, etc.) This particular one I hadn’t heard of before, so I thought it would be a good reintroduction. I considered VALIS, but it is part of a trilogy and seems a bit much for now, given the synopsis.&lt;/p&gt;

&lt;h2 id="the-last-blackrobe-of-indiana-and-the-potawatomi-trail-of-death---john-william-mcmullen"&gt;The Last Blackrobe of Indiana and the Potawatomi Trail of Death - John William McMullen&lt;/h2&gt;
&lt;p&gt;This one is currently on loan to me from someone that lives near the area covered in the book. It spans French and American history in the 1800s, as well as Catholic and native American culture, so it should be interesting. It seems to be written in a story driven way rather than purely academic, though it is based on real accounts.&lt;/p&gt;

&lt;h2 id="the-name-of-the-rose---umberto-eco"&gt;The Name of the Rose - Umberto Eco&lt;/h2&gt;
&lt;p&gt;Really I want to read Foccult’s Pendulum, because that keeps coming up as a reccomendation. However, my goal is to one day read that in the original Italian – perhaps too lofty of a goal. Regardless, I am going to start at the beginning of Ecos’ bibliography, even though I have already seen the film adaptation of this one. The film adaptation is quite enjoyable, so I guess I already know what happens, but I can compare the book to the movie in any case.&lt;/p&gt;

&lt;h2 id="inferno---dante"&gt;Inferno - Dante&lt;/h2&gt;
&lt;p&gt;This is something that I have already been reading, but I want to continue this year.&lt;/p&gt;

&lt;h2 id="the-one-year-chronological-bible"&gt;The One Year Chronological Bible&lt;/h2&gt;
&lt;p&gt;I find the bible fascinating for a variety of reasons, but I have never read it in its entirety. This version is arranged chronologically rather than by traditional book order, and is also chunked into 365 days. This is an alluring format for me, because it is already structured for daily progress.&lt;/p&gt;
</description>
      <guid>http://aesthetikx.info/blog/books_in_2026.html</guid>
      <pubDate>Tue, 6 Jan 2026 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Weird Ruby</title>
      <link>http://aesthetikx.info/blog/weird_ruby.html</link>
      <description>&lt;p&gt;Here is an ongoing collection of weird Ruby snippets that I have come across in my travels.&lt;/p&gt;

&lt;h3 id="camping-r-helper"&gt;Camping R Helper&lt;/h3&gt;

&lt;p&gt;Camping uses a bizarre helper method R that acts as a stand-in for a parent class.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Edit&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;R&lt;/span&gt; &lt;span class="s1"&gt;'/post/(\d+)/edit'&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;require_login!&lt;/span&gt;
    &lt;span class="vi"&gt;@post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:edit&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See: https://github.com/camping/camping/blob/main/examples/blog.rb#L63&lt;/p&gt;

&lt;p&gt;Decoding the implementation of this method left as an exercise for the reader… notably &lt;code&gt;grep(Hash)&lt;/code&gt;, &lt;code&gt;gsub(CampTools.descape){$1}&lt;/code&gt;, and the &lt;code&gt;h.any??&lt;/code&gt;.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;R&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sr"&gt;/\(.+?\)/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;grep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;-=&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"bad route"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;\/?$/&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt; &lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="no"&gt;U&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_param&lt;/span&gt; &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))}.&lt;/span&gt;&lt;span class="nf"&gt;gsub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CampTools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;descape&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="vg"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any?&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;"?"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="no"&gt;U&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There is also this gem: (https://github.com/camping/camping/commit/6724a04b37902c48c44c568ec5ce53b2f1a28620)&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;meta_def&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;instance_eval&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Later on in the &lt;a href="https://github.com/camping/reststop"&gt;camping/reststop&lt;/a&gt; library, we ammend the afforementioned R method with an even fancier REST method, featuring an all caps method name, a module_eval, a meta_def, and an all caps global.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;REST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
  &lt;span class="n"&gt;crud&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;R&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:prefix&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/([0-9a-zA-Z]+)/([a-z_]+)(?:&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;[a-z]+)?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:prefix&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/([0-9a-zA-Z]+)(?:&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;[a-z]+)?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:prefix&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/([a-z_]+)(?:&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;[a-z]+)?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:prefix&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;(?:&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;[a-z]+)?"&lt;/span&gt;

  &lt;span class="n"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;module_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;meta_def&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:restful?&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="vg"&gt;$LOG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Creating RESTful controller for &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; using Reststop &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="s1"&gt;'pull version number here'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$LOG&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id_or_custom_action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;custom_action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# :nodoc:&lt;/span&gt;
      &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="webrick-method-names"&gt;WEBrick Method Names&lt;/h3&gt;

&lt;p&gt;The WEBrick HTTP server toolkit provides a way to implement custom behavior through the use of mounted ‘servlets’, which have funny looking method names (&lt;code&gt;def do_GET&lt;/code&gt;).&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Simple&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;WEBrick&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTPServlet&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;AbstractServlet&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_GET&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;do_stuff_with&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'text/plain'&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Hello, World!'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See: https://github.com/ruby/webrick/blob/master/lib/webrick.rb&lt;/p&gt;

&lt;h3 id="webrick-option-symbols"&gt;WEBrick Option Symbols&lt;/h3&gt;

&lt;p&gt;It’s not that unusual to see capital letters in symbols, but this line from the documentation alwasy strikes me as odd. Perhaps its just because of the hashrocket syntax…&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;WEBrick&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTPServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="ss"&gt;:Port&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:DocumentRoot&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="syntropy-example"&gt;Syntropy Example&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/digital-fabric/syntropy"&gt;syntropy&lt;/a&gt; is a web framework for building multi-page and single-page apps. I’m no what this example does, but its cool looking:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;export&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;markdown&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="no"&gt;MD&lt;/span&gt;&lt;span class="sh"&gt;
      ```ruby
      @buffer &amp;lt;&amp;lt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;
      ```
&lt;/span&gt;&lt;span class="no"&gt;    MD&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;tap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'!'&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;Papercraft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compiled_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;proc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See: https://github.com/digital-fabric/syntropy/blob/main/examples/bad.rb&lt;/p&gt;
</description>
      <guid>http://aesthetikx.info/blog/weird_ruby.html</guid>
      <pubDate>Mon, 29 Dec 2025 00:00:00 +0000</pubDate>
    </item>
  </channel>
</rss>
