Reputation: 880
What is Thread.current
for in this code? I'm looking at this example of using DCI in a Rails application. In lib/context.rb, there's this:
module Context
include ContextAccessor
def context=(ctx)
Thread.current[:context] = ctx
end
def in_context
old_context = self.context
self.context = self
res = yield
self.context = old_context
res
end
end
which is used in the various contexts in app/contexts, e.g.:
def bid
in_context do
validator.validate
biddable.create_bid
end
#...
end
What is the benefit of running the code in the in_context
block and setting a key-value pair on the current thread?
Upvotes: 0
Views: 149
Reputation: 121000
Generally, inside block you do not have an access to the caller’s context (besides closure variables.)
▶ class A
▷ attr_accessor :a
▷ def test
▷ yield if block_given?
▷ end
▷ end
#⇒ :test
▶ inst = A.new
#⇒ #<A:0x00000006f41e28>
▶ inst.a = 'Test'
#⇒ "Test"
▶ inst.test do
▷ puts self
▷ # here you do not have an access to inst at all
▷ # this would raise an exception: puts self.a
▷ end
#⇒ main
But with context you still might have an access to inst
from inside block:
▶ in_context do
▷ puts self.context.a
▷ end
#⇒ 'Test'
So, one might introduce the proc
(consider both A
and B
have Context
included):
▶ pr = ->() { puts self.context }
▶ A.new.in_context &pr
#⇒ #<A:0x00000006f41e28>
▶ B.new.in_context &pr
#⇒ #<B:0x00000006f41eff>
Now external proc
pr
has virtually full access to its caller.
Upvotes: 3
Reputation: 7655
Thread.current
is required to support multiple threading application, where each thread has its own context.
There is also ContextAccessor
module included, where one gets context. Putting them together just gives more clear picture:
# context.rb
def context=(ctx)
Thread.current[:context] = ctx
end
# context_accessor.rb
def context
Thread.current[:context]
end
The in_context
method is designed to safely change context inside its block. Whatever the changes were, the old context is restored when the block ends execution.
Upvotes: 2