为什么围绕Ruby方法的类似Rails的回调不起作用?

时间:2016-03-13 15:58:48

标签: ruby-on-rails ruby

class Callbacks
  def self.before_actions
    @before_actions ||= []
  end

  def self.before_action(callback)
    before_actions << callback
  end

  def self.inherited(child_class)
    before_actions.each { |f| child_class.before_actions << f }
    after_actions.each { |f| child_class.after_actions << f }
  end

  def execute(action)
    self.class.before_actions.each { |callback| send(callback) }
    send(action)
    self.class.after_actions.each { |callback| send(callback) }
  end
end

class Test < Callbacks
  before_action :hello

  def heraks
    puts "heraks"
  end

  private

  def hello
    puts "Hello"
  end
end

Test.new.execute(:heraks)

这样做有效,但如果我写@before_actions = []而没有||,那么它就不起作用。

如果我改变回调的存储方式:

@@callbacks = []
def self.before_actions(action)
  @@callbacks << action
end

它有效。

我使用了byebug并检查Test.before_actions == []before_action :hello是否未添加到数组中。

他们之间有什么区别?这是一个错误吗?

1 个答案:

答案 0 :(得分:1)

当您使用类实例变量(multipart_data = MultipartEncoder( fields=( ('action', 'ingest'), ('item', 'spam'), ('item', 'sausage'), ('item', 'eggs'), ) ) )并且@before_actions使用self.before_actions时,您的代码可以正常工作;细

||=使用self.before_actions代替=时,您的代码会失败,因为每次拨打||=时,它都会将before_actions重置为@before_actions。没有回调将保持足够长的时间来做任何事情。

您使用类变量([])的代码版本有效,因为您只在访问者之外初始化@@callbacks一次。但是,只要有@@callbacks的两个子类Callbacks并且它的子类将共享相同的Callbacks,您就会遇到问题,因此您将无法有所不同具有不同回调的子类。