我正在编写一个应用程序来帮助我跟踪我的社交媒体广告预算。当您输入新广告时,它应计算并更新从中抽取的预算所花费的金额。这是我的模型,实现了这一点。
class Advert < ActiveRecord::Base
belongs_to :budget
before_save :update_budget
after_destroy :update_budget
validates :budget_id, :name, :platform, :ad_type, :amount, :start_date, :end_date, presence: true
validates :amount, numericality: true
validate :check_budget
# Checks to see if there is enough budget remaining to set up advert
def check_budget
if self.amount > self.budget.amount_remaining
errors.add(:amount, " cannot exceed amount remaining in budget.")
end
end
# Updates the amount remaining in the budget on advert save.
def update_budget
budget = Budget.find(self.budget_id)
@adverts = Advert.all
total_spent = self.amount
@adverts.each do |advert|
if advert.budget_id == self.budget_id
total_spent += advert.amount
end
end
budget.amount_spent = total_spent
budget.save
end
end
这一切都有效,但我正在教自己编写测试,所以我想我会在rspec中为它编写一个测试。
require 'rails_helper'
describe Advert do
it "updates budget before save" do
advert = create(:advert)
budget = advert.budget
expect(budget.amount_spent).to eq(advert.amount)
expect(budget.amount_remaining).to eq(budget.amount - budget.amount_spent)
end
end
然而,这个测试如果失败但我无法弄清楚为什么。这是错误代码。
1) Advert updates budget before save
Failure/Error: expect(budget.amount_spent).to eq(advert.amount)
expected: 7.0 (#<BigDecimal:7ffa61358b18,'0.7E1',9(18)>)
got: 0.0 (#<BigDecimal:7ffa6026a9a0,'0.0',9(18)>)
(compared using ==)
# ./spec/models/advert_spec.rb:27:in `block (2 levels) in <top (required)>'
这是相关的测试日志。
SQL (0.3ms) INSERT INTO "budgets" ("name", "amount", "client_id", "amount_remaining", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["name", "eos"], ["amount", "432.0"], ["client_id", 102], ["amount_remaining", "432.0"], ["created_at", "2016-03-12 18:08:54.607999"], ["updated_at", "2016-03-12 18:08:54.607999"]]
(0.1ms) RELEASE SAVEPOINT active_record_1
(0.2ms) SAVEPOINT active_record_1
Budget Load (0.4ms) SELECT "budgets".* FROM "budgets" WHERE "budgets"."id" = $1 LIMIT 1 [["id", 49]]
Advert Load (0.5ms) SELECT "adverts".* FROM "adverts"
SQL (0.4ms) UPDATE "budgets" SET "amount_spent" = $1, "amount_remaining" = $2, "updated_at" = $3 WHERE "budgets"."id" = $4 [["amount_spent", "7.0"], ["amount_remaining", "425.0"], ["updated_at", "2016-03-12 18:08:54.616491"], ["id", 49]]
SQL (0.4ms) INSERT INTO "adverts" ("budget_id", "name", "platform", "ad_type", "amount", "start_date", "end_date", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING "id" [["budget_id", 49], ["name", "ut"], ["platform", "voluptate"], ["ad_type", "facere"], ["amount", "7.0"], ["start_date", "2016-03-01"], ["end_date", "2016-04-12"], ["created_at", "2016-03-12 18:08:54.619698"], ["updated_at", "2016-03-12 18:08:54.619698"]]
(0.2ms) RELEASE SAVEPOINT active_record_1
(0.2ms) ROLLBACK
有趣的是,如果我评论出第一个“期望”,那么测试就会通过。就好像它无法访问advert.amount所以将它设置为0.
有人有什么想法吗?
答案 0 :(得分:0)
这解决了我的问题。
describe Advert do
it "updates budget before save" do
advert = build(:advert)
budget = advert.budget
expect(budget.amount_spent).to eq(0)
advert.save
budget.reload
expect(budget.amount_spent).to eq(advert.amount)
expect(budget.amount_remaining).to eq(budget.amount - budget.amount_spent)
end
我认为我的问题的根源并没有重新加载我的预算,这意味着我在更新之前尝试访问该属性。