Class: CurrentScope
- Inherits:
-
ActiveSupport::CurrentAttributes
- Object
- ActiveSupport::CurrentAttributes
- CurrentScope
- Defined in:
- app/models/current_scope.rb
Overview
Class Method Summary collapse
-
.with_locale(locale) ⇒ Object
Block-scoped locale override that restores both CurrentScope.locale and I18n.locale on exit, even if the block raises.
- .with_user_id(user_id) ⇒ Object
Instance Method Summary collapse
- #current_user_id ⇒ Object
- #employee_logged_in? ⇒ Boolean
-
#locale=(locale) ⇒ Object
Setter override: keep CurrentScope.locale and I18n.locale in lock-step.
- #user=(user) ⇒ Object
Class Method Details
.with_locale(locale) ⇒ Object
Block-scoped locale override that restores both CurrentScope.locale and
I18n.locale on exit, even if the block raises. Mirrors with_user_id.
Useful in workers, helpers, and other non-controller code that needs
to render in a different locale temporarily without affecting the rest
of the request/job.
Snapshot the two slots independently. Folding them together with
prev_locale = CurrentScope.locale || I18n.locale loses the
distinction between "CurrentScope was unset" and "CurrentScope had a
value", and the ensure block would write I18n.locale back into
CurrentScope.locale, leaving the slot dirty.
On exit, BOTH slots are restored from their own snapshots:
CurrentScope.locale = prev_current_scope_locale-- the setter
mirrors to I18n.locale whenever the prior CurrentScope was non-
nil. That mirror would clobber the I18n snapshot, so step 2
immediately overwrites it.I18n.locale = prev_i18n_locale-- unconditional, since
I18n.localealways returns a non-nil value. This restores the
original thread-local value even when the caller entered with
CurrentScope.localeandI18n.localeintentionally out of
sync (e.g. legacy code that wroteI18n.localedirectly while
CurrentScope.localewas unset, or vice versa).
Order matters: I18n must be restored AFTER CurrentScope so the
setter's mirror does not silently undo it.
106 107 108 109 110 111 112 113 114 |
# File 'app/models/current_scope.rb', line 106 def self.with_locale(locale, &) prev_current_scope_locale = CurrentScope.locale prev_i18n_locale = I18n.locale CurrentScope.locale = locale if locale I18n.with_locale(locale || prev_i18n_locale, &) ensure CurrentScope.locale = prev_current_scope_locale I18n.locale = prev_i18n_locale end |
.with_user_id(user_id) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'app/models/current_scope.rb', line 52 def self.with_user_id(user_id) prev_user_id = CurrentScope.current_user_id # If a user id was not passed in, we have to default to something user_id ||= CurrentScope.current_user_id begin PaperTrail.request.whodunnit = user_id || prev_user_id CurrentScope.user_id = user_id || prev_user_id yield ensure CurrentScope.user_id = prev_user_id PaperTrail.request.whodunnit = prev_user_id end end |
Instance Method Details
#current_user_id ⇒ Object
31 32 33 |
# File 'app/models/current_scope.rb', line 31 def current_user_id user_id || user&.id end |
#employee_logged_in? ⇒ Boolean
35 36 37 |
# File 'app/models/current_scope.rb', line 35 def employee_logged_in? user.is_a?(Employee) end |
#locale=(locale) ⇒ Object
Setter override: keep CurrentScope.locale and I18n.locale in lock-step.
I18n.locale is a thread-local on Thread.current. Without explicit reset
it leaks across requests reusing the same Puma thread. Routing every
locale write through CurrentScope (which is reset between requests by
ActionDispatch::Executor and between Sidekiq jobs by the Sidekiq
CurrentAttributes integration) plus the before_reset hook below
establishes a single source of truth.
74 75 76 77 78 |
# File 'app/models/current_scope.rb', line 74 def locale=(locale) sym = locale&.to_sym I18n.locale = sym if sym super(sym) end |
#user=(user) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'app/models/current_scope.rb', line 39 def user=(user) if user self.user_id = user.id self.account = user.account PaperTrail.request.whodunnit = user.id else self.user_id = nil self.account = nil PaperTrail.request.whodunnit = nil end super end |