2015-10-06 6 views
0

У меня есть случай, когда у меня есть методы класса, доступные в классе, исходя из того, включает ли этот класс модуль. Например:Проверка метода входящего класса, который может отсутствовать

class HomePage 
    include Symbiont 

    url_matches 'test' 
end 

class WeightPage 
    include Symbiont 
end 

Вот когда Симбионт включен, он предоставляет метод класса под названием url_matches. Обратите внимание, однако, что вам не нужно использовать это, как показывает WeightPage. Таким образом, в то время как Symbiont делает этот метод доступным, класс, который включает Symbiont, не должен его использовать.

В этом случае:Что я хочу сделать, это проверить, действительно ли класс использует его.

Но я не могу понять, как. Так что давайте говорить, что я это сделать:

@home = HomePage.new 
@weight = WeightPage.new 

Я хочу быть в состоянии сделать что-то вроде этого:

@home.respond_to?(:url_matches) # should return true 
@weight.respond_to?(:url_matches) # should return false 

Это не работает. Оба возвращают false. Затем я попробовал это по классу:

@home.class.respond_to?("url_matches") 
@weight.class.respond_to?("url_matches") 

Это всегда возвращает true.

Я попытался это:

@home.class.public_instance_methods.include?(:url_matches) 
@weight.class.public_instance_methods.include?(:url_matches) 

Всегда возвращает ложь.

@home.class.method_defined?(:url_matches) 
@weight.class.method_defined?(:url_matches) 

Всегда возвращает false.

На данный момент я не уверен, что делать.

исходный код Context

код в контексте может быть немного трудно следовать для целей данного вопроса, а просто предоставить ему:

Вот модуль «Симбионт», который получает включены :

https://github.com/jnyman/symbiont/blob/master/lib/symbiont.rb

Примечание в частности этой части:

module Symbiont 
    def self.included(caller) 
    caller.extend Symbiont::Assertion 

симбионта :: Утверждение здесь:

https://github.com/jnyman/symbiont/blob/master/lib/symbiont/assertions.rb

Вот где url_matches приходит. Поэтому, когда Symbiont включен в класс, как показано выше, это то, что позволяет объявлять url_matches в классе.

ответ

1

Вы добавляете этот метод url_matches к обоим классам только путем включения в них обоих Symbiont.

Это сказало: вас не интересует, отвечает ли класс этому методу, но если был вызван метод. Если вы посмотрите на implementation of that method, вы увидите, что этот метод устанавливает переменную @url_match. Поэтому вы должны задать вопрос: был ли установлен набор @url_match?

Это может быть достигнуто с помощью instance_variable_get:

@home.class.instance_variable_get(:@url_match) 
@weight.class.instance_variable_get(:@url_match) 
+0

Не уверен, что это хорошая идея. '@ url_match', похоже, является деталью реализации, которая не должна быть просочилась в ваш код. – Magnuss

+0

@Magnuss Хорошая точка, но на самом деле логика, которую я здесь делаю, является частью другого класса внутри этого кода. Я не упоминал об этом, чтобы не усложнять ситуацию. Я пытаюсь выполнить код, указанный в ответе; будет обновляться, если он выглядит хорошо. Пока все признаки положительные. –

+0

@Magnuss: Я согласен с вами, '@ url_match' является деталью реализации, и, вероятно, это плохая идея использовать эту переменную за пределами драгоценного камня. Но проверка этой переменной, по-видимому, единственная опция на данный момент, поскольку ОП не сказал нам, почему он должен знать, был ли вызван этот метод, и поскольку этот камень не предлагает другого варианта. – spickermann

0

насчет

expect(HomePage).to respond_to(:url_matches) 

?

0

Мои 2 цента: Я думаю, я бы залатать метод url_matches, так что при вызове, она устанавливает переменную класса @@symbiont_enabled в true, и я бы добавьте другой метод класса, который будет выглядеть примерно так:

def self.symbiont_enabled? 
    @@symbiont_enabled 
end 
+0

Я думал о том же самом – Roko

Смежные вопросы