是否有可能知道Ruby类何时完成链接方法?

qlzsbp2j  于 2023-04-29  发布在  Ruby
关注(0)|答案(1)|浏览(74)

我试图确定在Ruby中是否有可能确定一个方法链何时完成调用。
假设我有一个从数据库中检索信息的类。我通常只想调用类的一个示例来访问所有包含的数据,但在很多情况下,我会链接附加的方法来应用过滤器等。目前,实际的数据检索是由一个总是最后调用的方法执行的,如下所示:

all_data = data_retriever.run
filtered_data = data_retriever.condition({k1: v1}).run
filtered_data = data_retriever.condition({k1: v1}).condition({k2: v2}).run

这很好用,但我不禁想到Ruby可能有办法做到这一点,而不必在每次使用结束时都添加.run这样的方法。我的类有可能“知道”我什么时候完成了方法链接吗?比如在所有链接的方法被调用后执行的钩子?

class DataRetriever 
  @conditions = {}
  def initialize()
  end
 
  def condition(condition_hash)
    @conditions << condition_hash
  end

  #...

  def after_chains
    # run the data retrieval code using the contents of @conditions
  end
end
dced5bon

dced5bon1#

我的类有可能“知道”我什么时候完成了方法链接吗?
不,链接方法等同于一个接一个地调用它们。被调用的方法无法区分调用样式。这实际上是好的,考虑以下几点:

retriever = data_retriever.condition({k1: v1})
retriever.condition({k2: v2}) if something
retriever.condition({k3: v3}) if something_else
data = retriever.run

在上面的示例中,您可能不希望第一行已经触发了数据检索。
Ruby可能有一种方法来做到这一点,而无需在每次使用结束时都添加类似.run的方法
除了run之外,您还可以使用一个更微妙的入口点来触发执行。each是Ruby的默认枚举方法:

data = data_retriever.condition({k1: v1})

data.each do |entry|
  # ...
end

发动机罩下:(有多种方法可以实现这一点)

class DataRetriever
  def run
    @data = # retrieve actual data
  end

  def each(&block)
    run unless @data
    
    @data.each(&block)
  end
end

只要确保在添加更多条件时使@data无效(或者freezerun之后的对象)。
你甚至可以从inspect调用each:(您可能需要缩写长数据)

class DataRetriever
  def inspect
    "#<DataRetriever data=#{each.to_a.inspect}>"
  end
end

在IRB中:

filtered_data = DataRetriever.new.condition({k1: v1})
#=> #<DataRetriever data=[1, 2, 3]>

相关问题