有没有一种简单的方法可以计算 Rails 中的和积?
Is there a simple way to calculate sumproduct in Rails?
我有一个 PositionGroup
has_many :positions
。
每当触摸 position_group
对象时,我想像这样更新 pg.average_price
:
# Average Price = ((position1.transaction_price * (position1.volume/total_volume) +
# position2.transaction_price * (position2.volume/total_volme))
在我的回调方法中,我试过这个:
def update_average_price
total_volume = positions.sum(:volume)
avg_price = positions.sum("transaction_price * (volume/#{total_volume})")
update_column(:average_price, avg_price)
end
但是当我检查 avg_price
的值时,一旦存在多个 positions
,我得到 0.0
。
这是我对这个特定功能的规范:
it "should calculate the Weighted Average Purchase Price of all positions" do
# Position 3: Price = 20, volume = 200
# (Position 1 Price * (Position 1 Units/Total # of Units)) +
# (Position 2 Price * (Position 2 Units/Total # of Units)) +
# (Position 3 Price * (Position 3 Units/Total # of Units))
# ( * (100/400)) + ( * (100/400) + * (100/400)) =
# (.50 + .75 + ) = .25
price3 = 20
pos3 = create(:position, stock: stock, portfolio: portfolio, transaction_price: 20, current_price: price3, action: :buy, volume: 200, position_group: pg)
expect(pg.average_price).to eql 11.25
end
这是我运行时的结果:
1) PositionGroup methods should calculate the Weighted Average Purchase Price of all positions
Failure/Error: expect(pg.average_price).to eql 11.25
expected: 11.25
got: 0.0
(compared using eql?)
我很确定问题出在这一行,来自我在 PositionGroup
上的回调方法 update_average_price
:
avg_price = positions.sum("transaction_price * (volume/#{total_volume})")
是否有更好的方法来解决这个问题,或者是否有其他东西在我不应该的时候给了我 0.0
?
avg_price = positions.sum("transaction_price * (volume/#{total_volume.to_f})")
to_f
缺失,正在转换为浮点数以获取小数。
示例
irb(main):022:0> Position.all
Position Load (0.3ms) SELECT "positions".* FROM "positions" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Position id: 1, transaction_price: 0.5e2, volume: 150, position_group_id: 1>, #<Position id: 2, transaction_price: 0.1e1, volume: 50, position_group_id: 1>]>
irb(main):023:0> Position.all.sum("transaction_price * (volume/#{total_volume.to_f})")
(0.2ms) SELECT SUM(transaction_price * (volume/200.0)) FROM "positions"
=> 37.75
我有一个 PositionGroup
has_many :positions
。
每当触摸 position_group
对象时,我想像这样更新 pg.average_price
:
# Average Price = ((position1.transaction_price * (position1.volume/total_volume) +
# position2.transaction_price * (position2.volume/total_volme))
在我的回调方法中,我试过这个:
def update_average_price
total_volume = positions.sum(:volume)
avg_price = positions.sum("transaction_price * (volume/#{total_volume})")
update_column(:average_price, avg_price)
end
但是当我检查 avg_price
的值时,一旦存在多个 positions
,我得到 0.0
。
这是我对这个特定功能的规范:
it "should calculate the Weighted Average Purchase Price of all positions" do
# Position 3: Price = 20, volume = 200
# (Position 1 Price * (Position 1 Units/Total # of Units)) +
# (Position 2 Price * (Position 2 Units/Total # of Units)) +
# (Position 3 Price * (Position 3 Units/Total # of Units))
# ( * (100/400)) + ( * (100/400) + * (100/400)) =
# (.50 + .75 + ) = .25
price3 = 20
pos3 = create(:position, stock: stock, portfolio: portfolio, transaction_price: 20, current_price: price3, action: :buy, volume: 200, position_group: pg)
expect(pg.average_price).to eql 11.25
end
这是我运行时的结果:
1) PositionGroup methods should calculate the Weighted Average Purchase Price of all positions
Failure/Error: expect(pg.average_price).to eql 11.25
expected: 11.25
got: 0.0
(compared using eql?)
我很确定问题出在这一行,来自我在 PositionGroup
上的回调方法 update_average_price
:
avg_price = positions.sum("transaction_price * (volume/#{total_volume})")
是否有更好的方法来解决这个问题,或者是否有其他东西在我不应该的时候给了我 0.0
?
avg_price = positions.sum("transaction_price * (volume/#{total_volume.to_f})")
to_f
缺失,正在转换为浮点数以获取小数。
示例
irb(main):022:0> Position.all
Position Load (0.3ms) SELECT "positions".* FROM "positions" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Position id: 1, transaction_price: 0.5e2, volume: 150, position_group_id: 1>, #<Position id: 2, transaction_price: 0.1e1, volume: 50, position_group_id: 1>]>
irb(main):023:0> Position.all.sum("transaction_price * (volume/#{total_volume.to_f})")
(0.2ms) SELECT SUM(transaction_price * (volume/200.0)) FROM "positions"
=> 37.75