Ruby: требуется или включать / расширять: использовать модуль внутри другого, но не показывать пользователям - PullRequest
0 голосов
/ 14 октября 2018

У меня возникли проблемы с пониманием ошибки при модульном тестировании моего модуля, который является миксином.

Предположим, что тестируемый миксин - это модуль A:

require 'path/b'    
module A
    def methodA()
        puts methodB.attr1 
    end
end

И это зависит отдругой миксин B, который был определен в файле по пути / b.rb

module B
    def methodB
       return someObject #that has property 'attr1'
    end       
end

Теперь у нас есть модуль для модульного тестирования A

require 'path/moduleA'
class TestA
    include Path::moduleA
end

describe 'test moduleA.methodA'
  it 'does something'
     testObject = TestA.new
     testObject.methodA()
     expect(....)
  end
end  

При запуске я получаю следующую ошибкутест rspec

NameError:
   undefined local variable or method `methodB' for #<TestA:0x00007f77a03db9a8>

Я могу решить его одним из следующих способов:

  1. , включая модуль B в модуле A
  2. , включая модуль B в классеTestA

Вопросы

  1. Мне не ясно, почему для получения доступа к methodB в модуле A и классе TestA требуется 'include'require 'уже был добавлен в модуль A.

  2. Мое намерение состоит в том, чтобы использовать методы модуля B в модуле A, но не позволять пользователям модуля A обращаться к методам модуля B автоматически.

    • Разрешение 1 выше предоставляет пользователям A доступ к методам B

    • Разрешение 2 вынуждает пользователей A (пользователь -> класс модульного тестированияв этом примере) включить зависимость A напрямую от B, даже если пользователь заинтересован только в доступе к методам A.

Следовательно, оба разрешения не достигают того, что яхочу.Есть ли способ достичь этого?

Я новичок в Ruby, так что, возможно, он этого не поддерживает.Я из Java-среды, где я бы смоделировал A и B как два класса, сделал бы экземпляр B в качестве поля A, а затем представил собственные публичные методы A для пользователей A. Но, поскольку они являются миксинами, мне нужно использовать модули врубин.

Ответы [ 3 ]

0 голосов
/ 15 октября 2018

Просто, чтобы быть очень явным: require / require_relative / load и include / extend / prepend не имеют абсолютно ничего общего друг с другом.

Первоетри просто запускают файл Ruby.Вот и все.Это все, что они делают.Они отличаются тем, как и где они ищут файл, но после того, как они нашли файл, они ничего не делают, кроме как просто выполняют его.

Последние три добавляют модуль в цепочку предков.include по существу делает модуль суперклассом, extend действительно совпадает с singleton_class.include (то есть делает модуль суперклассом класса singleton), а prepend вставляет модуль в начало цепи предка, то есть фактически до класса, к которому он добавлен.

0 голосов
/ 15 октября 2018

После еще одного поиска, я нашел ответ на свой 2-й вопрос, используя предложение из: https://makandracards.com/makandra/977-calling-selected-methods-of-a-module-from-another-module

, поэтому я сделал:

require 'path/b'
module A
   module B_RequiredMethods
       include Path::B
       module_function :methodB
   end

    def methodA
        puts B_RequiredMethods.methodB.attr1
    end
end

В моем случае можно было бы назвать B_RequiredMethodsправильно представлять метод B, который будет выставлен им.В идеале я бы сделал эти методы методами класса класса B, но им управляет какая-то другая команда.

0 голосов
/ 14 октября 2018

require просто говорит ruby ​​прочитать / загрузить код внутри файла ruby.В этом случае он просто определит модуль.Однако для того, чтобы код внутри модуля был включен в другой модуль или класс, вы должны include его внутри модуля или класса.Таким образом, вы должны сделать то же самое:

require 'path/b'    
module A
  include B
  def methodA()
    puts methodB.attr1 
  end
end

Вам не нужно менять тест с этим, так как модуль A уже включает в себя модуль B. Однако это не очень хороший шаблон проектирования ООП здесь.Но, надеюсь, вы понимаете, почему сейчас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...