Rails ActiveRecord 模型未在 RSpec 模型规范中更新
Rails ActiveRecord Model not updating in RSpec model spec
这让我发疯。我在不丢失上下文的情况下将其精简到最低限度(我认为!)
我想做的就是检查当我更新一个值并将其保存到数据库时,该值是否已保存。我想这样做是因为我需要编写一些其他代码来在 before_save 回调中有条件地阻止这种情况,并且在我确定它正在工作之前我无法测试它!
下面是工厂和规格,我敢肯定这确实很愚蠢,但我就是想不通...
FactoryGirl.define do
factory :programme do
name 'Trainee Programme'
end
factory :membership do
programme
end
factory :specialty do
sequence(:name) { |n| "Specialty #{n}" }
end
factory :user do
sequence(:email) { |n| "factorygirl-user-#{n}@remailer.org" }
password 'password'
password_confirmation 'password'
factory :trainee, class: User do
sequence(:email) { |n| "factorygirl-trainee-#{n}@remailer.org" }
name 'Factory Girl Trainee'
after(:create) do |user|
FactoryGirl.create(:membership, user: user, start_date: 1.day.ago)
end
end
end
end
describe Membership do
let(:trainee) { FactoryGirl.create(:trainee) }
it 'sets specialty' do
puts trainee.current_membership.inspect
trainee.current_membership.specialty = specialty
puts trainee.current_membership.inspect
trainee.current_membership.save!
puts trainee.current_membership.inspect
expect(trainee.current_membership.specialty).to eq(specialty)
end
end
规范失败,因为期望看到一个 nil 值。当我 运行 代码时,我得到的调试输出是:
#<Membership id: 11, user_id: 11, programme_id: 11, start_date: "2015-03-10", end_date: nil, created_at: "2015-03-11 22:02:51", updated_at: "2015-03-11 22:02:51", options: {}, specialty_id: nil, membership_type_id: nil>
#<Membership id: 11, user_id: 11, programme_id: 11, start_date: "2015-03-10", end_date: nil, created_at: "2015-03-11 22:02:51", updated_at: "2015-03-11 22:02:51", options: {}, specialty_id: nil, membership_type_id: nil>
#<Membership id: 11, user_id: 11, programme_id: 11, start_date: "2015-03-10", end_date: nil, created_at: "2015-03-11 22:02:51", updated_at: "2015-03-11 22:02:51", options: {}, specialty_id: nil, membership_type_id: nil>
所以好像专业的分配从来没有发生过??
尝试重新加载 trainee
,例如
expect(trainee.reload.current_membership.specialty).to eq(specialty)
我能想到的唯一原因是 speciality
是一条新的非持久记录。由于 membership belongs_to :speciality
和 membership
已经持久化,因此它不会在赋值时或保存时保存关联对象。简而言之,确保 speciality
在创建关联之前已保存。
感谢 BroiState 和 Mori 给我的一些指示,我能够确定它与持久性有关(特别是我的一个对象方法不尊重它!)
trainee.current_membership的代码如下:
def current_membership
return unless memberships.current.any?
memberships.current.first
end
在成员资格中使用这些相关范围...
scope :started, -> { self.where("#{table_name}.#{_start_field}::TIMESTAMP < '#{Time.now}'") }
scope :not_ended, -> { self.where("#{table_name}.#{_end_field} IS NULL OR #{table_name}.#{_end_field}::TIMESTAMP > '#{Time.now}'") }
scope :current, -> { self.started.not_ended }
所以每次调用 trainee.current_membership 都会给我一个 'current' 会员记录的新实例
通过明确使用同一对象,规范顺利通过,即:
it 'sets specialty' do
membership = trainee.current_membership
membership.specialty = specialty
membership.save!
expect(membership.specialty).to eq(specialty.reload)
end
这让我发疯。我在不丢失上下文的情况下将其精简到最低限度(我认为!)
我想做的就是检查当我更新一个值并将其保存到数据库时,该值是否已保存。我想这样做是因为我需要编写一些其他代码来在 before_save 回调中有条件地阻止这种情况,并且在我确定它正在工作之前我无法测试它!
下面是工厂和规格,我敢肯定这确实很愚蠢,但我就是想不通...
FactoryGirl.define do
factory :programme do
name 'Trainee Programme'
end
factory :membership do
programme
end
factory :specialty do
sequence(:name) { |n| "Specialty #{n}" }
end
factory :user do
sequence(:email) { |n| "factorygirl-user-#{n}@remailer.org" }
password 'password'
password_confirmation 'password'
factory :trainee, class: User do
sequence(:email) { |n| "factorygirl-trainee-#{n}@remailer.org" }
name 'Factory Girl Trainee'
after(:create) do |user|
FactoryGirl.create(:membership, user: user, start_date: 1.day.ago)
end
end
end
end
describe Membership do
let(:trainee) { FactoryGirl.create(:trainee) }
it 'sets specialty' do
puts trainee.current_membership.inspect
trainee.current_membership.specialty = specialty
puts trainee.current_membership.inspect
trainee.current_membership.save!
puts trainee.current_membership.inspect
expect(trainee.current_membership.specialty).to eq(specialty)
end
end
规范失败,因为期望看到一个 nil 值。当我 运行 代码时,我得到的调试输出是:
#<Membership id: 11, user_id: 11, programme_id: 11, start_date: "2015-03-10", end_date: nil, created_at: "2015-03-11 22:02:51", updated_at: "2015-03-11 22:02:51", options: {}, specialty_id: nil, membership_type_id: nil>
#<Membership id: 11, user_id: 11, programme_id: 11, start_date: "2015-03-10", end_date: nil, created_at: "2015-03-11 22:02:51", updated_at: "2015-03-11 22:02:51", options: {}, specialty_id: nil, membership_type_id: nil>
#<Membership id: 11, user_id: 11, programme_id: 11, start_date: "2015-03-10", end_date: nil, created_at: "2015-03-11 22:02:51", updated_at: "2015-03-11 22:02:51", options: {}, specialty_id: nil, membership_type_id: nil>
所以好像专业的分配从来没有发生过??
尝试重新加载 trainee
,例如
expect(trainee.reload.current_membership.specialty).to eq(specialty)
我能想到的唯一原因是 speciality
是一条新的非持久记录。由于 membership belongs_to :speciality
和 membership
已经持久化,因此它不会在赋值时或保存时保存关联对象。简而言之,确保 speciality
在创建关联之前已保存。
感谢 BroiState 和 Mori 给我的一些指示,我能够确定它与持久性有关(特别是我的一个对象方法不尊重它!)
trainee.current_membership的代码如下:
def current_membership
return unless memberships.current.any?
memberships.current.first
end
在成员资格中使用这些相关范围...
scope :started, -> { self.where("#{table_name}.#{_start_field}::TIMESTAMP < '#{Time.now}'") }
scope :not_ended, -> { self.where("#{table_name}.#{_end_field} IS NULL OR #{table_name}.#{_end_field}::TIMESTAMP > '#{Time.now}'") }
scope :current, -> { self.started.not_ended }
所以每次调用 trainee.current_membership 都会给我一个 'current' 会员记录的新实例
通过明确使用同一对象,规范顺利通过,即:
it 'sets specialty' do
membership = trainee.current_membership
membership.specialty = specialty
membership.save!
expect(membership.specialty).to eq(specialty.reload)
end