【问题标题】:RSpec: Factory definition for associated objectRSpec:关联对象的工厂定义
【发布时间】:2019-11-24 21:13:42
【问题描述】:

我有以下三个模型:ProductWarehouseInventory

# app/models/product.rb
class Product < ApplicationRecord
  has_many :inventories
  has_many :warehouses, through: :inventories  
end

# app/models/warehouse.rb
class Warehouse < ApplicationRecord
  has_many :inventories
  has_many :products, through: :inventories
end

# app/models/inventory.rb
class Inventory < ApplicationRecord
  belongs_to :product
  belongs_to :warehouse
end

我有这个工厂用于库存:

FactoryBot.define do
  factory :inventory do
    product { nil }
    warehouse { nil }
    item_count { 1 }
    low_item_threshold { 1 }
  end
end

我如何将这个工厂用于库存,或者我的其他工厂需要进行哪些更改,以便我可以拥有这样的规格?

RSpec.describe Inventory, type: :model do
  it "has a valid factory" do
   expect(FactoryBot.build(:inventory)).to be_valid
  end
end

【问题讨论】:

    标签: ruby-on-rails rspec factory-bot


    【解决方案1】:

    你需要改变:inventory工厂定义,像这样

    FactoryBot.define do
      factory :inventory do
        product
        warehouse
        item_count { 1 }
        low_item_threshold { 1 }
      end
    end
    

    这将“告诉”工厂机器人实例化相关对象 (https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#associations)

    但要使其工作,您需要定义 warehouseproduct 工厂。

    【讨论】:

      【解决方案2】:

      如果工厂作为符号,您可以使用createbuild 方法传递名称:

        it "has a valid factory" do
         expect(create(:inventory)).to be_valid
       end
      
        # OR
      
        it "has a valid factory" do
         expect(build(:inventory)).to be_valid
       end
      

      create 将保存模型,而build 将简单地实例化它。如果您在加载工厂时遇到问题,请确保它们位于 right place 中。

      【讨论】:

        【解决方案3】:

        您可以将 Inventory 类的定义更改为:

        # app/models/inventory.rb
        class Inventory < ApplicationRecord
          belongs_to :product, optional: true
          belongs_to :warehouse, optional: true 
        end
        

        您将获得成功的验证

        inventory = FactoryBot.build(:inventory)
        inventory.valid? #true
        

        ##############################################

        解释:

        要使用模型的当前定义(如问题描述)构建有效的 Inventory 对象,还需要初始化关联对象。所以每次验证都会检查 warehouseproduct 属性是否存在。 但是使用关联属性optional: true 可以避免这种行为。

        # app/models/inventory.rb
        class Inventory < ApplicationRecord
          belongs_to :product
          belongs_to :warehouse
        end
        
        FactoryBot.define do
          factory :inventory do
            product { nil }
            warehouse { nil }
            item_count { 1 }
            low_item_threshold { 1 }
          end
        end
        
        inventory = FactoryBot.build(:inventory)
        inventory.valid? #false 
        inventory.errors.full_messages # ["Product must exist", "Warehouse must exist"] 
        

        :必填 当设置为 true 时,关联也会有 存在验证。这将验证关联本身,而不是 ID。您可以使用 :inverse_of 来避免验证期间的额外查询。 注意: required 默认设置为 true 并且已弃用。如果你 不想验证关联存在,请使用 optional: true。 https://apidock.com/rails/ActiveRecord/Associations/ClassMethods/belongs_to

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多