Files
simply_based/lib/simply_based/database_config.rb
GregandClaude Opus 4.8 86299b8827 SimplyBased 0.1.0 — Couchbase-native ActiveModel ORM
A from-scratch fork of simply_couch's model layer that runs on Couchbase
natively: `include SimplyBased::Model` instead of `include SimplyCouch::Model`.

- SimplyBased::Store replaces the CouchDB layer: KV documents, N1QL/SQL++
  finders + lazily-created GSIs, CAS mapped onto _rev. No design documents or
  JavaScript map/reduce — the hand-written association views become N1QL
  (belongs_to/has_many/has_one scalar FK; habtm via ANY ... SATISFIES + array
  index, or KV multi-get on the storing side).
- Redis replacements on the same cluster: Counter (atomic increment/decrement),
  Cache (ActiveSupport::Cache::Store over KV+TTL, drop-in Rails.cache/ActiveJob),
  Lock (insert-if-absent + TTL + CAS-checked release).
- Runs the simply_couch test suite against live Couchbase: 378/432 applicable
  examples green (CouchDB-mechanic specs tagged :couchdb_only and excluded).
- Remaining: ancestry (tree) + embedded_in reverse-lookups (recursive/embedded
  N1QL) and a few pagination/lifecycle edges.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 13:58:47 -05:00

69 lines
2.1 KiB
Ruby

# frozen_string_literal: true
require 'active_support/core_ext/module/attribute_accessors'
module SimplyBased
# Global Couchbase configuration.
#
# Set once at boot:
# SimplyBased.database_url =
# "couchbase://user:pass@localhost/my_bucket?scope=_default&collection=_default"
#
# Per-request override (multi-tenant): define a top-level Current class with a
# `couch_database` attribute and set `Current.couch_database =
# SimplyBased.database_for(...)`. Block-scoped: SimplyBased.with_database(db){}.
#
# Fallback chain for Model#database:
# 1. Model's own use_database URL
# 2. Current.couch_database (request-scoped)
# 3. SimplyBased.database_url (global default)
mattr_accessor :database_url
mattr_accessor :s3_defaults
# Load S3 defaults from a YAML config file with ERB support.
def self.load_s3_config(path, env = nil)
env ||= defined?(Rails) ? Rails.env : 'development'
raw = File.read(path.to_s)
yaml = defined?(ERB) ? ERB.new(raw).result : raw
config = YAML.safe_load(yaml, permitted_classes: [], permitted_symbols: [], aliases: true) || {}
self.s3_defaults = (config[env] || {}).deep_symbolize_keys
end
# Returns a Store for the given Couchbase connection URL, cached by URL.
def self.database_for(url)
return nil unless url
databases[url] ||= Store.new(url)
end
def self.database
current_database || database_for(database_url) || fallback_database
end
def self.with_database(database)
previous = current_database
self.current_database = database
yield
ensure
self.current_database = previous
end
def self.current_database
defined?(::Current) && ::Current.respond_to?(:couch_database) ? ::Current.couch_database : nil
end
def self.current_database=(db)
::Current.couch_database = db if defined?(::Current) && ::Current.respond_to?(:couch_database=)
end
private
def self.databases
@_databases ||= {}
end
def self.fallback_database
database_for(ENV['COUCHBASE_URL'] || 'couchbase://Administrator:password@localhost/simply_based')
end
end