Class: CurrentScope

Inherits:
ActiveSupport::CurrentAttributes
  • Object
show all
Defined in:
app/models/current_scope.rb

Overview

Class Method Summary collapse

Instance Method Summary collapse

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:

  1. 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.
  2. I18n.locale = prev_i18n_locale -- unconditional, since
    I18n.locale always returns a non-nil value. This restores the
    original thread-local value even when the caller entered with
    CurrentScope.locale and I18n.locale intentionally out of
    sync (e.g. legacy code that wrote I18n.locale directly while
    CurrentScope.locale was 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_idObject



31
32
33
# File 'app/models/current_scope.rb', line 31

def current_user_id
  user_id || user&.id
end

#employee_logged_in?Boolean

Returns:

  • (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. = user.
    PaperTrail.request.whodunnit = user.id
  else
    self.user_id = nil
    self. = nil
    PaperTrail.request.whodunnit = nil
  end
  super
end