Согласование классовых контрактов в Ruby - PullRequest
1 голос
/ 10 февраля 2012

Ядром моего приложения является механизм, который принимает спецификацию проблемы, кодируется как структура данных и генерирует необходимые результаты. Существует два способа создания структуры данных spec: путем анализа скрипта или через пользовательский интерфейс Rails. В случае Rails структура данных - это объекты модели в БД, в случае сценария - это экземпляр класса модели в памяти. Движок находится в отдельном геме, так что процесс, управляемый сценариями, может запускаться автономно без необходимости использования Rails.

Мой вопрос заключается в том, как обеспечить, чтобы две структуры данных, модель БД Rails и модель в памяти, выполняли один и тот же контракт. Если бы это была Java, я бы написал интерфейс, который реализовали бы оба класса моделей, но в Ruby я полагаюсь на типизацию утиной утилитой. У меня будут тесты для каждой модели, но было бы более СУХОЕ иметь только один набор тестов. Однако я не понимаю, как разделить тесты между проектом gem и проектом rails.

Основная проблема: предположим, что я добавляю ответственность к модели Rails, как я могу гарантировать, что соответствующая ответственность будет добавлена ​​к модели памяти скриптов, или наоборот?

1 Ответ

1 голос
/ 10 февраля 2012

Полагаю, вам следует создать модуль, в обязанности которого входит проверка того, что класс получателя содержит требуемые методы.

Примерно так:

module Contract
  STATIC_METHODS   = [ :class_foo ]
  INSTANCE_METHODS = [ :instance_foo ]

  def self.included(receiver)
    STATIC_METHODS.each do |method|
      raise("missing class method #{method}") unless receiver.respond_to? method
    end
    INSTANCE_METHODS.each do |method|
      raise("missing instance method #{method}") unless receiver.instance_methods.include? method.to_s
    end
  end
end

class YourClass
  def self.class_foo
  end

  def instance_foo

  end

  include Contract
end

Остерегайтесь включить Contract в конце вашего файла в противном случае он логически завершится неудачей (методы не будут определены).

Что касается ваших тестов, вам следует создать несколько общих тестов и запустить их в ваших классах с чем-то вроде: it_should_behave_like

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