Вопрос

Чтобы быть более конкретным, " Как проверить, что для модели требуется создать как минимум 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top