Проверка вложенных моделей? - PullRequest
2 голосов
/ 17 июня 2009

Чтобы быть более точным, «Как проверить, что для модели требуется создать хотя бы 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

Все проверки выполняются в определениях схемы, как вы можете видеть. Важным здесь является "has 2..n, :tasks". Эта проверка на самом деле работает нормально, учитывая, что вложенные атрибуты задач в хэше params приведут к допустимым задачам. Однако, если они создают задачу неверное , то задача не будет создана, и в результате вы получите проект, содержащий менее 2 задач, и, таким образом, проект неверный объект.

Насколько я понимаю, это потому, что он не может выяснить, действительны ли атрибуты задачи, пока не попытается сохранить задачи, и поскольку - , насколько я знаю - задачи не может быть сохранен перед проектом, проект не знает, будут ли задачи правильными или нет. Правильно ли я предположил это?

Во всяком случае, я надеялся, что будет быстрый ответ, но он кажется намного менее тривиальным, чем я надеялся. Если у вас есть какие-либо предложения, это будет с благодарностью.

Ответы [ 3 ]

2 голосов
/ 01 июля 2009

Я действительно нашел хорошее решение здесь, используя транзакции в 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 в коде моего контроллера.

0 голосов
/ 19 июня 2009

Существует метод модели valid?, который запускает проверки объекта модели перед его сохранением. Таким образом, простым способом проверки ассоциаций будет использование validates_with_block' or '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
0 голосов
/ 17 июня 2009

SET CONSTRAINTS DEFERRED может быть полезно, если ваша база данных поддерживает это.

В противном случае, возможно, напишите хранимую процедуру для вставки, а затем скажите, что она отвечает за хранимую процедуру, чтобы гарантировать, что вставляются только правильные, проверенные данные.

...