验证多态关联的引用完整性

时间:2015-08-15 13:35:20

标签: ruby-on-rails validation polymorphism polymorphic-associations

在Rails应用程序中工作,我正在将可选的belongs_to关联更改为多态。现有的代码验证了关联的引用完整性,我试图找出如何将其转换为多态的习语。

简化但说明性的例子......

旧:

class Climb < ActiveRecord::Base

  belongs_to :ladder
  validate   :ladder_exists_if_id_set

  def ladder_exists_if_id_set
    if ladder_id.present? && Ladder.find_by_id(ladder_id).blank?
      errors.add('Ladder id', 'invalid. Set a different ladder id or nil.')
    end
  end

end

新的:

class Climb < ActiveRecord::Base

  belongs_to :climbable, polymorphic: true
  validate   :climbable_exists_if_set

  def climbable_exists_if_set
    return unless climbable_id.present? && climbable_type.present?

    klass = climbable_type.constantize

    if klass.find_by_id(climbable_id).blank?
      errors.add("#{klass} id", "invalid. Set a different #{klass} id or nil.")
    end
  end

end

这似乎有效,但这是正确的方法吗?好像我正在重新实现多态性给你的动态getter / setter方法。

Sidenote :我可以忽略仅设置_type_id的情况,因为在这种情况下Rails使记录无效。

1 个答案:

答案 0 :(得分:1)

我想知道,为什么你首先在你的旧代码中以这种方式验证id的唯一性?如果需要,可以更轻松地编写validates :ladder_id, uniqueness: true, allow_nil: true [, allow_blank: true] (you should decide what you want to allow)并使用自定义消息。然后看看Rails是否在新代码中为您处理多态关联。我认为你不需要你的climbable_exists_if_set。

发表评论后

可能更容易。您只需验证梯形图对象的存在。注意,不是ladder_id,而是对象本身,因此您的验证应该如下:

validates :ladder, presence: true, allow_nil: true [, allow_blank: true]

在这种情况下,rails会验证梯形图表中是否存在具有给定ID的实际梯形记录。