【问题标题】:Validation on model with 'intentional' invalid data使用“故意”无效数据验证模型
【发布时间】:2011-01-06 14:21:59
【问题描述】:

我使用的数据源很糟糕。有些地方你会期望整数,你会得到“三”。在电话号码字段中,您可能会得到“电话号码是 xxx”。有些字段只是空白。

这没关系,因为我正在解析每个字段,因此“三”将在我的模型中以整数 3 结尾,电话号码(等)将通过正则表达式提取。该服务的用户知道数据是粗略且不完整的,因为这是我们的数据源维护方式的不幸事实,我们对此无能为力,只能加强我们的解析游戏!顺便说一句,随着我们解析越来越多的原始数据,我们正在缓慢地生成我们自己的数据版本,但这个糟糕的来源现在必须做。

因此,用户选择他们希望解析的数据,然后我们尽我们所能,返回部分/不正确的模型。现在应该验证我们要存储的最终模型 - 某些字段不能为空,某些字符串必须遵守格式等等。

应用的流程是:

  1. 用户告诉服务哪些数据 解析。
  2. 服务停止并抓取 数据,解析它可以和 返回一个部分模型 它可以检索到的任何数据。
  3. 我们向用户显示数据, 允许他们进行更正 并填写任何必填字段 没有收集任何数据。
  4. 这个用户更正的数据是 已保存,因此经过验证。
  5. 如果验证失败,再次显示数据 供用户进行修复、冲洗和 重复。

让模型开始时可能完全无效或不包含数据但最终需要验证的最佳方法是什么?我想到(并部分实施)的两种方法是:

  1. 2 个模型 - 一个具有验证等的数据模型和一个没有验证的 UnconfirmedData 模型。原始数据会被放入 UnconfirmedData 模型,直到用户做出更正后,才会将原始数据放入 Data 模型并尝试验证。
  2. 一个模型,带有“已确认数据”标志,手动执行验证而不是 Rails 验证。

在实践中我倾向于使用 2 种模型,但我对 Rails 还很陌生,所以我认为我有更好的方法来做到这一点,Rails 有这样让我惊讶的习惯 :)

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 rails-models


    【解决方案1】:

    您必须在请求之间保存数据吗?如果是这样,我会使用您的两种模型格式,但使用单表继承 (STI) 来保持干燥。

    第一个模型,负责解析和渲染以及尽最大努力的模型,不应该对保存它进行任何验证或限制。但是,它应该在迁移中具有type 列,以便您可以使用继承优势。如果您不知道我在说什么,请阅读有关 STI 的大量信息,a definitive guide 是一个不错的起点。

    第二种模型将是您将在应用程序的其余部分中使用的模型,即严格模型,具有所有验证的模型。每次用户提交修改后的和可能有效的数据时,您的应用程序都会尝试将您从参数创建的开放模型的实例移动到第二个模型的实例,并查看它是否有效。如果是,将其保存到数据库中,type 属性将发生变化,一切都会变得美好。如果它无效,则保存第一个实例,并将第二个实例返回给用户,以便可以使用验证错误消息。

    class ArticleData < ActiveRecord::Base
        def parse_from_url(url)
            # parses some stuff from the data source
        end
    end
    
    class Article < ArticleData
         validates_presence_of :title, :body
         validates_length_of :title, :greater_than => 20
         # ...
    end
    

    您需要一个非常激烈的控制器操作来促进上述过程,但这应该不会太难。在您的应用程序的其余部分中,请确保您在 Article 模型上运行查询以仅返回有效的查询。

    希望这会有所帮助!

    【讨论】:

    • 非常感谢您的澄清,我认为这就是我要走的路。数据将在请求之间移动,甚至可能在会话之间移动,因此存储临时数据会很有用;这在未来可能比现在更重要。也感谢 railsforum 链接,非常有用。
    【解决方案2】:

    使用一个模型应该足够简单。您需要一个属性/方法来确定是否应该执行验证。您可以通过:if =&gt; 绕过/启用它们:

    validates_presence_of :title, :if => :should_validate
    

    should_validate 可以是一个简单的布尔属性,当模型实例为“临时”时返回 false,或者如果需要,可以是更复杂的方法。

    【讨论】:

    • 啊,这就是我所希望的 Rails 优点。然而,在实现了这个和我上面概述的方法之后,我想我会沿着 2 模型路线走。它没有那么光滑,但让我能够更好地将有效数据与临时数据区分开来,这对未来可能很重要。非常感谢您的回复,我没见过:如果以前,毫无疑问它很快就会派上用场。
    猜你喜欢
    • 1970-01-01
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    • 2018-05-31
    • 2014-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多