Похоже, у него должен быть простой ответ, но после долгого времени в Google и ТАК я не могу его найти.Это может быть случай отсутствия правильных ключевых слов.
В моем приложении RoR у меня есть несколько моделей, которые имеют специфический тип строкового атрибута, который имеет специальную проверку и другие функции.Ближайший похожий пример, который я могу вспомнить, - это строка, представляющая URL.
Это приводит к большому дублированию в моделях (и еще большему дублированию в модульных тестах), но я не уверен, как сделать его более СУХИМЫМ.
Я могу придуматьнесколько возможных направлений ...
- создать плагин по аналогии с плагином validates_url_format_of, но это только сделает валидации DRY
- для этой специальной строки своей собственной моделью,но это кажется очень тяжелым решением
- создать класс ruby для этой специальной строки, но как заставить ActiveRecord связать этот класс с атрибутом модели, который является строкой в базе данных db
Номер 3 кажется наиболее разумным, но я не могу понять, как расширить ActiveRecord для обработки чего-либо, кроме базовых типов данных.Любые указатели?
Наконец, если есть способ сделать это, где в иерархии папок вы бы поместили новый класс, который не является моделью?
Большое спасибо.
ОБНОВЛЕНИЕ :
Одно из возможных решений с использованием предложения Мэтта о миксине, приведенного ниже (и с использованием примера URL).Обратите внимание, что это ближе к psuedocode, чем к реальному ruby и предназначено для передачи принципа, а не совершенного синтаксиса.
Сначала создайте url
mixin:
module Url
def url_well_formed?
[...]
end
def url_live?
[...]
end
end
И в *Модель 1033 *, включите этот модуль:
Class Site < ActiveRecord:Base
include Url
validate :url_well_formed?
end
И когда мне нужно проверить, что сайт по URL-адресу работает, выполните ...
if site.url_live?
[...]
end
То, чего нетt решить, как сделать юнит-тесты сухими.Если у меня есть другая модель, скажем, Page
, которая также использует миксин Url
, ей все равно потребуется дубликат набора модульных тестов для URL.Конечно, я мог бы поместить их в помощник, но это кажется грязным.
Есть ли более фундаментальное решение, или это так хорошо, как оно получается?