代码之家  ›  专栏  ›  技术社区  ›  Carl Edwards monkbroc

确保集合中的一个对象为true,并将其他对象设置为false

  •  0
  • Carl Edwards monkbroc  · 技术社区  · 5 年前

    我有一个布尔属性的类, primary

    validates_uniqueness_of :primary, if: :primary, scope: [:restaurant_id]
    

    最近,我想自定义writer方法,使其在将当前实例在集合中的同级设置为false(如果实例为true)时分配当前实例的新值。尽管如此,我的测试还是失败了:

     MenuGroup did not properly validate that :primary is case-sensitively
           unique within the scope of :restaurant_id.
             After taking the given MenuGroup, setting its :primary to ‹"an
             arbitrary value"› (read back as ‹true›), and saving it as the existing
             record, then making a new MenuGroup and setting its :primary to a
             different value, ‹true› and its :restaurant_id to a different value,
             ‹nil›, the matcher expected the new MenuGroup to be invalid, but it
             was valid instead.
    

    这是测试:

    it { should validate_uniqueness_of(:primary).scoped_to([:restaurant_id]) }
    

    class MenuGroup < ApplicationRecord
      belongs_to :restaurant
    
      validates_uniqueness_of :primary, if: :primary, scope: [:restaurant_id]
    
      def primary=(primary)
        if primary?
          MenuGroup
           .where.not(id: self.id)
           .where(restaurant_id: self.restaurant_id).update_all(primary: false)
        end
    
        write_attribute :primary, primary
      end
    end
    
    0 回复  |  直到 5 年前
        1
  •  0
  •   user229044    5 年前

    if primary? 检查记录是否 self.primary?

    这个 ? 打电话给当地人 primary? 方法,由ActiveRecord自动生成。它是 对变量的检查 primary 作为参数传递给函数。

    也就是说,你的验证不能被测试,实际上什么也做不了。

    primary= setter将自动取消设置前一个 初级的 记录。由于setter阻止模型进入无效状态,验证无法中断。

    你的测试试图设置秒 MenuGroup primary = true primary = false 在所有现有的 菜单组 s、 所以验证运行并顺利通过。