Проверка вложенных моделей?
-
05-07-2019 - |
Вопрос
Чтобы быть более конкретным, " Как проверить, что для модели требуется создать как минимум x допустимых связанных моделей? " . Я пытался проверить вложенные модели, которые создаются в той же форме, что и родительский (и в конечном итоге показывают немедленные проверки в виде jQuery). В качестве популярного примера рассмотрим следующие модели и схемы.
class Project
include DataMapper::Resource
property :id, Serial
property :title, String, :nullable => false
has 2..n, :tasks
end
class Task
include DataMapper::Resource
property :id, Serial
property :project_id, Integer, :key => true
property :title, String, :nullable => false
belongs_to :project
end
Как вы видите, все проверки выполняются в определениях схемы. Важным здесь является то, что имеет 2..n,: tasks
" ;. Эта проверка на самом деле работает нормально, учитывая, что вложенные атрибуты задач в хэше params будут генерировать valid задачи. Однако, если они создают задачу неверное , то задача не будет создана, и в результате вы получите проект, содержащий менее 2 задач и, следовательно, неверный объект проекта.
Насколько я понимаю, это потому, что он не может выяснить, являются ли атрибуты задачи действительными или нет, пока не попытается сохранить задачи, и поскольку - , насколько я знаю - задачи не могут быть сохранены перед проектом, проект не знает, будут ли задачи действительными или нет. Правильно ли я предположил это?
В любом случае, я надеялся, что ответ будет быстрым, но он кажется гораздо менее тривиальным, чем я надеялся. Если у вас есть какие-либо предложения, это будет с благодарностью.
Решение
Я действительно нашел хорошее решение здесь, используя транзакции в DataMapper. По сути, эта транзакция пытается сохранить родительский объект, а также все дочерние объекты. Как только не удается сохранить, транзакция останавливается и ничего не создается. Если все будет хорошо, объекты будут успешно сохранены.
class Project
def make
transaction do |trans|
trans.rollback unless save
tasks.each do |task|
unless task.save
trans.rollback
break
end
end
end
end
end
Это гарантирует, что все действительно, прежде чем что-либо будет сохранено. Мне просто нужно было изменить методы #save и #update на #make в коде моего контроллера.
Другие советы
SET CONSTRAINTS DEFERRED может быть полезно, если ваш движок базы данных это поддерживает.
В противном случае, возможно, напишите хранимую процедуру для вставки, а затем скажите, что она отвечает за хранимую процедуру, чтобы гарантировать, что вставляются только правильные, проверенные данные.
Существует метод модели valid?
, который выполняет проверки объекта модели перед его сохранением. Таким образом, простым способом проверки ассоциаций будет использование validates_with_block 'или' validates_with_method
для проверки валидаций ассоциаций. Р>
Это будет выглядеть примерно так
validates_with_block do
if @tasks.all?{|t|t.valid?}
true
else
[false, "you have an invalid task"]
end
end
Или вы можете посмотреть dm-association-validator или dm-accept-nested-attribute
Изменить: для дополнительного сумасшествия. Запустите проверки задач, а затем проверьте, не являются ли ошибки только связанными.
validates_with_block do
if @tasks.all?{|t|t.valid?;!t.errors.any?{|e|e[0]==:project}}
true
else
[false, "you have an invalid task"]
end
end