Module: StrictLazy
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/strict_lazy.rb,
lib/strict_lazy/batch.rb,
lib/strict_lazy/errors.rb,
lib/strict_lazy/facade.rb,
lib/strict_lazy/loader.rb,
lib/strict_lazy/railtie.rb,
lib/strict_lazy/version.rb,
lib/strict_lazy/preloader.rb
Overview
strict_lazy applies the spirit of Rails’ strict_loading to computed values. Include it in a model, declare values with lazy_load, prepare them in the controller with StrictLazy.preload, and read them via record.lazy.x. Reading without a preceding preload raises in development/test.
Defined Under Namespace
Classes: Batch, Error, Facade, Loader, Preloader, Railtie, UnloadedError
Constant Summary collapse
- VALID_VIOLATIONS =
The accepted violation policies.
%i[raise log ignore].freeze
- READER_FORMAT =
A valid reader is a bare name, optionally a ‘?` predicate. Setter (`=`), bang (`!`), and operator readers are rejected: the `.lazy` namespace is read-only, and any other form has no valid ivar to back it.
/\A[A-Za-z_][A-Za-z0-9_]*\??\z/- VERSION =
"0.4.0"
Class Method Summary collapse
-
.preload(records, *spec) ⇒ Object
Prepare lazy values for a group of records.
-
.violation ⇒ Object
The effective policy for the current execution context: the innermost with_violation override if any, otherwise the global baseline.
-
.violation=(mode) ⇒ Object
Backward-compatible global setter.
-
.with_violation(mode) ⇒ Object
Run the block with
modeas the effective policy, restoring the previous state afterward (exception-safe).
Instance Method Summary collapse
-
#lazy ⇒ Object
The
.lazynamespace facade (memoized per record).
Class Method Details
.preload(records, *spec) ⇒ Object
Prepare lazy values for a group of records.
The spec is a Rails-style list (mirroring ActiveRecord’s preload): each element is either a reader name (Symbol) prepared on the given records, or a Hash whose keys are associations to traverse and whose values are the spec to apply recursively to the associated records. A Hash value may itself be a Symbol, a Hash, or an array mixing both — so a single level can prepare its own readers and descend into nested associations at once:
StrictLazy.preload(posts,
:comments_count, # reader on posts
comments: [:score, { replies: :like_count }] # reader on comments + nested
)
With no spec at all, every declared loader on the records is prepared. sync: true loaders resolve immediately; others on first read.
Records may mix classes (e.g. STI subtrees, or children gathered across associations): they are grouped by their STI base class so each loader’s resolver runs once per declaring class.
155 156 157 |
# File 'lib/strict_lazy.rb', line 155 def self.preload(records, *spec) Preloader.call(records, spec) end |
.violation ⇒ Object
The effective policy for the current execution context: the innermost with_violation override if any, otherwise the global baseline. The facade consults this — never read default_violation directly.
98 99 100 |
# File 'lib/strict_lazy.rb', line 98 def self.violation (violation_overrides || []).last || default_violation end |
.violation=(mode) ⇒ Object
Backward-compatible global setter. Sets the baseline only; it does not touch any active with_violation override. Existing callers (and the Railtie) keep working unchanged.
105 106 107 |
# File 'lib/strict_lazy.rb', line 105 def self.violation=(mode) self.default_violation = validate_violation!(mode) end |
.with_violation(mode) ⇒ Object
Run the block with mode as the effective policy, restoring the previous state afterward (exception-safe). Overrides nest; an inner call shadows an outer one and unwinds cleanly. Scoped to the current Fiber/Thread, so parallel test processes never interfere.
StrictLazy.with_violation(:ignore) { ... } # never raises inside
115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/strict_lazy.rb', line 115 def self.with_violation(mode) # Validate first: an invalid mode raises here, before the stack is touched, # so the begin/ensure only ever runs against a successfully pushed frame. validated = validate_violation!(mode) begin pushed = (violation_overrides || []) + [validated] self.violation_overrides = pushed yield ensure self.violation_overrides = pushed[0...-1] end end |