如何使FactoryGirl.create影响另一个记录的属性?

时间:2016-11-09 14:59:04

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

在网店应用程序中,通常在产品的预订之后, bookings_controller 创建操作会执行order.save,而order.sum_of_all_bookings会激活必要的before_save方法{{1 }}

为管理员查看订单列表构建RSpec测试时,进行预订不会更改订单总数。索引在浏览器中有效。

require 'rails_helper'

RSpec.feature 'Admin can oversee orders' do
  let(:admin) { FactoryGirl.create(:user, :admin) }
  let(:customer) { FactoryGirl.create( :user ) }
  let!(:order_1) { FactoryGirl.create( :order, customer: customer ) }
  let!(:booking_1) { FactoryGirl.create( :booking,  product_name: 'Honingpot', 
                                                    product_quantity: 1, 
                                                    product_price: '5,00', 
                                                    order: order_1 ) }
  let!(:order_2) { FactoryGirl.create( :order, customer: customer ) }
  let!(:booking_2) { FactoryGirl.create( :booking,  product_name: 'Streekpakket',
                                                    product_quantity: 2, 
                                                    product_price: '10,00', 
                                                    order: order_2 ) }


  before do
    order_1.sum_all_bookings
    order_2.sum_all_bookings
    login_as(admin)
    visit orders_path
  end

  scenario 'with success' do
    within('table#paid') do
      expect(page).to have_content '5,00'
      expect(page).to have_content '10,00'
    end
  end
end

在阻止之前不起作用。

创建后的工厂女孩​​也没有:

FactoryGirl.define do
  factory :booking do
    product_name 'Honingpot'
    product_quantity '1'
    product_price '3,99'
    order
    after(:create) { |booking| booking.order.save } # booking.order.sum_all_bookings, also not working
  end
end

RSpec打印订单中的订单,但订单总数不变。

如何使订单与预订相加?

或更一般地说:

如何让FactoryGirl.create影响其他记录的属性?

1 个答案:

答案 0 :(得分:2)

清理您的规格

首先,您的规格中有太多的出厂配置。 FactoryGirl用于从您的规范中移除创建和设置

这不会直接解决您的问题,但这些步骤将使您的测试过程更清晰,更简单,更快捷。

1。 Faker Gem

要开始改造,请继续添加faker gem,这样您就可以轻松为工厂生成有用的随机数据。

FactoryGirl.define do
  factory :booking do
    product_name { Faker::Commerce.product_name }
    product_quantity { Faker::Number.number(2) }
    product_price Faker::Number.decimal(2)

    order
  end
end

你去了,一些准备好的预订工厂准备好了。

2。性状

对于某些情况,它们是调整工厂的好方法。绝对是read more about them in the docs

FactoryGirl.define do
  factory :order do 
    customer

    trait :with_bookings do 
      after(:create) do |order|
        order.bookings << create_list(:booking, 2)
      end
    end
  end
end

现在您可以轻松创建包含或不包含预订的订单:

let(:order_with_bookings) { create(:order, :with_bookings) }

3。更清晰的语法

您可以省略FactoryGirl语法,只需create(:order)即可。完成这些步骤后,您应该拥有更清洁的测试环境。

解决回调问题

据我了解,你设置了这样的回调:

class Order
  has_many :bookings

  before_save :update_order_cache

  def update_order_cache
    # calculation of the total bookings sum 
  end
end

class Booking
  belongs_to :order
end

但是你应该反过来做,在产品创建或更新后,应该触发订单回调:

class Order
  has_many :bookings

  def update_order_cache
    # calculation of the total bookings sum 
  end
end

class Booking
  belongs_to :order

  after_save do
    order.update_order_cache
  end
end

如果该字段永远不应为空白,您还可以为总和添加默认值。

validates :sum_field, presence: true, default: '0.0'

这应该为你解决这个问题。干杯!