Midas 0.5.0 is tagged, and it does one main thing: it lowers the supported Rails floor from >= 7.1.5.2 to >= 6.1.
I want to be plain about why. The changelog calls the old floor an end-of-life policy choice, not a technical constraint. Then I had a real application on Rails 6.1.7.10 and Ruby 3.3.11 that wanted to adopt Coin, and a policy line is a poor reason to turn that away.
Lowering the number was not the whole job, though. The commit that made the change says the ledger models declared their enums with the positional form and validate: true, neither of which exists in Rails 6.1, and that those files load on boot, so 6.1 could not even require the engine. The sections below cover what had to change to fix that.
What follows are the changes that matter for Rails compatibility, and the one place where behavior differs.
The dependency floors
Two lines in the gemspec moved:
railsfrom>= 7.1.5.2to>= 6.1polyfrom~> 1.0to~> 1.3
According to the changelog, Poly 1.3 is the release that lowered Poly’s own ActiveRecord floor. At the tag, the gemspec reads rails >= 6.1, poly ~> 1.3, money ~> 6.19.0, and required_ruby_version >= 3.2.0.
Enums that depend on the Rails version
The part that needed real thought was Ledger::Account#kind and Ledger::Posting#direction. I was using two things Rails 6.1 does not have: the positional form enum :kind, values, and the validate: true option, which turns an unknown value into a validation error. Checking the released gems, enum in ActiveRecord 6.1.7.10 only takes a hash of definitions. The positional signature is already there in 7.0.8, and validate: first appears in 7.1.0. Only the version check in the code below uses 7.1, because that is where validate: begins.
So each model now declares its enum conditionally on ActiveRecord::VERSION::STRING:
if ActiveRecord::VERSION::STRING >= '7.1'
enum :kind, KINDS, validate: true
else
enum kind: KINDS
end
On Rails 7.1 and later, behavior is exactly what it was. On 6.1 there is one difference you should know about. Assigning an unknown value raises ArgumentError at assignment time rather than producing a validation error.
I accepted that because the direction of the difference matters. It is stricter on 6.1, never looser. For a double-entry ledger, a bad kind or direction being rejected earlier is a tolerable trade. A bad value slipping through would not be. ActiveRecord 6.1 has no validate: option on enum, which is what moves that check to validation on 7.1 and later.
To make the allowed values easy to reach, the value maps are now exposed as constants: Account::KINDS and Posting::DIRECTIONS.
Migrations that Rails 6.1 can parse
Every bundled migration used to declare ActiveRecord::Migration[8.0]. Rails 6.1 cannot parse a newer compatibility version, so they now declare ActiveRecord::Migration[6.1].
I looked at whether that changes the resulting schema. For the adapters Midas supports, it does not in any way that matters. The only difference between 6.1 and 7.0 that would reach these tables is datetime precision. PostgreSQL’s plain timestamp is already microsecond-precision, and SQLite treats precision as advisory.
Existing installations are unaffected, because their migrations have already run.
Proving it in CI
Declaring a floor you never test is a promise you cannot keep. CI now has a Rails version axis, RAILS_VERSION, covering 7.1, 7.2, and 8.x, plus a 6.1 cell. Rails 6.1 predates Ruby 3.4, so that cell is pinned to Ruby 3.3, the Ruby the real consumer runs. RuboCop was split into its own job, since lint does not vary with the Rails version.
Making that matrix work meant fixing the test app and a few development dependencies too:
spec/dummycould only boot on Rails 7.1 and later. Settings such asconfig.autoload_lib,config.enable_reloading, andprimary_abstract_classare now version-guarded, as are theshow_exceptionsvalue type andraise_on_missing_callback_actions.spec/rails_helper.rbfalls back fromfixture_pathstofixture_pathon older ActiveRecord.- The
rspec-railsdevelopment dependency went from~> 7.0to>= 6.1, because 7.x cannot resolve against Rails 6.1. - The 6.1 bundle lane pins
concurrent-ruby < 1.3.5andsqlite3 ~> 1.4. Both live in the Gemfile only; neither is a runtime requirement of the gem.
Where it stands
The 0.5.0 section of the changelog and the repository at the v0.5.0 tag are the sources for everything above, apart from two things. The reason 6.1 could not require the engine comes from the commit message of 5e88d07 on the integration branch. The statement about which ActiveRecord release introduced the positional form and validate: comes from the enum.rb source of the activerecord 6.1.7.10, 7.0.8 and 7.1.0 gems, not from the Midas changelog.
The product page is at /products/midas/, and the project site is at midas.whittakertech.com.