ruby-on-rails Rails在创建多个记录时进行验证

wvt8vs2t  于 2023-08-08  发布在  Ruby
关注(0)|答案(2)|浏览(123)

在我们的Rails应用中,我们有一些验证规则,确保在创建或编辑配置时,属于同一应用的配置具有唯一的代码:

class Configuration < ApplicationRecord
    belongs_to :app
    validate :unique_code

    private

    def unique_code
      if app_codes&.include?(code)
        errors.add(code, 'is already being used for this app')
        return false
      end
      true
    end

    def app_configurations
      app&.configurations&.where&.not(id: id)
    end

    def app_codes
      app_configurations&.map(&:code)
    end
  end

字符串
这确保了我们不能在同一个应用程序上使用相同代码的配置,但我们可以在另一个应用程序上使用相同代码的配置。并且在自己创建和编辑配置时工作得很好。
但是,如果我们创建一个新的应用程序,并同时创建多个配置(通过accepts_nested_attributes_for),验证不会捕获它,并让重复的代码通过有效.很可能是因为验证是与“现有”应用程序配置进行比较,而不是与即将创建的应用程序配置进行比较,因此数据库中不存在要检查的应用程序配置...
我们如何检查这两种情况?现有的和正在创建的?

zengzsys

zengzsys1#

一种名为existing_and_new_app_codes的新方法,它将现有配置和为应用程序创建的新配置结合在一起。
使用app.new_configurations.reject(&:marked_for_destruction?)检索新配置,以确保列表中仅包括未标记为销毁的新配置。

class Configuration < ApplicationRecord
  belongs_to :app
  validate :unique_code

  private

  def unique_code
    all_app_codes = existing_and_new_app_codes

    if all_app_codes.include?(code)
      errors.add(:code, 'is already being used for this app')
    end
  end

  def existing_and_new_app_codes
    existing_codes = app_codes || []
    new_codes = app.new_configurations.reject(&:marked_for_destruction?).map(&:code)
    existing_codes + new_codes
  end

  def app_configurations
    app&.configurations&.where.not(id: id)
  end

  def app_codes
    app_configurations&.map(&:code)
  end
end

字符串

xqkwcwgp

xqkwcwgp2#

我在上面的解决方案中不断遇到边缘情况,发现Rails有一个内置的验证范围,就是为了这个目的:

validates_uniqueness_of :code, scope: :app_id

字符串

相关问题