验证嵌套模型?

发布于 2024-07-24 07:30:22 字数 904 浏览 4 评论 0原文

更具体地说,“如何验证模型需要至少创建 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 个的项目,因此是一个无效 > 项目对象。

据我了解,这是因为它无法确定任务属性是否有效,直到它尝试保存任务,并且因为 - 据我所知 - 任务可以'在项目之前保存,项目不知道任务是否有效。 我的假设正确吗?

不管怎样,我希望能有一个快速的答案,但这似乎比我希望的要简单得多。 如果您有任何建议,我们将不胜感激。

To be more specific, "How do I validate that a model requires at least x valid associated models to be created?". I've been trying to validate nested models that get created in the same form as the parent (and ultimately show immediate validations a la jQuery). As a popular example, lets assume the following models and schema.

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

All the validations are done in the schema definitions, as you can see. The important one here is "has 2..n, :tasks". This validation actually works normally, given that the nested task attributes in the params hash will produce valid tasks. If they produce an invalid task, however, then the task won't get created and you'll end up with a Project that has less than 2 tasks, and thus an invalid project object.

As I understand it, this is because it can't figure out if the task attributes are valid or not until it attempts to save the tasks, and since - as far as I know - the tasks can't get saved before the project, the project is unaware if the tasks will be valid or not. Am I correct in assuming this?

Anyway, I was hoping there would be a quick answer, but it seems a lot less trivial then I'd hoped. If you've got any suggestions at all, that would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无声无音无过去 2024-07-31 07:30:22

实际上,我在这里使用 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 即可。

I actually found a nice solution here using transactions in DataMapper. Basically this transaction tries to save the parent object as well as all the child objects. As soon as one fails to save, then the transaction stops and nothing gets created. If all goes well, then the objects will save successfully.

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

This assures that everything is valid before it anything gets saved. I just needed to change my #save and #update methods to #make in my controller code.

瘫痪情歌 2024-07-31 07:30:22

如果您的数据库引擎支持,SET CONSTRAINTS DEFERRED 可能会很有用。

否则,可能会编写一个存储过程来执行插入,然后说存储过程的职责是确保仅插入正确的、经过验证的数据。

SET CONSTRAINTS DEFERRED might be useful if your database engine supports that.

Otherwise, maybe write a stored procedure to do the inserts, and then say that its the resonsibility of the stored procedure to ensure that only correct, validated data is inserted.

相对绾红妆 2024-07-31 07:30:22

有一个模型方法 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-validatordm-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

There is a model method valid? that runs the validations on a model object before it is saved. So, the simple way to validate the associations would be to use validates_with_block' or 'validates_with_method to check the validations on the associations.

It would look something like this

validates_with_block do
  if @tasks.all?{|t|t.valid?}
    true
  else
    [false, "you have an invalid task"]
  end
end

Or you could look at dm-association-validator or dm-accepts-nested-attributes

Edit: for extra crazy. run validations on the tasks, then check to see if the only errors are ones related to the association.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文