"включить" модуль, но все еще не может вызвать метод

Почему следующий код дает ошибку ниже?

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Он думал, что мне не понадобится Open3:: немного?

Спасибо

1 ответ

Решение

Вы определили метод экземпляра, но пытаетесь использовать его как одноэлементный метод. Чтобы сделать то, что вы хотите, вы также должны 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
Другие вопросы по тегам