'include'-ing一个模块,还是调用不了方法

'include'-ing a module, but still can't call the method

为什么下面的代码会报下面的错误?

require 'open3'

module Hosts
  def read
    include Open3
    popen3("cat /etc/hosts") do |i,o,e,w|
      puts o.read
    end
  end
end

Hosts.read
#=> undefined method `popen3' for Hosts:Class (NoMethodError)

如果我使用完整路径调用 popen3,它会起作用,即 Open3::popen3。但是我已经 include-ed 它了,所以我认为我不需要 Open3:: 位?

谢谢

您已经定义了一个实例方法,但正试图将其用作单例方法。为了让你想要的成为可能,你还必须 extend Open3,而不是 include:

module Hosts
  extend Open3

  def read
    popen3("cat /etc/hosts") do |i,o,e,w|
      puts o.read
    end
  end
  module_function :read # makes it available for Hosts
end

现在:

Hosts.read
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1             localhost
=> nil

阅读 Ruby 中的以下概念将使您更加清楚:

  • 上下文

  • self

  • include 对比 extend

代替module_fuction,您也可以使用以下任一方法获得相同的结果:

module Hosts
  extend Open3
  extend self

  def read
    popen3("cat /etc/hosts") do |i,o,e,w|
      puts o.read
    end
  end
end

module Hosts
  extend Open3

  def self.read
    popen3("cat /etc/hosts") do |i,o,e,w|
      puts o.read
    end
  end
end