【问题标题】:Call a nested method in a module's method在模块的方法中调用嵌套方法
【发布时间】:2015-09-15 21:08:46
【问题描述】:

我定义了以下模块,以及一个模块方法和一个嵌套在模块方法中的方法:

module RansackHelpers
  def self.split(attribute, model_class)
    def run(memo, model_class, attribute)
      # Code
    end
    run([], model_class, attribute)
  end
end

如何在self.split 中调用run?显然,它没有找到嵌套方法。

【问题讨论】:

  • def self.run(memo, model_class, attribute) 怎么样?
  • 确实如此。但是既然run嵌套在self.split上,那我为什么还要加上self呢?
  • 这种“嵌套”run 方法的目的是什么?
  • 这是一个在self.split内部触发的递归方法。我有它主要是因为我不想用固定属性调用self.split,例如[]

标签: ruby


【解决方案1】:

根据Metaprogramming Ruby 2

,Ruby 中有一个current class 概念

无论您在 Ruby 程序中的哪个位置,您总是有一个当前对象:self。同样,您总是有一个当前类(或模块)。由于 Ruby 解释器始终保持对当前类(或模块)的引用,因此当您定义一个方法时,该方法将成为当前类的实例方法。

它随着classmodule 关键字的变化而变化。

当您打开带有class 关键字的类(或带有module 关键字的模块)时,该类将成为当前类

所以在你的情况下,run 方法定义的当前类仍然是RansackHelpers,但不是RansackHelpers 的单例类。

在这里可以正常工作,

module RansackHelpers
  class << self
    def split(attribute, model_class)
      def run(memo, model_class, attribute)
        # Code
      end
      run([], model_class, attribute)
    end
  end
end

【讨论】:

    【解决方案2】:

    如果你想要一个“本地函数”,你可以用 lambdas 来模拟它。

    module RansackHelpers
      def self.split(attribute, model_class)
        run = ->(memo, model_class, attribute) do 
          # Code
        end
        run.call([], model_class, attribute)
      end
    end
    

    从这个例子来看,你为什么要这样做并不明显。如果它被定义并立即调用,您还不如直接执行函数体。如果要从外部使用,您应该创建一个普通的,而不是嵌套的方法。

    对于递归调用,这应该只是事情。

    【讨论】:

    • 我明白了。谢谢你的榜样!
    • 只是一个侧面说明:我如何从内部调用 lambda?
    【解决方案3】:

    There is no such thing as a nested method in Ruby。如果您在 split 之前调用 run,您将收到 NoMethod 错误。如果您调用 split 两次,您将收到警告:“警告:方法重新定义;丢弃旧运行。”

    您有一个方法split,它在调用时定义了另一个方法。

    【讨论】:

    • 也许我问错了。我不想从外部调用run,它只是从self.split 内部调用。我在上面的一个 cmets 中解释了我制作它的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 2013-01-03
    • 2017-06-03
    相关资源
    最近更新 更多