2

より具体的には、「モデルが少なくとも 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 つ未満のプロジェクトになり、無効なプロジェクト オブジェクトになります。

私が理解しているように、これは、タスクを保存しようとするまで、タスク属性が有効かどうかを判断できないためです。また、私の知る限り、タスクはプロジェクトの前に保存できないため、プロジェクトは、タスクが有効かどうかを認識していません。これを仮定するのは正しいですか?

とにかく、私は迅速な答えがあることを望んでいましたが、私が望んでいたよりもはるかに些細なことではないようです. 何か提案があれば、それは大歓迎です。

4

3 に答える 3

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に変更する必要がありました。

于 2009-07-01T14:53:36.850 に答える
0

データベース エンジンがサポートしている場合は、SET CONSTRAINTS DEFERRED が役立つ場合があります。

それ以外の場合は、ストアド プロシージャを作成して挿入を行い、正しい検証済みデータのみが確実に挿入されるようにするためのストアド プロシージャの責任について説明します。

于 2009-06-17T00:38:12.733 に答える
0

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-accepts-nested-attributes を見ることができます

編集:さらにクレイジーに。タスクで検証を実行し、エラーが関連付けに関連するものだけであるかどうかを確認します。

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
于 2009-06-19T16:14:31.290 に答える