jeudi 3 janvier 2019

How to make dependent factories in factorygirl

In my application. I have models - order has_many order_items, invoice has_many invoice_items. I am creating factory for order and order_items like this:-

Order Factory :-

FactoryGirl.define do
  factory :order do 
    booked_at {Date.current}
    approved_at {Date.current}
    state "draft"
    customer
    user
    notes "NOTE !!!"
    ip_address "127.0.0.1"
    approver_id 1
    channel "mobile"

    transient do
      order_items_count { 5 }
    end

    order_items_attributes do
      attributes = []
      order_items_count.times do 
        # We are not using attributes_for(:order_item) below as attributes_for do not generate attributes for association (varint in this case)
        attributes << attributes_with_foreign_keys_for(:order_item)
      end
      attributes
    end

    after(:build) do |order|
      order.customer.reload # Do not remove this, if you remove this customer.default_address and customer.shipping_address etc won`t show up in customer.addresses
      order.shipping_address = FactoryGirl.build(:customer_address, customer_id: order.customer_id)
      order.billing_address = FactoryGirl.build(:customer_address, customer_id: order.customer_id)
    end
  end
end

OrderItem Factory:-

FactoryGirl.define do
  factory :order_item do
    association :variant, factory: :product
    booked_quantity 10
    price 50
  end
end

Now, when I am creating my invoice and invoice item factory, I am facing a problem that invoice items are dependent on order items. Its like first order is created, only then invoices can be created.

Invoice Factory :-

FactoryGirl.define do
  factory :invoice do
    date "2018-03-05"
    due_date "2018-03-05"
    user
    invoice_term

    transient do
      invoice_items_count { 5 }
    end

    invoice_items_attributes do
      attributes = []
      invoice_items_count.times do 
        # We are not using attributes_for(:invoice_item) below as attributes_for do not generate attributes for association (varint in this case)
        attributes << attributes_with_foreign_keys_for(:invoice_item)
      end
      attributes
    end

    after(:build) do |invoice|
        @order = create(:order, state: "confirm")
        @customer_id = @order.customer_id 
        invoice.customer_id = @customer_id
      end
  end
end

Invoice Item Factory :-

FactoryGirl.define do
  factory :invoice_item do
    variant_id 1
    order_item_id 1
    quantity "9.99"
    price "9.99"
    item_total "9.99"
    discount_total "9.99"
    tax_total "9.99"
    tax_category_id 1
  end
end

Now, in my invoice item factory, where I have put variant_id 1, order_item_id 1, it should come from already created order_item (not 1 for every invoice_item). How can I do this?

Aucun commentaire:

Enregistrer un commentaire