Class: Railsmith::Context
- Inherits:
-
Object
- Object
- Railsmith::Context
- Defined in:
- lib/railsmith/context.rb
Overview
Immutable value object for propagating request context through service calls. Accepts domain: plus any number of extra keyword args (actor_id, request_id, etc.) stored at the top level — no nested :meta hash needed.
Example:
ctx = Railsmith::Context.new(domain: :billing, actor_id: 42)
BillingService.call(action: :create, params: params, context: ctx.to_h)
Accessing extras:
ctx[:actor_id] # => 42
ctx.to_h # => { current_domain: :billing, actor_id: 42 }
Direct Known Subclasses
Instance Attribute Summary collapse
-
#domain ⇒ Object
readonly
Returns the value of attribute domain.
Class Method Summary collapse
-
.build(context) ⇒ Object
Coerces any context-like value into a
Contextinstance. -
.current ⇒ Object
Returns the thread-local
Contextset by.with, ornil. -
.current=(ctx) ⇒ Object
Sets the thread-local
Contextdirectly. -
.normalize_current_domain(value) ⇒ Object
Normalizes a domain value to a Symbol (or nil for blank/nil input).
-
.with(context = nil, **kwargs) ⇒ Object
Runs
blockwith a thread-local context built from the given kwargs (or an existingContextinstance).
Instance Method Summary collapse
-
#[](key) ⇒ Object
Accesses extra keys by symbol.
-
#blank_domain? ⇒ Boolean
Returns true when no domain has been set.
-
#current_domain ⇒ Object
Backward-compatible reader — returns the same value as
domain. -
#initialize(domain: nil, current_domain: nil, **extras) ⇒ Context
constructor
A new instance of Context.
-
#request_id ⇒ Object
Returns the request ID (auto-generated UUID if not supplied at construction).
-
#to_h ⇒ Object
Serializes to a plain hash.
Constructor Details
#initialize(domain: nil, current_domain: nil, **extras) ⇒ Context
Returns a new instance of Context.
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/railsmith/context.rb', line 95 def initialize(domain: nil, current_domain: nil, **extras) if !current_domain.nil? && domain.nil? warn "[DEPRECATION] Railsmith::Context: `current_domain:` is deprecated; use `domain:` instead." domain = current_domain end @domain = self.class.normalize_current_domain(domain) extras[:request_id] ||= SecureRandom.uuid @extras = extras.freeze freeze end |
Instance Attribute Details
#domain ⇒ Object (readonly)
Returns the value of attribute domain.
107 108 109 |
# File 'lib/railsmith/context.rb', line 107 def domain @domain end |
Class Method Details
.build(context) ⇒ Object
Coerces any context-like value into a Context instance.
-
Context→ returned as-is -
nilor {} →Context.newwith auto-generatedrequest_id -
Hash → deep-duped and wrapped in
Context.new;:current_domainis remapped to:domainso the deprecated alias path is never triggered
63 64 65 66 67 68 69 70 71 72 |
# File 'lib/railsmith/context.rb', line 63 def self.build(context) case context when Context context when Hash build_from_hash(context) else new end end |
.current ⇒ Object
Returns the thread-local Context set by .with, or nil.
22 23 24 |
# File 'lib/railsmith/context.rb', line 22 def self.current Thread.current[THREAD_KEY] end |
.current=(ctx) ⇒ Object
Sets the thread-local Context directly. Prefer .with for scoped use.
27 28 29 |
# File 'lib/railsmith/context.rb', line 27 def self.current=(ctx) Thread.current[THREAD_KEY] = ctx end |
.normalize_current_domain(value) ⇒ Object
Normalizes a domain value to a Symbol (or nil for blank/nil input).
84 85 86 87 88 89 90 |
# File 'lib/railsmith/context.rb', line 84 def self.normalize_current_domain(value) return nil if value.nil? return nil if value.is_a?(String) && value.strip.empty? return value if value.is_a?(Symbol) value.respond_to?(:to_sym) ? value.to_sym : value end |
.with(context = nil, **kwargs) ⇒ Object
Runs block with a thread-local context built from the given kwargs (or an existing Context instance). Restores the previous value afterwards, even if the block raises.
Railsmith::Context.with(domain: :web, actor_id: 42) do
UserService.call(action: :create, params: { ... })
end
38 39 40 41 42 43 44 45 46 47 |
# File 'lib/railsmith/context.rb', line 38 def self.with(context = nil, **kwargs) ctx = thread_context_from(context, **kwargs) previous = current self.current = ctx begin yield ensure self.current = previous end end |
Instance Method Details
#[](key) ⇒ Object
Accesses extra keys by symbol.
120 121 122 123 124 125 |
# File 'lib/railsmith/context.rb', line 120 def [](key) sym = key.to_sym return @domain if %i[current_domain domain].include?(sym) @extras[sym] end |
#blank_domain? ⇒ Boolean
Returns true when no domain has been set.
128 129 130 |
# File 'lib/railsmith/context.rb', line 128 def blank_domain? @domain.nil? end |
#current_domain ⇒ Object
Backward-compatible reader — returns the same value as domain.
115 116 117 |
# File 'lib/railsmith/context.rb', line 115 def current_domain @domain end |
#request_id ⇒ Object
Returns the request ID (auto-generated UUID if not supplied at construction).
110 111 112 |
# File 'lib/railsmith/context.rb', line 110 def request_id @extras[:request_id] end |
#to_h ⇒ Object
Serializes to a plain hash. Uses :current_domain as the domain key for backward compatibility with services that read context[:current_domain] directly.
135 136 137 |
# File 'lib/railsmith/context.rb', line 135 def to_h { current_domain: @domain }.merge(@extras) end |