【问题标题】:What is Thread.current for in the DCI in Ruby example?Ruby 示例中的 DCI 中的 Thread.current 是什么?
【发布时间】:2015-11-27 14:28:26
【问题描述】:

这段代码中的Thread.current 是什么意思?我正在查看this 在 Rails 应用程序中使用 DCI 的示例。在 lib/context.rb 中,有这样的:

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

在应用程序/上下文中的各种上下文中使用,例如:

def bid
  in_context do
    validator.validate
    biddable.create_bid
  end
  #...
end

in_context 块中运行代码并在当前线程上设置键值对有什么好处?

【问题讨论】:

  • 它基本上是一个全局变量。只有线程安全。

标签: ruby-on-rails ruby dci


【解决方案1】:

通常,在块内部,您无法访问调用者的上下文(除了闭包变量。)

▶ 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

但是根据上下文,您仍然可以从块内部访问inst

▶ in_context do 
▷   puts self.context.a
▷ end
#⇒ 'Test'

因此,可以引入proc(考虑AB 都包含Context):

▶ pr = ->() { puts self.context }
▶ A.new.in_context &pr
#⇒ #<A:0x00000006f41e28>
▶ B.new.in_context &pr
#⇒ #<B:0x00000006f41eff>

现在外部proc pr 几乎可以完全访问其调用者

【讨论】:

    【解决方案2】:

    Thread.current 需要支持多线程应用程序,其中每个线程都有自己的上下文。

    还包括ContextAccessor module,其中包含上下文。将它们放在一起只会给出更清晰的画面:

    # context.rb
    def context=(ctx)
      Thread.current[:context] = ctx
    end
    
    # context_accessor.rb
    def context
      Thread.current[:context]
    end
    

    in_context 方法旨在安全地更改其块内的上下文。无论更改是什么,当块结束执行时,旧的上下文都会恢复。

    【讨论】:

      猜你喜欢
      • 2022-11-23
      • 2020-08-05
      • 2010-09-17
      • 2012-03-29
      • 2014-01-04
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多