使用ActiveRecord :: Base#只验证一个属性有效吗?

时间:2014-11-20 17:36:11

标签: ruby-on-rails ruby validation rails-activerecord

我正在寻找一种仅在一个属性上使用ActiveRecord::Base#valid?的方法。请考虑以下示例,受RailsGuides启发:

class Product < ActiveRecord::Base
  belongs_to :company

  validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/ }
  validates :name, uniqueness: { scope: :company }
end

由于Product#valid?验证:

,调用name将触发SQL查询
Product.new(legacy_code: "helloworld", company: c).valid?
  Product Exists (0.3ms)  SELECT  1 AS one FROM "products"  WHERE ("products"."name" IS NULL AND "products"."company_id" = 1) LIMIT 1
=> true

现在,我只想查看legacy_code属性:

Product.new(legacy_code: "helloworld").valid?
  Product Exists (0.2ms)  SELECT  1 AS one FROM "products"  WHERE ("products"."name" IS NULL AND "products"."company_id" IS NULL) LIMIT 1
=> true

看到问题?我喜欢使用类似Product#valid?(:legacy_code)之类的内容,并避免尝试验证我不关心的属性。

到目前为止,我的解决方案是使用我可以独立调用的Product#valid_legacy_code?方法,并在我的模型的验证声明中调用此方法。

1 个答案:

答案 0 :(得分:4)

我最终为此写了一个宝石:https://github.com/KevinBongart/valid_attribute

# Test only one attribute:
product.valid_attribute?(:company)      # => true
product.valid_attribute?(:name)         # => true
product.valid_attribute?(:legacy_code)  # => false

# Test several attributes at once, like a boss:
product.valid_attribute?(:company, :name)               # => true
product.valid_attribute?(:company, :name, :legacy_code) # => false

# Wow, you can even filter down to a specific validator:
product.valid_attribute?(name: :format)                     # => true
product.valid_attribute?(name: [:format, :uniqueness])      # => true
product.valid_attribute?(name: :format, company: :presence) # => true