Repository navigation
Register framework integrations when the gem is required - #786
Merged
yukideluxe merged 2 commits intoSep 29, 2026
Merged
yukideluxe merged 2 commits into
yukideluxe merged 2 commits into
Conversation
`monetize` and the Action View helpers were only mixed in from the railtie initializer, via `MoneyRails::Hooks.init`. Outside a full Rails boot nothing registered those hooks, so `monetize` existed on no class: `ActiveRecord::Base.respond_to?(:monetize)` was false, and anything that inspects code rather than runs a server — documentation generators, editor autocomplete, static analysis, a plain `require "money-rails"` in a script or a test harness — saw an Active Record integration that was simply absent. It is the same class of problem as RubyMoneyGH-614: an integration invisible until an initializer happens to run. Move the two framework mixins to require time in `lib/money-rails.rb`. Registering an `ActiveSupport.on_load` hook is lazy and cheap: it does not load Active Record or Action View, it only queues the block until something else loads them, so non-Rails users pay nothing. The migration extensions stay in `Hooks.init`, because choosing between the PostgreSQL and generic variants reads `connection_db_config` and so needs a configured database — which is what the railtie's `after: "active_record.initialize_database"` guarantees. `Hooks.init` remains public and its documented use for non-Rails apps is unchanged; the mixins it no longer performs are already registered by the require it necessarily follows, and a repeated `include` is a no-op anyway. No behavior change for Rails apps. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mokevnin
force-pushed
the
register-framework-hooks-at-require-time
branch
from
September 17, 2026 15:29
064feaf to
ee3a233
Compare
Author
|
Rebased onto Verified locally on the rebased commit: CI is sitting at |
yukideluxe
approved these changes
Sep 29, 2026
yukideluxe
left a comment
Member
There was a problem hiding this comment.
Thank you! I fixed the changelog conflict 😊
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Move the two framework mixins —
MoneyRails::ActiveRecord::MonetizableandMoneyRails::ActionViewExtension— fromMoneyRails::Hooks.initto require time inlib/money-rails.rb.Why
Hooks.initis only called from the railtie initializer, and it is what registers theActiveSupport.on_load(:active_record)/on_load(:action_view)blocks. Outside a full Rails boot nothing registers them, somonetizeends up defined on no class at all:That makes the Active Record integration invisible to everything that inspects the code rather than boots a server: doc generators, editor autocomplete, static analysis, and a plain
require "money-rails"in a script or a test harness. It is the same class of problem as #614 / #727, whereMoneyRails::ActionViewExtensionwas unavailable until a callback happened to fire.Registering an
on_loadhook is lazy and cheap — it does not load Active Record or Action View, it only queues the block until something else loads them. So people using the gem without Rails (#470, #291) pay nothing for the registration, and getmonetizefrom the barerequire.require "active_support/lazy_load_hooks"is added explicitly rather than relying onmoney/monetizeto have pulled Active Support in;activesupportis already a runtime dependency.What stays put
The migration extensions stay in
Hooks.init. Choosing between the PostgreSQL and generic variants readsconnection_db_config, which needs a configured database — exactly what the railtie'safter: "active_record.initialize_database"guarantees, and not something a barerequirecan promise.Hooks.initremains public and its README-documented use for non-Rails apps is unchanged. The mixins it no longer performs are already registered by therequireit necessarily follows, and a repeatedincludeof the same module is a no-op regardless.No behavior change — Rails apps load the same modules into the same classes, in the same order.
Tested
bundle exec rake specgreen onactive_record7.0,7.1,7.2,8.0and8.1(Ruby 4.0), 278 examples each.bundle exec rubocopclean.money-railsbeforeactive_record, asserts the require did not eagerly load Active Record, then assertsmonetizeis there. It fails onmainand passes here.