Я пытаюсь разработать приложение, которое может представлять один и тот же ресурс разным пользователям и где ресурс может по-разному проверять поведение в зависимости от пользователя.
Я пытался использовать метапрограммирование Ruby, чтобы легко решить эту проблему, но, похоже, мне не хватает некоторых ключевых знаний по этому вопросу.
Я могу привести пример такой модели, как
class Profile < ActiveRecord::Base
# validates_presence_of :string1
end
Модель имеет свойство 'string1', которое иногда требуется, а иногда нет. Я хотел бы создать подклассы для каждого пользователя (по причинам, не очевидным в этом упрощении) и создал модуль, который я хотел бы включить:
module ExtendProfile
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def configure_validation(required)
if required
class_eval("ActiveRecord::Base.validates_presence_of :string1")
end
end
end
end
Его единственная цель - добавить метод, который добавляет условную валидацию на основе приведенных аргументов.
Он добавляет проверку при вызове с аргументом, который является истинным, но не делает это чисто. Похоже, что он не разделяет подклассы, как я думал, что будет.
Это можно проиллюстрировать следующими тестами:
profile = Profile.new
profile.save; profile.errors
=> []
Профиль по умолчанию может быть сохранен без ошибок.
Object::const_set('FirstExtendedProfile'.intern, Class::new(Profile) { include ExtendProfile })
FirstExtendedProfile.configure_validation(true)
fep = FirstExtendedProfile.new; fep.save; fep.errors
=> {:string1=>["skal udfyldes", "skal udfyldes"]}
Создание нового подкласса и вызов configuring_validation
добавляет проверку, но по какой-то причине она вызывается дважды во время проверки («skal udfyldes» - это датский язык и означает, что это требуется).
Object::const_set('SecondExtendedProfile'.intern, Class::new(Profile) { include ExtendProfile })
sep = SecondExtendedProfile.new; sep.save; sep.errors
=> {:string1=>["skal udfyldes"]}
Создается еще один потомок, и хотя configure_validation
не вызывается, он все равно проверяет свойство string1
(но теперь только один раз).
Добавление еще одного потомка и вызов configure_validation
добавляет проверку еще раз ...
Почему я не могу добавить проверку для определенного потомка профиля?
Я использую Ruby 1.9.2 и Rails 3.06. Пожалуйста, поймите, что я хотел бы понять, как заставить это создание динамического класса работать - я знаю о "стандартной" пользовательской проверке.