Почему этот before_save не вызывается для объекта в моем тесте RSPE C? - PullRequest
0 голосов
/ 17 марта 2020

У меня есть следующая PositionGroup модель:

# == Schema Information
#
# Table name: position_groups
#
#  id                     :bigint           not null, primary key
#  ticker                 :string
#  total_spend            :float
#  total_units            :integer
#  total_value            :float
#  created_at             :datetime         not null
#  updated_at             :datetime         not null
#  portfolio_id           :integer
#
class PositionGroup < ApplicationRecord
  has_many :positions
  belongs_to :portfolio

  before_save :update_total_units

  def update_total_units
    self.positions.each do |p|
      self.total_units = p.volume + self.total_units
    end
  end
end

В моем position_group_spec.rb у меня есть следующее:

RSpec.describe PositionGroup, type: :model do
  price1 = 10.00
  price2 = 15.00
  let(:stock) { create(:stock, price: price1) }
  let(:portfolio) { create(:portfolio) }
  let(:pg) { create(:position_group, portfolio: portfolio) }
  let(:position1) { create(:position, stock: stock, portfolio: portfolio, position_group: pg)}
  let(:position2) { create(:position, stock: stock, portfolio: portfolio, position_group: pg)}

  before do
    stock
    portfolio
    pg
    position1
    position2
    pg.positions << [position1, position2]
  end

  context "associations" do
    it { should belong_to(:portfolio) }
  end

  context "methods" do

    it "should calculate the total # of units" do
      # (Position 1 Volume + Position 2 Volume)
      # 100 + 100 = 200
      binding.pry
      expect(pg.total_units).to eql 200
    end

Все же, когда я запускаю его, и он нажимает что binding.pry в этом первом тесте показывает, что pg.total_units не был установлен.

    49:     it "should calculate the total # of units" do
    50:       # (Position 1 Volume + Position 2 Volume)
    51:       # 100 + 100 = 200
 => 52:       binding.pry
    53:       expect(pg.total_units).to eql 200
    54:     end
    55: 

[1] pry(#<RSpec::ExampleGroups::PositionGroup::Methods>)> pg
=> #<PositionGroup:0x00007fd63d4e41c8
 id: 2,
 ticker: nil,
 portfolio_id: 4,
 created_at: Tue, 17 Mar 2020 08:05:42 UTC +00:00,
 updated_at: Tue, 17 Mar 2020 08:05:42 UTC +00:00,
 total_units: nil,
 total_spend: nil,
 total_value: nil,
[2] pry(#<RSpec::ExampleGroups::PositionGroup::Methods>)> pg.positions.count
=> 2
[4] pry(#<RSpec::ExampleGroups::PositionGroup::Methods>)> pg.total_units
=> nil

Так почему же это let утверждение, не затрагивающее этот before_save обратный вызов в моей PositionGroup модели?

let(:position1) { create(:position, stock: stock, portfolio: portfolio, position_group: pg)}

1 Ответ

1 голос
/ 17 марта 2020

Rails has_many добавление не вызывает before_save обратный вызов для модели.

Вы можете использовать before_add обратный вызов для ассоциации. Например, что-то вроде этого:

class PositionGroup < ApplicationRecord
  has_many :positions, before_add: :update_total_units
  belongs_to :portfolio

  def update_total_units(position)
    update(total_units: total_units + position.volume)
  end
end

Do c здесь: https://guides.rubyonrails.org/association_basics.html#association -callbacks

...