Мне нужна условная проверка в некоторых частях моего приложения. Сейчас я использую следующую схему:Изменение правил валидации на лету
User.create
User::WithPassword.create
User::WithPhone.create
Было бы здорово, если бы я мог изменить поведение класса на лету, как это:
User.with_phone.with_password.create
Так что я попытался сделать это следующим образом:
class User < ActiveRecord::Base
validates :phone, presence: true, if: :phone_required?
def self.with_phone
define_method(:phone_required?) { true }
self
end
private
def phone_required?
false
end
end
Так он может быть использован как это, где это необходимо:
User.with_phone.create(user_params)
Проблема с этим подходом заключается в том, что все экземпляры Пользователя получают новое поведение после изменения фактического класса.
Есть ли способ вернуть только модифицированную копию класса User
с новым методом экземпляра phone_required?
, не затрагивая «базовый» класс?
Update
Спасибо за комментарии, как это было больше идей, требование в том, что я создаю пользователь без определенной проверки автоматически, а затем, когда они редактируют профиль, они имеют дело с нетронутой User
модели , Я создаю with_/without_
на лету в методе, который отсутствует при необходимости.
Вот моя следующая итерация:
class User < ActiveRecord::Base
validates :phone, presence: true, if: :phone_required?
def self.with_password
define_singleton_method(:password_required?) { true }
self
end
def password_required?
self.class.try :password_required?
end
end
Видимо это не лучше, как метод одноплодной остается там все время.
Пожалуйста, не делайте этого. Он летит перед лицом объектно-ориентированного дизайна, если вы не пытаетесь использовать шаблон «Работа за счет размытия обфускации». Почему бы не использовать флаг 'attr_accessor' или столбец первого класса, чтобы сохранить это логическое значение? Этот метод больше не будет отображаться, поэтому, когда вы попытаетесь перезаписать существующую запись, ваша проверка не удастся. – tadman
Благодарим вас за ввод, на самом деле мне нужен пользовательский класс только для времени создания. Я реорганизую это из модели User :: WithoutPassword. Я обновил исходный вопрос при создании метода singleton, чтобы он не загрязнял базовый класс. – firedev