<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ifad on Marcello Barnaba</title>
    <link>https://sindro.me/tags/ifad/</link>
    <description>Recent content in Ifad on Marcello Barnaba</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Sat, 11 Apr 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://sindro.me/tags/ifad/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>ansible-wsadmin: Bypassing AdminConfig to Automate WebSphere via JMX</title>
      <link>https://sindro.me/posts/2026-04-11-ansible-wsadmin/</link>
      <pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2026-04-11-ansible-wsadmin/</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;tl;dr&lt;/strong&gt; — IBM WebSphere has a clean configuration API (ConfigService) buried under a broken string-based wrapper (AdminConfig). I built an object-oriented Jython layer that hooks into ConfigService directly via JMX — easing configuration and ensuring type correctness through metadata introspection — plus a persistent daemon that eliminates JVM boot overhead, and 55 idempotent scripts that integrate with Ansible&amp;rsquo;s change detection. &lt;a href=&#34;https://github.com/vjt/ansible-wsadmin&#34; target=&#34;_blank&#34;&gt;github.com/vjt/ansible-wsadmin&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;In 2021, I spent six months automating the &lt;a href=&#34;https://www.ifad.org/&#34; target=&#34;_blank&#34;&gt;IFAD&lt;/a&gt; WebSphere infrastructure with Ansible. The stack was IBM WebSphere Application Server (WAS), WebSphere Portal Server (WPS), and Business Automation Workflow (BAW) — a clustered deployment with a Deployment Manager, multiple nodes, federated LDAP, SIB messaging, the works.&lt;/p&gt;&#xA;&lt;p&gt;The standard approach to automating WAS is to write Jython scripts using &lt;code&gt;AdminConfig&lt;/code&gt;, &lt;code&gt;AdminTask&lt;/code&gt;, and &lt;code&gt;AdminApp&lt;/code&gt; — the four global scripting objects that IBM provides inside &lt;a href=&#34;https://en.wikipedia.org/wiki/Wsadmin&#34; target=&#34;_blank&#34;&gt;wsadmin&lt;/a&gt;. I tried that. It lasted about a day before I started looking at what&amp;rsquo;s underneath.&lt;/p&gt;&#xA;&lt;p&gt;What I found changed how I approached the entire project. It also produced a library full of ideas I never had a chance to describe properly — until now, with a little help from &lt;a href=&#34;https://claude.ai&#34; target=&#34;_blank&#34;&gt;Claude&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Integrating OneSpan Two-Factor Products with Ruby</title>
      <link>https://sindro.me/posts/2020-09-11-integrating-onespan-2fa-with-ruby/</link>
      <pubDate>Fri, 11 Sep 2020 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2020-09-11-integrating-onespan-2fa-with-ruby/</guid>
      <description>&lt;p&gt;I was tasked with integrating &lt;a href=&#34;https://www.onespan.com/&#34; target=&#34;_blank&#34;&gt;OneSpan&lt;/a&gt; (formerly VASCO) hardware token two-factor authentication into a Ruby stack — wrapping their proprietary VACMAN Controller C SDK for local OTP validation, and building a client for their &lt;a href=&#34;https://docs.onespan.com/sec/docs/onespan-authentication-server&#34; target=&#34;_blank&#34;&gt;OneSpan Authentication Server&lt;/a&gt; (originally named Identikey Authentication Server, and renamed mid-project) SOAP API. Neither had a Ruby library.&lt;/p&gt;&#xA;&lt;p&gt;For &lt;a href=&#34;https://github.com/vjt/vacman_controller&#34; target=&#34;_blank&#34;&gt;vacman_controller&lt;/a&gt; there was a starting point: &lt;a href=&#34;https://github.com/mlankenau/vacman_controller&#34; target=&#34;_blank&#34;&gt;a Ruby C extension&lt;/a&gt; by Marcus Lankenau wrapping the AAL2 SDK. One commit, no releases, rough around the edges, but a solid foundation — linking, importing tokens and basic wrappers — was there. I &lt;a href=&#34;https://github.com/ifad/vacman_controller&#34; target=&#34;_blank&#34;&gt;forked it at IFAD&lt;/a&gt;, fixed it, extended it, and pushed &lt;a href=&#34;https://github.com/vjt/vacman_controller/commits/master&#34; target=&#34;_blank&#34;&gt;97 additional commits&lt;/a&gt; on top. 14 releases, v0.1.0 through v0.9.3.&lt;/p&gt;&#xA;&lt;p&gt;For &lt;a href=&#34;https://github.com/vjt/identikey&#34; target=&#34;_blank&#34;&gt;identikey&lt;/a&gt; there was nothing — OneSpan ships a Java SDK, no Ruby library exists. I &lt;a href=&#34;https://github.com/vjt/identikey&#34; target=&#34;_blank&#34;&gt;wrote one from scratch&lt;/a&gt;: 123 commits, 18 tags, v0.2.0 through v0.9.1.&lt;/p&gt;&#xA;&lt;p&gt;Both are &lt;a href=&#34;https://github.com/vjt/vacman_controller&#34; target=&#34;_blank&#34;&gt;on&lt;/a&gt; &lt;a href=&#34;https://github.com/vjt/identikey&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;. Here&amp;rsquo;s what&amp;rsquo;s inside.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ChronoModel 1.0: Seven Years to Ship</title>
      <link>https://sindro.me/posts/2019-04-06-chronomodel-one-dot-zero/</link>
      <pubDate>Sat, 06 Apr 2019 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2019-04-06-chronomodel-one-dot-zero/</guid>
      <description>&lt;div class=&#34;retrospective&#34;&gt;&#xA;  &lt;span class=&#34;retrospective-icon&#34;&gt;&amp;#x1f50d;&lt;/span&gt;&#xA;  &lt;div class=&#34;retrospective-body&#34;&gt;&#xA;    &lt;em&gt;2026 retrospective&lt;/em&gt;&lt;br&gt;&#xA;    My last release was &lt;a href=&#34;https://rubygems.org/gems/chrono_model/versions/1.2.2&#34; target=&#34;_blank&#34;&gt;v1.2.2&lt;/a&gt; in May 2019. After that, &lt;a href=&#34;https://github.com/tagliala&#34; target=&#34;_blank&#34;&gt;Geremia Taglialatela&lt;/a&gt; took over and pushed it to &lt;a href=&#34;https://rubygems.org/gems/chrono_model/versions/5.0.0&#34; target=&#34;_blank&#34;&gt;v5.0.0&lt;/a&gt; with Rails 8.1 and Ruby 4.0 support. &lt;a href=&#34;https://rubygems.org/gems/chrono_model/versions&#34; target=&#34;_blank&#34;&gt;34 releases&lt;/a&gt; spanning 14 years, &lt;a href=&#34;https://github.com/ifad/chronomodel/stargazers&#34; target=&#34;_blank&#34;&gt;201 stars&lt;/a&gt;, and still actively maintained. The &lt;a href=&#34;https://vjt.github.io/chronomodel/&#34; target=&#34;_blank&#34;&gt;API documentation&lt;/a&gt; and the &lt;a href=&#34;https://github.com/ifad/chronomodel&#34; target=&#34;_blank&#34;&gt;repo&lt;/a&gt; are both alive.&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Seven years ago I &lt;a href=&#34;https://sindro.me/posts/2012-05-07-chronomodel-time-travel-postgresql/&#34;&gt;released ChronoModel v0.1.0&lt;/a&gt; — a Ruby gem that gives ActiveRecord models temporal capabilities on PostgreSQL. Five days of hacking, thirty-six commits, no tests, and a confession about monkey-patching the PostgreSQL adapter constant.&lt;/p&gt;&#xA;&lt;p&gt;Today I&amp;rsquo;m tagging &lt;a href=&#34;https://github.com/ifad/chronomodel/commit/aa07e74&#34; target=&#34;_blank&#34;&gt;v1.0.0&lt;/a&gt;. The commit message is &lt;code&gt;:gem: this is v1.0.0&lt;/code&gt;. Not much of a speech, but the code speaks for itself: 506 commits, 31 releases, 52 files changed, 5,392 lines added. The &lt;a href=&#34;https://sindro.me/posts/2012-05-07-chronomodel-time-travel-postgresql/#the-architecture&#34;&gt;core idea&lt;/a&gt; — updatable views on &lt;code&gt;public&lt;/code&gt;, current data on &lt;code&gt;temporal&lt;/code&gt;, history on &lt;code&gt;history&lt;/code&gt; with table inheritance — never changed. Everything else did.&lt;/p&gt;</description>
    </item>
    <item>
      <title>A Shameless Translation Memory Importer for Pontoon</title>
      <link>https://sindro.me/posts/2018-02-14-translation-memory-pontoon/</link>
      <pubDate>Wed, 14 Feb 2018 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2018-02-14-translation-memory-pontoon/</guid>
      <description>&lt;div class=&#34;retrospective&#34;&gt;&#xA;  &lt;span class=&#34;retrospective-icon&#34;&gt;&amp;#x1f50d;&lt;/span&gt;&#xA;  &lt;div class=&#34;retrospective-body&#34;&gt;&#xA;    &lt;em&gt;2026 retrospective&lt;/em&gt;&lt;br&gt;&#xA;    The repo at &lt;a href=&#34;https://github.com/ifad/translation-memory&#34; target=&#34;_blank&#34;&gt;github.com/ifad/translation-memory&lt;/a&gt; is still public, still has no README, and the Pontoon fork it talks to remains private. &lt;a href=&#34;https://github.com/mozilla/pontoon&#34; target=&#34;_blank&#34;&gt;Mozilla&amp;rsquo;s upstream&lt;/a&gt; is open and very much alive. Whether anyone at IFAD still runs Pontoon eight years on, I honestly don&amp;rsquo;t know — I built this for one project on my desk, not as a corporate workflow change. The hyphen-stripping regex did its job for the months I needed it. Then, presumably, the next Pontoon schema migration broke something. That&amp;rsquo;s what happens to integrations that talk to a database directly.&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;http://www.ifad.org/&#34; target=&#34;_blank&#34;&gt;IFAD&lt;/a&gt; is a UN agency that operates in &lt;a href=&#34;https://www.ifad.org/en/web/operations/languages&#34; target=&#34;_blank&#34;&gt;English, French, Spanish, and Arabic&lt;/a&gt;. Every public-facing string in our Rails apps needs to exist in four languages, which means we have a translation team, which means we have a translation workflow, which on most projects involves a &lt;a href=&#34;https://en.wikipedia.org/wiki/Computer-assisted_translation&#34; target=&#34;_blank&#34;&gt;desktop CAT tool&lt;/a&gt;, files attached to emails, and translation memories shipped around as XML.&lt;/p&gt;&#xA;&lt;p&gt;That workflow does not survive a project I&amp;rsquo;m building right now. It&amp;rsquo;s a Rails web app on a tight schedule, the source strings change every week, and by the time a translator has finished a TM file and emailed it back the strings have already moved. I need translators and developers looking at the same database in real time. I pick &lt;a href=&#34;https://pontoon.mozilla.org/&#34; target=&#34;_blank&#34;&gt;Mozilla Pontoon&lt;/a&gt; — open-source, free, adaptable, written in Django, backed by Postgres — and stand it up for my project. The catch: there is a corpus of translations from the previous tool that I want to seed Pontoon with on day one, so the translators don&amp;rsquo;t start from a blank slate.&lt;/p&gt;&#xA;&lt;p&gt;Today I start a &lt;a href=&#34;https://github.com/ifad/translation-memory&#34; target=&#34;_blank&#34;&gt;translation-memory&lt;/a&gt; repo and write the first parser. The project is described, with all due engineering humility, as &lt;a href=&#34;https://github.com/ifad/translation-memory&#34; target=&#34;_blank&#34;&gt;&amp;ldquo;Parser for TMX, SDL/XLIFF and TXML files and shameless importer into Mozilla Pontoon&amp;rdquo;&lt;/a&gt;. The &amp;ldquo;shameless&amp;rdquo; part is doing a lot of work in that sentence.&lt;/p&gt;</description>
    </item>
    <item>
      <title>From Heathen to Colore: A Document Pipeline Story</title>
      <link>https://sindro.me/posts/2016-01-15-document-pipeline-heathen-colore/</link>
      <pubDate>Fri, 15 Jan 2016 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2016-01-15-document-pipeline-heathen-colore/</guid>
      <description>&lt;div class=&#34;retrospective&#34;&gt;&#xA;  &lt;span class=&#34;retrospective-icon&#34;&gt;&amp;#x1f50d;&lt;/span&gt;&#xA;  &lt;div class=&#34;retrospective-body&#34;&gt;&#xA;    &lt;em&gt;2026 retrospective&lt;/em&gt;&lt;br&gt;&#xA;    Colore is still alive at &lt;a href=&#34;https://github.com/ifad/colore&#34; target=&#34;_blank&#34;&gt;github.com/ifad/colore&lt;/a&gt; — &lt;a href=&#34;https://github.com/ifad/colore/commits?author=tagliala&#34; target=&#34;_blank&#34;&gt;Geremia Taglialatela&lt;/a&gt; took over after I drifted onto other things and pushed the project forward through Ruby 2.7, 3.0, 3.1, 3.2, sidekiq 6, and modern CI. He sits at &lt;a href=&#34;https://github.com/ifad/colore/graphs/contributors&#34; target=&#34;_blank&#34;&gt;354 commits&lt;/a&gt; — three times mine. The &lt;a href=&#34;https://github.com/ifad/colore/tree/master/nginx/ngx_colore_module&#34; target=&#34;_blank&#34;&gt;nginx C module&lt;/a&gt; Joe wrote in February 2015 is unchanged. Heathen the standalone service was eventually folded directly into Colore as a library; the &lt;a href=&#34;https://github.com/ifad/heathen&#34; target=&#34;_blank&#34;&gt;original repo&lt;/a&gt; is archived but the code lives on inside &lt;code&gt;lib/heathen/&lt;/code&gt; of Colore. Same idea, fewer moving parts.&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;http://www.ifad.org/&#34; target=&#34;_blank&#34;&gt;IFAD&lt;/a&gt; is a UN agency that runs on documents. Loan agreements, evaluation reports, country strategy notes, board decisions, project briefs — every web application we build sooner or later needs to take a Word file and give back a PDF, or take a scan and give back something searchable, or take an arbitrary blob and turn it into a thumbnail. Three years ago we decided to stop solving this problem one application at a time and put it behind a single service.&lt;/p&gt;&#xA;&lt;p&gt;Today I&amp;rsquo;m merging &lt;a href=&#34;https://github.com/ifad/colore/commit/63d4fe0&#34; target=&#34;_blank&#34;&gt;v1.0.0 of Colore&lt;/a&gt;. It&amp;rsquo;s the second attempt at that service, and it&amp;rsquo;s the one we get to keep. This is the story of both attempts and the people who built them — because almost none of the code below is mine.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Eaco: The Holder of the Keys of Hades</title>
      <link>https://sindro.me/posts/2015-02-28-eaco-authorization-ruby/</link>
      <pubDate>Sat, 28 Feb 2015 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2015-02-28-eaco-authorization-ruby/</guid>
      <description>&lt;div class=&#34;retrospective&#34;&gt;&#xA;  &lt;span class=&#34;retrospective-icon&#34;&gt;&amp;#x1f50d;&lt;/span&gt;&#xA;  &lt;div class=&#34;retrospective-body&#34;&gt;&#xA;    &lt;em&gt;2026 retrospective&lt;/em&gt;&lt;br&gt;&#xA;    Eaco reached &lt;a href=&#34;https://github.com/ifad/eaco/tree/v1.0.0&#34; target=&#34;_blank&#34;&gt;v1.0.0&lt;/a&gt; on May 5, 2016 — commit message: &amp;ldquo;This is v1.0.0. Two years in production.&amp;rdquo; It grew to 54 stars, 8 forks, 240 commits, and ran authorization at IFAD for five more years after that. &lt;a href=&#34;https://github.com/tagliala&#34; target=&#34;_blank&#34;&gt;Geremia Taglialatela&lt;/a&gt; picked it up in 2020 and kept it running on Rails 6.0 and 6.1, then &lt;a href=&#34;https://github.com/ifad/eaco/commit/19&#34; target=&#34;_blank&#34;&gt;modernized the CI&lt;/a&gt; in late 2025. The ABAC-with-hash-ACLs pattern turned out to be exactly right for an organization where access is determined by position, department, and working group — not just &amp;ldquo;admin or not.&amp;rdquo; The &lt;a href=&#34;https://github.com/ifad/eaco&#34; target=&#34;_blank&#34;&gt;repo&lt;/a&gt; is still online, and the &lt;a href=&#34;https://vjt.github.io/eaco/&#34; target=&#34;_blank&#34;&gt;YARD documentation&lt;/a&gt; is still some of the most thorough I&amp;rsquo;ve ever written for a gem.&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Scriptoria is an internal workflow application at &lt;a href=&#34;http://www.ifad.org/&#34; target=&#34;_blank&#34;&gt;IFAD&lt;/a&gt; — a UN specialized agency in Rome — and its authorization layer has been annoying me for months. The code works, but it&amp;rsquo;s tangled into the app. Every time we need to add a new role or change who can access what, we&amp;rsquo;re editing application code that shouldn&amp;rsquo;t care about authorization semantics.&lt;/p&gt;&#xA;&lt;p&gt;So eight days ago I started extracting it. Today I&amp;rsquo;m releasing the result: &lt;a href=&#34;https://github.com/ifad/eaco&#34; target=&#34;_blank&#34;&gt;Eaco&lt;/a&gt; — an Attribute-Based Access Control framework for Ruby, named after &lt;a href=&#34;http://en.wikipedia.org/wiki/Aeacus&#34; target=&#34;_blank&#34;&gt;Eacus&lt;/a&gt;, the holder of the keys of Hades in Greek mythology.&lt;/p&gt;&#xA;&lt;p&gt;172 commits. Five releases. 100% test coverage. And a Saturday afternoon I&amp;rsquo;ll never get back.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hermes: contextual help in 48 hours (Rails Rumble 2013)</title>
      <link>https://sindro.me/posts/2013-10-20-hermes-rails-rumble-2013/</link>
      <pubDate>Sun, 20 Oct 2013 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2013-10-20-hermes-rails-rumble-2013/</guid>
      <description>&lt;div class=&#34;retrospective&#34;&gt;&#xA;  &lt;span class=&#34;retrospective-icon&#34;&gt;&amp;#x1f50d;&lt;/span&gt;&#xA;  &lt;div class=&#34;retrospective-body&#34;&gt;&#xA;    &lt;em&gt;2026 retrospective&lt;/em&gt;&lt;br&gt;&#xA;    The &amp;ldquo;contextual help&amp;rdquo; space exploded into a whole product category — Intercom, Pendo, Appcues and others now do this commercially at scale. IFAD&amp;rsquo;s fork lived on for years inside the agency. The Rails Rumble itself stopped running after 2015, and the era of 48-hour competition hackathons gave way to AI hackathons and startup weekends. The &lt;a href=&#34;https://github.com/vjt/r13-hermes&#34; target=&#34;_blank&#34;&gt;repo&lt;/a&gt; is archived but still up.&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;http://railsrumble.com/&#34; target=&#34;_blank&#34;&gt;Rails Rumble&lt;/a&gt; is — was — a 48-hour hackathon where teams of up to four people build a complete web app from scratch using Ruby. No prep work, no pre-written code. Just caffeine, git, and a deadline.&lt;/p&gt;&#xA;&lt;p&gt;This year our team — &lt;a href=&#34;https://github.com/amedeo&#34; target=&#34;_blank&#34;&gt;@amedeo&lt;/a&gt;, &lt;a href=&#34;https://github.com/liquid1982&#34; target=&#34;_blank&#34;&gt;@liquid1982&lt;/a&gt;, &lt;a href=&#34;https://github.com/maisongb&#34; target=&#34;_blank&#34;&gt;@maisongb&lt;/a&gt;, and me — built &lt;strong&gt;Hermes: the epic messenger service&lt;/strong&gt;, entry #385.&lt;/p&gt;&#xA;&lt;p&gt;(My &lt;a href=&#34;https://sindro.me/posts/2012-10-14-guess-the-friend-rails-rumble-2012/&#34;&gt;previous Rumble entry&lt;/a&gt; was &lt;em&gt;Guess The Friend&lt;/em&gt; in 2012, with a different team.)&lt;/p&gt;</description>
    </item>
    <item>
      <title>data-confirm-modal: When a User Did Too Much Damage</title>
      <link>https://sindro.me/posts/2013-07-02-data-confirm-modal/</link>
      <pubDate>Tue, 02 Jul 2013 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2013-07-02-data-confirm-modal/</guid>
      <description>&lt;div class=&#34;retrospective&#34;&gt;&#xA;  &lt;span class=&#34;retrospective-icon&#34;&gt;&amp;#x1f50d;&lt;/span&gt;&#xA;  &lt;div class=&#34;retrospective-body&#34;&gt;&#xA;    &lt;em&gt;2026 retrospective&lt;/em&gt;&lt;br&gt;&#xA;    This tiny gem grew to 268 stars and 112 forks, with 32 contributors over 7 years. It learned &lt;a href=&#34;https://github.com/ifad/data-confirm-modal/blob/v1.6.0/vendor/assets/javascripts/data-confirm-modal.js#L12-L33&#34; target=&#34;_blank&#34;&gt;Bootstrap 3, then 4 with auto-detection&lt;/a&gt; (v1.6.0), got a &lt;a href=&#34;https://github.com/ifad/data-confirm-modal?tab=readme-ov-file#without-rails-with-data-attributes-example-b3-example-b4&#34; target=&#34;_blank&#34;&gt;non-Rails mode&lt;/a&gt; with &lt;code&gt;dataConfirmModal.confirm()&lt;/code&gt; callbacks (v1.2.0), an &lt;a href=&#34;https://www.npmjs.com/package/data-confirm-modal&#34; target=&#34;_blank&#34;&gt;npm package&lt;/a&gt; still pulling 3,700 downloads/week (v1.6.2), and kept working with every Rails version through 6.0. The concept became so mainstream that every UI framework now ships its own confirmation dialog component. The &lt;a href=&#34;https://github.com/ifad/data-confirm-modal&#34; target=&#34;_blank&#34;&gt;repo&lt;/a&gt; is still up.&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;A user at &lt;a href=&#34;http://www.ifad.org/&#34; target=&#34;_blank&#34;&gt;IFAD&lt;/a&gt; did too much damage last week.&lt;/p&gt;&#xA;&lt;p&gt;Not maliciously — they just clicked through a chain of destructive actions, happily dismissing the browser&amp;rsquo;s &lt;code&gt;confirm()&lt;/code&gt; dialogs without reading them. Because nobody reads those. They&amp;rsquo;re ugly grey system dialogs that blend into the background of your workflow. Click OK, click OK, click OK — and suddenly half the data is gone.&lt;/p&gt;&#xA;&lt;p&gt;So I fixed it. And then I extracted the fix into a gem, because this problem isn&amp;rsquo;t specific to our application. Today I&amp;rsquo;m releasing &lt;a href=&#34;https://github.com/ifad/data-confirm-modal&#34; target=&#34;_blank&#34;&gt;data-confirm-modal&lt;/a&gt; — 116 lines of JavaScript that replace Rails&amp;rsquo; built-in &lt;code&gt;confirm()&lt;/code&gt; with a &lt;a href=&#34;https://getbootstrap.com/2.3.2/javascript.html#modals&#34; target=&#34;_blank&#34;&gt;Bootstrap modal&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ChronoModel: Time Travel for PostgreSQL</title>
      <link>https://sindro.me/posts/2012-05-07-chronomodel-time-travel-postgresql/</link>
      <pubDate>Mon, 07 May 2012 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2012-05-07-chronomodel-time-travel-postgresql/</guid>
      <description>&lt;div class=&#34;retrospective&#34;&gt;&#xA;  &lt;span class=&#34;retrospective-icon&#34;&gt;&amp;#x1f50d;&lt;/span&gt;&#xA;  &lt;div class=&#34;retrospective-body&#34;&gt;&#xA;    &lt;em&gt;2026 retrospective&lt;/em&gt;&lt;br&gt;&#xA;    ChronoModel is still alive — 14 years, 41 releases, 201 stars. The rules got replaced by INSTEAD OF triggers in &lt;a href=&#34;https://github.com/ifad/chronomodel/tree/v0.6.0&#34; target=&#34;_blank&#34;&gt;v0.6&lt;/a&gt; (2014), the &lt;code&gt;box()&lt;/code&gt;/&lt;code&gt;point()&lt;/code&gt; hack by proper &lt;code&gt;tsrange&lt;/code&gt; columns, and the monkey-patching by a proper adapter registration. &lt;a href=&#34;https://github.com/tagliala&#34; target=&#34;_blank&#34;&gt;Geremia Taglialatela&lt;/a&gt; took over maintenance in 2020 and pushed it to &lt;a href=&#34;https://rubygems.org/gems/chrono_model/versions/5.0.0&#34; target=&#34;_blank&#34;&gt;v5.0.0&lt;/a&gt; with Rails 8.1 and Ruby 4.0 support. The core idea — updatable views on &lt;code&gt;public&lt;/code&gt;, current data on &lt;code&gt;temporal&lt;/code&gt;, history on &lt;code&gt;history&lt;/code&gt; with table inheritance — never changed. The &lt;a href=&#34;https://github.com/ifad/chronomodel&#34; target=&#34;_blank&#34;&gt;repo&lt;/a&gt; is healthy and actively maintained.&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Update, April 2019:&lt;/strong&gt; &lt;a href=&#34;https://sindro.me/posts/2019-04-06-chronomodel-one-dot-zero/&#34;&gt;ChronoModel reached 1.0&lt;/a&gt; — seven years, 506 commits, and 31 releases later.&lt;/p&gt;&#xA;&lt;p&gt;We&amp;rsquo;re building a CRM at &lt;a href=&#34;http://www.ifad.org/&#34; target=&#34;_blank&#34;&gt;IFAD&lt;/a&gt; — a UN specialized agency in Rome — and one of the hard requirements is temporal data. We need to know what a record looked like at any point in the past. What was this project&amp;rsquo;s budget on March 15th? When did this beneficiary&amp;rsquo;s address change? Who approved what, and what did the record look like at the time?&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;d been prototyping a PostgreSQL schema approach for this — views, rules, table inheritance — and it worked. Then &lt;a href=&#34;https://github.com/amedeo&#34; target=&#34;_blank&#34;&gt;Amedeo&lt;/a&gt;, my boss, looked at it and said: &amp;ldquo;This shouldn&amp;rsquo;t live inside the CRM. Make it a reusable framework.&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;He was right. The temporal pattern has nothing to do with CRM logic. It belongs in a gem.&lt;/p&gt;&#xA;&lt;p&gt;So I had five days of uninterrupted focus, and today I&amp;rsquo;m releasing &lt;a href=&#34;https://github.com/ifad/chronomodel&#34; target=&#34;_blank&#34;&gt;ChronoModel&lt;/a&gt; — an ActiveRecord extension that gives your models full temporal capabilities on PostgreSQL. What Oracle sells as &lt;a href=&#34;http://docs.oracle.com/cd/B28359_01/appdev.111/b28424/adfns_flashback.htm&#34; target=&#34;_blank&#34;&gt;Flashback Queries&lt;/a&gt; and charges enterprise money for, we can do with standard SQL on Postgres 9.0+.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
