Module: Rhino::Context

Defined in:
lib/rhino/context.rb

Overview

Ambient tenant context resolver.

Reads the current user/organization from RequestStore by default (request-time context set by the controller before_actions), but can be overridden for the duration of a block via with — used by the explicit query builder so jobs, rake tasks, and tests can query without a route.

Class Method Summary collapse

Class Method Details

.organizationObject

The active organization: the explicit override if one is in effect, else the request-time organization from RequestStore.



15
16
17
18
19
20
21
# File 'lib/rhino/context.rb', line 15

def organization
  if store.key?(:rhino_organization)
    store[:rhino_organization]
  elsif defined?(RequestStore)
    RequestStore.store[:rhino_organization]
  end
end

.storeObject

Fiber-local override store for the active explicit context.



84
85
86
# File 'lib/rhino/context.rb', line 84

def store
  Thread.current[:rhino_context_override] ||= {}
end

.userObject

The active user: the explicit override if one is in effect, else the request-time user from RequestStore.



25
26
27
28
29
30
31
# File 'lib/rhino/context.rb', line 25

def user
  if store.key?(:rhino_current_user)
    store[:rhino_current_user]
  elsif defined?(RequestStore)
    RequestStore.store[:rhino_current_user]
  end
end

.with(user:, organization:) ⇒ Object

Run block with the given user/organization installed into RequestStore. Snapshots the prior RequestStore user+org, sets the new ones, yields, and restores the snapshot in an ensure. Returns the block's value.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rhino/context.rb', line 36

def with(user:, organization:)
  return yield unless defined?(RequestStore)

  had_user = RequestStore.store.key?(:rhino_current_user)
  had_org  = RequestStore.store.key?(:rhino_organization)
  prev_user = RequestStore.store[:rhino_current_user]
  prev_org  = RequestStore.store[:rhino_organization]

  # Track the active override so Context.user/organization prefer it even when
  # the passed value is nil (distinguishing "explicitly nil" from "absent").
  had_override_user = store.key?(:rhino_current_user)
  had_override_org  = store.key?(:rhino_organization)
  prev_override_user = store[:rhino_current_user]
  prev_override_org  = store[:rhino_organization]

  RequestStore.store[:rhino_current_user] = user
  RequestStore.store[:rhino_organization] = organization
  store[:rhino_current_user] = user
  store[:rhino_organization] = organization

  begin
    yield
  ensure
    if had_user
      RequestStore.store[:rhino_current_user] = prev_user
    else
      RequestStore.store.delete(:rhino_current_user)
    end
    if had_org
      RequestStore.store[:rhino_organization] = prev_org
    else
      RequestStore.store.delete(:rhino_organization)
    end

    if had_override_user
      store[:rhino_current_user] = prev_override_user
    else
      store.delete(:rhino_current_user)
    end
    if had_override_org
      store[:rhino_organization] = prev_override_org
    else
      store.delete(:rhino_organization)
    end
  end
end