【问题标题】:rails 4 validating associated object + db constraintrails 4验证关联对象+数据库约束
【发布时间】:2016-03-09 19:39:06
【问题描述】:

我正在尝试为 rails 中的外键字段和 postgres db 中的约束添加验证。

假设有一个userUser has_many :productsproduct belongs_to :user。在这种情况下,情况很容易,因为用户是在添加新产品时确定的。所以validates: user, presence: true可以添加到product model中,user_id, null: false可以添加到postgres db中。

但是如果同时创建父子对象和对象呢?假设在 product form 我有 product_features 作为嵌套属性。所以product has_many :product_featuresproduct_feature belongs_to :product

根据 Rails 4 Way:“当您尝试确保关联存在时,请传递其外键属性的 validates_presence_of,而不是关联变量本身。请注意,如果父子节点都存在验证将失败的情况对象未保存(因为外键为空白)。”

在这种情况下,如何实现模型验证和外键字段的数据库约束?

【问题讨论】:

    标签: ruby-on-rails database postgresql validation constraints


    【解决方案1】:

    事实是,验证密钥本身(例如product_id)的存在是毫无用处的,因为@product_feature.product_id = -25 将通过验证。

    我总是对关联进行存在验证:

    validates :product, presence: true
    

    无论您以哪种方式创建对象,这都会起作用:

    ProductFeature.new product: Product.new
    

    ...或...

    Product.new product_features: [ ProductFeature.new ]
    

    我不确定为什么有人会推荐其他任何东西,验证密钥本身并不能保证密钥存在于数据库中。

    【讨论】:

    • 是的,我在 Rails 中这样做只是没有正确表达自己。但是对于 db,没有这样的东西。 Mike Perham http://www.mikeperham.com/2012/05/05/five-common-rails-mistakes/#more-833 推荐 foreign_key 版本。这种验证并不完美,但总比没有好。好的,在rails方面不会有问题,但是postgres呢?如果我将空约束添加到 db,它是否适用于嵌套 attrs?
    • 还发现了这个拥有 200 万 DL 的 gem:github.com/matthuhiggins/foreigner
    • 是的,null 约束(和/或外键约束)可以用于嵌套属性,Rails 以正确的顺序保存。
    • 谢谢 Smathy,最后一个问题。您将在 db 中的外键字段上使用什么:空约束或外键约束或两者兼而有之?这个话题很难找到明确的答案。
    • 它们的用途不同。外键约束确保如果该字段被设置然后它被设置为一个有效的 id,那么空约束是该关联是否是强制性的。
    【解决方案2】:

    在这种情况下,您可以在模型中创建自定义验证方法。

    Product 模型中编写以下验证方法,以确保product 具有product_features

     validate :product_features
    
     def product_features
       product_features.present?
     end
    

    【讨论】:

    • Product_feature 不是必需的。我需要反过来。如果用户决定将product_feature 添加到product,则应用程序和数据库应确保product_id 存在于product_feature 表中。
    • 这很简单。 validates_presence_of :productProductFeature 模型中。在这种情况下使用嵌套形式,没有product,您将永远不会有任何product_feature
    • 您对数据库方面有何看法?空约束会导致问题吗?
    • 除非您指定 rails 以避免验证 save,否则调用将永远不会达到 db 级别。
    • 我知道正式情况是这样,但 db 比应用程序验证更重要。 mikeperham.com/2012/05/05/five-common-rails-mistakes/#more-833
    【解决方案3】:

    这并不能直接回答您的问题,但是在使用嵌套表单时,您应该像这样构建对象:

    Product.product_features.new
    

    这样你就可以确定你在product_feature中有product_id

    【讨论】:

    • 我就是这样用的。只是 rails 4 way 的评论让我很困惑,因为我不知道在嵌套属性的情况下到底会发生什么。
    • 如果您以这种方式使用它,则不需要该验证,该对象是使用 product_id 创建的。
    • 你如何看待db端的空约束?
    • product_id或其他属性?
    • postgres 中 product_id 字段的 product_features 表中的完全空约束。
    猜你喜欢
    • 2013-07-24
    • 1970-01-01
    • 2015-09-30
    • 2013-05-21
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 2014-08-24
    • 1970-01-01
    相关资源
    最近更新 更多