tags: Til

PTA: Plain Text Accounting

Recently I learned about PTA: Plain Text Accounting. You can record income and expenses with plain text, gather data programmatically, then calculate and visualize. Ledger, hledger, and Beancount are software tools that provide a way to express double-entry bookkeeping in plain text. They use similar plain-text DSLs, though Beancount is not directly source-compatible with the others. Here’s a small example of Beancount syntax (Assume these accounts were opened earlier): 2026-08-03 * "Employer" "Salary" Assets:Bank 300000 JPY Income:Salary 2026-08-04 * "Cafe" "Coffee" Expenses:Food 600 JPY Assets:Bank What does it mean PTA provides a shared style of notation for expressing accounting activities in plain text. This is handy common knowledge in case we want to write down transactions quickly in a text file or even on a whiteboard. Similar to the benefit of UML.

Read more →

Signing and Encrypting data with Rails

Rails provides abstractions for signing and encrypting data. If a Rails app needs to authenticate some data, (let’s say, to generate a magic link sent by email) Rails.application.message_verifier provides a convenient solution. This application-level interface was added in Rails 4.1, so it is already a mature Rails feature. The examples below wrap an opaque login token that is associated with a user in the payload. login_token = SecureRandom.urlsafe_base64(32) # => "2LfzCleMQtoNLYij4Ah_y5M80LwXbj3yPqeojsVvRBY" verifier = Rails.application.message_verifier(:magic_link) signed_message = verifier.generate( { token: login_token }, expires_in: 30.minutes, purpose: :login ) # => "eyJfcmFpbHMiOnsiZGF0YSI6eyJ0b2tlbiI6IjJMZnpDbGVNUXRvTkxZaWo0QWhfeTVNODBMd1hiajN5UHFlb2pzVnZSQlkifSwiZXhwIjoiMjAyNi0wNy0yNlQxMjowODozNS42ODBaIiwicHVyIjoibG9naW4ifX0=--3f9948547736a1650e31c35c6c7b38f518785380" payload = verifier.verify(signed_message, purpose: :login) # => {"token" => "2LfzCleMQtoNLYij4Ah_y5M80LwXbj3yPqeojsVvRBY"} Rails.application.message_verifier is a turnkey solution for signing and verifying application data with a MAC-based mechanism. It supports expiration and purpose scoping outside of the data itself. The secret is derived from secret_key_base.

Read more →

MOC: Map of Content

What is an MOC An MOC (Map of Content) is a curated cluster of related information around some area of interest. At a glance, it may look like just an index of notes. But an MOC is not only for organizing scattered notes, but also provides an opportunity to think, deepen your understanding, discover connections, and distill ideas. Building and maintaining an MOC is therefore part of the value it provides.

Read more →

Variables with Shell-Style Default in docker-compose.yml

Today I learned that in docker-compose.yml, a variable interpolation with a default can be expressed as ${VAR1:-default value} like shell-style parameter expansion. With parameter expansion, you can do more than setting a default value such as modifying the parameter. However, the supported features in docker-compose.yml are limited to two of them: to set a default variable or to make the parameter mandatory. Let’s define VAR_ALPHA with a default value for the example service.

Read more →

What is MySQL's Online DDL

Today I learned a MySQL term: online DDL. The online DDL lets you alter tables efficiently, without making tables unavailable during the entire operation and exclusive table locks. The behavior of a DDL operation can be specified using the ALGORITHM and LOCK clauses. You don’t have to get overwhelmed by the mysterious terms. Actually, you may have used it before without knowing because MySQL will try to use it by default when you execute ordinary alter table statements.

Read more →

change_table with Bulk Option Combines Multiple alter-table Statements

Today I learned that when doing database-migration on Rails, change_table :#{table_name}, bulk: true let us combine multiple alter-table statements and it could reduce the cost of the whole alteration. That is, instead of executing multiple alter-table separately, def change add_column :users, :first_name, :string, null: false add_column :users, :last_name, :string, null: false end we can run a single alter-table statement by change_table like as follows. def change change_table :users, bulk: true do |t| t.column :first_name, :string, null: false t.column :last_name, :string, null: false end end However, why should we do that? What are the differences between them?

Read more →

RSpec's #to Method Takes the 2nd Argument As Its failing-message

Today I learned that RSpec’s #to method takes the 2nd argument as its custom failing-message. expect(actual_value).to eq(expected_value), message Let’s say we are going to test a JSON object. The following example expects a part of the JSON object response_json['eye_colour'] to be "blue". require 'net/https' require 'uri' require 'json' RSpec.describe do example do response = Net::HTTP.get_response(URI('https://swapi.dev/api/people/1/')) response_json = JSON.parse(response.body) expect(response_json['eye_colour']).to eq('blue') end end Unfortunately, this test fails and displays messages like this: Failures: 1) is expected to eq "blue" Failure/Error: expect(response_json['eye_colour']).to eq('blue') expected: "blue" got: nil (compared using ==) From this output, we could guess either response_json['eye_colour'] is set to nil or the key eye_colour is not defined. However, there is no more information here. To find out the cause of the error, an additional print-debug would be needed.

Read more →

How to Fix PostgreSQL Error: canceling statement due to conflict with recovery

Today I learned how to fix a PostgreSQL error like this: ERROR: canceling statement due to conflict with recovery DETAIL: User query might have needed to see row versions that must be removed. It’s about database replication. I have been getting that on read-only database which uses PostgreSQL Hot Standby. This error didn’t happen always but happened occasionally. I fixed that by setting both max_standby_archive_delay and max_standby_streaming_delay to a longer time (300s) on the standby servers. The reason that this error occurs is query conflicts. This kind of error is not inevitable because of the nature of database replication, and in some cases, queries running on standby servers have to be canceled. Then the error shows up.

Read more →

`sole` Method Is Going to Be Introduced into ActiveRecord and Enumerable

Today I learned that Rails 6.1.3 does not have methods that raise exceptions when more than one record was found. However, in future versions, we could use ActiveRecord::FinderMethods#sole for that purpose. It seems Enumerable#sole is also going to be introduced. Sometimes I need to make sure there is one and only one record that matches a condition without using a unique-index, for example, when I cannot add that constraint to the database.

Read more →

Format with to_s Methods ActiveSupport Provides

Today I learned/remembered that to format a number with a delimiter, we can use ActiveSupport::NumericWithFormat#to_s(:delimited). require 'active_support' require 'active_support/core_ext' 123456789.to_s(:delimited) # => "123,456,789" Not only that, but this method also provides other formats and takes options to tweak its behavior. 123456789.to_s(:delimited, delimiter: '-') # => "123-456-789" 123456789.to_s(:currency, precision: 3) # => "$123,456,789.000" 123456789.to_s(:human_size) # => "118 MB" 123456789.to_s(:human) # => "123 Million" Originally, when I need to format a number to a delimited number, I would try to use number_to_delimited provided by ActiveSupport::NumberHelper. But to_s is handy when we have to do that where the helper is not reachable by default, such as in a serializer class for ActiveModel Serializer. Calling this method passing a format is the same as calling ActiveSupport::NumberHelper.number_to_#{format}.

Read more →

Gentaro "hibariya" Terada

Otakanomori, Nagareyama, Chiba, Japan
Email me

Likes Ruby, Internet, and Programming.