Module: Briefly::Rails::DB

Defined in:
lib/briefly/rails/db.rb

Overview

Shortcut pack for a single database, reached through one Active Record class.

App = Briefly.define do
namespace(:db)  { use Briefly::Rails::DB }
namespace(:db2) { use Briefly::Rails::DB, base: "SecondaryApplicationRecord" }
end

App.db.txn { App.db.query("select * from users where id = ?", 1) }

base is a constant path, resolved on every call. Pass a String, not the class: a pack is +use+d from an initializer, where naming an autoloadable constant is what Rails warns about, and the captured class would go stale on the first code reload — permanently, since Reload clears memos, not closures. A Module is accepted for applications outside the autoloader, with that caveat.

Nothing here memoizes: a connection is leased from the pool, and query takes arguments. So the pack does not wire Reload, and works without a booted application.

Inside this file the framework is always ::Rails — bare Rails would resolve to the parent module.

Class Method Summary collapse

Class Method Details

.install(builder, base: "ApplicationRecord") ⇒ Briefly::Builder

Parameters:

  • builder (Briefly::Builder)
  • base (String, Symbol, Module) (defaults to: "ApplicationRecord")

    the Active Record class this database hangs off

Returns:



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/briefly/rails/db.rb', line 29

def install(builder, base: "ApplicationRecord")
  model = -> { base.is_a?(Module) ? base : Object.const_get(base) }

  builder.shortcut(:connection, :conn) { model.call.lease_connection }
  builder.shortcut(:transaction, :txn) { |**opts, &blk| model.call.transaction(**opts, &blk) }
  # `with_connection`, not `connection`: the latter is soft-deprecated, and raises outright under
  # `ActiveRecord.permanent_connection_checkout = :disallowed`.
  #
  # A bindless statement must skip `sanitize_sql_array`, which would fall through to its
  # `statement % values` branch and raise on any literal `%` — `... like '%foo%'`.
  #
  # No `**` parameter here, deliberately: taking no keywords is what makes Ruby pack
  # `query(sql, id: 1)` into `binds` as a trailing Hash, which is how named binds reach
  # `sanitize_sql_array`. A `**opts` would swallow them and send the statement unbound.
  builder.shortcut(:query) do |sql, *binds|
    record = model.call
    statement = binds.empty? ? sql : record.sanitize_sql_array([sql, *binds])
    record.with_connection { |connection| connection.exec_query(statement) }
  end
  builder
end