Factory Girl,InvalidRecord 错误问题
Factory Girl, issue with InvalidRecord error
我对错误有疑问:
ActiveRecord::RecordInvalid
由此造成的:
let(:ind2){ build(:ind2) }
Rspec 测试:
describe '#client_free_time_validation' do
let(:ind) { build(:ind).tap {|e| p e.valid?; p e.errors}}
let(:ind2){ build(:ind2).tap {|e| p e.valid?; p e.errors} }
context 'when training is during another training' do
it 'raises an error' do
expect(ind.valid?).to be_truthy
expect(ind2.valid?).to be_falsey
# expect(ind2.errors.count).to eq 1
# expect(ind2.errors[:base]).to eq(['Masz w tym czasie inny trening.'])
end
end
工厂:
FactoryGirl.define do
factory :individual_training do
date_of_training { Date.today.next_week.advance(days: 1) }
association :client, factory: :client
association :trainer, factory: :trainer
start_on Time.parse('12:30')
end_on Time.parse('13:30')
association :training_cost, factory: :tc2
factory :ind do
start_on Time.parse('11:00')
end_on Time.parse('12:00')
end
factory :ind2 do
start_on Time.parse('10:30')
end_on Time.parse('11:30')
end
end
end
我很困惑,因为类似 let
在另一个测试中工作。我尝试使用 tap
方法进行调试,但它没有显示错误消息(在另一种情况下,很好的礼物)。
如果我应该添加一些额外的数据(我的模型看起来如何等),请写信。
我看到如果我评论第一个 let
或第二个,测试通过。它着眼于两个 let
(ind
和 ind2
)无法一起工作的情况。
测试生成的属性示例值:
#<ActiveModel::Errors:0x00000001f4ade8 @base=#<IndividualTraining id: nil, date_of_training: "2016-08-23", client_id: 28, trainer_id: 29, start_on: "2016-08-20 11:00:00", end_on: "2016-08-20 12:00:00", training_cost_id: 4>, @messages={}>
您对如何调试无效记录有什么建议吗?
更新:
完整错误信息:
Failure/Error: let(:ind2){ build(:ind2).tap {|e| p e.valid?; p e.errors} }
ActiveRecord::RecordInvalid:
Nieprawidłowy rekord
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/validations.rb:79:in `raise_record_invalid'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/validations.rb:43:in `save!'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/attribute_methods/dirty.rb:29:in `save!'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb:291:in `block in save!'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb:351:in `block in with_transaction_returning_status'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb:220:in `transaction'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb:348:in `with_transaction_returning_status'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb:291:in `save!'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/configuration.rb:18:in `block in initialize'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/evaluation.rb:15:in `create'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy/create.rb:12:in `block in result'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy/create.rb:9:in `tap'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy/create.rb:9:in `result'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory.rb:42:in `run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory_runner.rb:29:in `block in run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activesupport-4.2.5.1/lib/active_support/notifications.rb:166:in `instrument'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory_runner.rb:28:in `run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy/build.rb:5:in `association'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/evaluator.rb:31:in `association'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute/association.rb:19:in `block in to_proc'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/evaluator.rb:75:in `instance_exec'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/evaluator.rb:75:in `block in define_attribute'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:56:in `get'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:16:in `block (2 levels) in object'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:15:in `each'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:15:in `block in object'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:14:in `tap'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:14:in `object'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/evaluation.rb:12:in `object'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy/build.rb:9:in `result'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory.rb:42:in `run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory_runner.rb:29:in `block in run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activesupport-4.2.5.1/lib/active_support/notifications.rb:166:in `instrument'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory_runner.rb:28:in `run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
# ./spec/models/individual_training_spec.rb:60:in `block (3 levels) in <top (required)>'
# ./spec/models/individual_training_spec.rb:65:in `block (4 levels) in <top (required)>'
更新 2:
当我在 factory 中设置 date_of_training Date.today
时错误消失了。我也尝试手动设置日期,如 2016-08-23,但它仍然是 InvalidRecord
。另外 Date.today + 1.day
不工作。知道有什么问题吗?也许 date_of_training 不是直接问题。
更新 3:
IndividualTraining 模型验证:
private
def date_and_start_on_validation
unless start_on.blank?
if date_of_training < Date.today
errors.add(:base, 'You cannot set individual training before today.')
elsif date_of_training == Date.today
if start_on <= Time.now
errors.add(:base, 'Time of today training is before current time.')
end
end
end
end
# check if trainer work while will be individual_training
def date_of_training_validation
unless start_on.blank?
trainer.work_schedules.each_with_index do |ti, ind|
if ti.day_of_week == BackendController.helpers.translate_date(date_of_training)
if (start_on.strftime('%H:%M')..end_on.strftime('%H:%M'))
.overlaps?(ti.start_time.strftime('%H:%M')..ti.end_time.strftime('%H:%M'))
break
else
errors.add(:base, 'Training is outside of trainer work schedule.')
end
elsif ind == trainer.work_schedules.size - 1
errors.add(:base, 'In this day trainer doesn't work.')
end
end
end
end
# check if client doesn't have another training or activity
def client_free_time_validation
unless start_on.blank?
client.individual_trainings_as_client.where(date_of_training: date_of_training)
.where('id != ?', id).each do |ci|
if (start_on...end_on).overlaps?(ci.start_on...ci.end_on)
errors.add(:base, 'You have another training.')
end
end
client.activities.where(day_of_week: BackendController.helpers.translate_date(date_of_training))
.each do |ca|
if (start_on...end_on).overlaps?(ca.start_on...end_on)
errors.add(:base, 'You have another activity.')
end
end
end
end
更新 4:
我注意到如果我先执行 ind.valid? - 它将为真且 ind2 将为 RecordInvalid。但是当我重新加载并检查 ind2.valid 时? - 现在是真的,现在是假的。
更新 5:
我在不同的上下文中使用了相同的 let ,但 rspec 通过了。可能是什么原因导致我不能在同一上下文中使用两个 let?
个人培训协会
belongs_to :trainer, class_name: 'Person', foreign_key: 'trainer_id'
belongs_to :client, class_name: 'Person', foreign_key: 'client_id'
belongs_to :training_cost
客户和培训师工厂
FactoryGirl.define do
factory :person do
pesel { Faker::Number.number(11) }
first_name 'Thomas'
last_name 'Owel'
date_of_birth { Faker::Time.between('1970-01-01', '2000-12-31') }
email { Faker::Internet.email }
password { Faker::Internet.password }
type 'Person'
end
factory :client, parent: :person, class: 'Client' do
first_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
type 'Client'
end
factory :trainer, parent: :person, class: 'Trainer' do
first_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
type 'Trainer'
salary { Faker::Number.decimal(4, 2) }
hiredate { Faker::Time.between('2016-01-01', '2016-04-30') }
end
end
更新 6:
在另一个上下文中,我有这个 let:
let(:individual_training) { build :individual_training, trainer_id: work_schedule[:person_id] }
let(:ind2) do
build :individual_training,
trainer_id: work_schedule[:person_id],
date_of_training: Date.today.next_week.advance(days: 0),
start_on: Time.now - 1.hour,
end_on: Time.now
end
这个不错的作品。没有报错:RecordInvalid
这些可能是 "Invalid record error" -
背后的原因
Reason - It usually happens when you use "create" and "build" together.
create method persists the instance while the build method keeps it only in memory.
首先,我会建议您使用构建方法,并请检查与之相关的验证。您的验证有问题。
我对错误有疑问:
ActiveRecord::RecordInvalid
由此造成的:
let(:ind2){ build(:ind2) }
Rspec 测试:
describe '#client_free_time_validation' do
let(:ind) { build(:ind).tap {|e| p e.valid?; p e.errors}}
let(:ind2){ build(:ind2).tap {|e| p e.valid?; p e.errors} }
context 'when training is during another training' do
it 'raises an error' do
expect(ind.valid?).to be_truthy
expect(ind2.valid?).to be_falsey
# expect(ind2.errors.count).to eq 1
# expect(ind2.errors[:base]).to eq(['Masz w tym czasie inny trening.'])
end
end
工厂:
FactoryGirl.define do
factory :individual_training do
date_of_training { Date.today.next_week.advance(days: 1) }
association :client, factory: :client
association :trainer, factory: :trainer
start_on Time.parse('12:30')
end_on Time.parse('13:30')
association :training_cost, factory: :tc2
factory :ind do
start_on Time.parse('11:00')
end_on Time.parse('12:00')
end
factory :ind2 do
start_on Time.parse('10:30')
end_on Time.parse('11:30')
end
end
end
我很困惑,因为类似 let
在另一个测试中工作。我尝试使用 tap
方法进行调试,但它没有显示错误消息(在另一种情况下,很好的礼物)。
如果我应该添加一些额外的数据(我的模型看起来如何等),请写信。
我看到如果我评论第一个 let
或第二个,测试通过。它着眼于两个 let
(ind
和 ind2
)无法一起工作的情况。
测试生成的属性示例值:
#<ActiveModel::Errors:0x00000001f4ade8 @base=#<IndividualTraining id: nil, date_of_training: "2016-08-23", client_id: 28, trainer_id: 29, start_on: "2016-08-20 11:00:00", end_on: "2016-08-20 12:00:00", training_cost_id: 4>, @messages={}>
您对如何调试无效记录有什么建议吗?
更新:
完整错误信息:
Failure/Error: let(:ind2){ build(:ind2).tap {|e| p e.valid?; p e.errors} }
ActiveRecord::RecordInvalid:
Nieprawidłowy rekord
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/validations.rb:79:in `raise_record_invalid'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/validations.rb:43:in `save!'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/attribute_methods/dirty.rb:29:in `save!'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb:291:in `block in save!'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb:351:in `block in with_transaction_returning_status'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb:220:in `transaction'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb:348:in `with_transaction_returning_status'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activerecord-4.2.5.1/lib/active_record/transactions.rb:291:in `save!'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/configuration.rb:18:in `block in initialize'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/evaluation.rb:15:in `create'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy/create.rb:12:in `block in result'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy/create.rb:9:in `tap'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy/create.rb:9:in `result'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory.rb:42:in `run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory_runner.rb:29:in `block in run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activesupport-4.2.5.1/lib/active_support/notifications.rb:166:in `instrument'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory_runner.rb:28:in `run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy/build.rb:5:in `association'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/evaluator.rb:31:in `association'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute/association.rb:19:in `block in to_proc'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/evaluator.rb:75:in `instance_exec'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/evaluator.rb:75:in `block in define_attribute'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:56:in `get'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:16:in `block (2 levels) in object'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:15:in `each'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:15:in `block in object'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:14:in `tap'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/attribute_assigner.rb:14:in `object'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/evaluation.rb:12:in `object'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy/build.rb:9:in `result'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory.rb:42:in `run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory_runner.rb:29:in `block in run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/activesupport-4.2.5.1/lib/active_support/notifications.rb:166:in `instrument'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/factory_runner.rb:28:in `run'
# /home/lukas/.rvm/gems/ruby-2.3.1/gems/factory_girl-4.7.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
# ./spec/models/individual_training_spec.rb:60:in `block (3 levels) in <top (required)>'
# ./spec/models/individual_training_spec.rb:65:in `block (4 levels) in <top (required)>'
更新 2:
当我在 factory 中设置 date_of_training Date.today
时错误消失了。我也尝试手动设置日期,如 2016-08-23,但它仍然是 InvalidRecord
。另外 Date.today + 1.day
不工作。知道有什么问题吗?也许 date_of_training 不是直接问题。
更新 3: IndividualTraining 模型验证:
private
def date_and_start_on_validation
unless start_on.blank?
if date_of_training < Date.today
errors.add(:base, 'You cannot set individual training before today.')
elsif date_of_training == Date.today
if start_on <= Time.now
errors.add(:base, 'Time of today training is before current time.')
end
end
end
end
# check if trainer work while will be individual_training
def date_of_training_validation
unless start_on.blank?
trainer.work_schedules.each_with_index do |ti, ind|
if ti.day_of_week == BackendController.helpers.translate_date(date_of_training)
if (start_on.strftime('%H:%M')..end_on.strftime('%H:%M'))
.overlaps?(ti.start_time.strftime('%H:%M')..ti.end_time.strftime('%H:%M'))
break
else
errors.add(:base, 'Training is outside of trainer work schedule.')
end
elsif ind == trainer.work_schedules.size - 1
errors.add(:base, 'In this day trainer doesn't work.')
end
end
end
end
# check if client doesn't have another training or activity
def client_free_time_validation
unless start_on.blank?
client.individual_trainings_as_client.where(date_of_training: date_of_training)
.where('id != ?', id).each do |ci|
if (start_on...end_on).overlaps?(ci.start_on...ci.end_on)
errors.add(:base, 'You have another training.')
end
end
client.activities.where(day_of_week: BackendController.helpers.translate_date(date_of_training))
.each do |ca|
if (start_on...end_on).overlaps?(ca.start_on...end_on)
errors.add(:base, 'You have another activity.')
end
end
end
end
更新 4: 我注意到如果我先执行 ind.valid? - 它将为真且 ind2 将为 RecordInvalid。但是当我重新加载并检查 ind2.valid 时? - 现在是真的,现在是假的。
更新 5: 我在不同的上下文中使用了相同的 let ,但 rspec 通过了。可能是什么原因导致我不能在同一上下文中使用两个 let?
个人培训协会
belongs_to :trainer, class_name: 'Person', foreign_key: 'trainer_id'
belongs_to :client, class_name: 'Person', foreign_key: 'client_id'
belongs_to :training_cost
客户和培训师工厂
FactoryGirl.define do
factory :person do
pesel { Faker::Number.number(11) }
first_name 'Thomas'
last_name 'Owel'
date_of_birth { Faker::Time.between('1970-01-01', '2000-12-31') }
email { Faker::Internet.email }
password { Faker::Internet.password }
type 'Person'
end
factory :client, parent: :person, class: 'Client' do
first_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
type 'Client'
end
factory :trainer, parent: :person, class: 'Trainer' do
first_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
type 'Trainer'
salary { Faker::Number.decimal(4, 2) }
hiredate { Faker::Time.between('2016-01-01', '2016-04-30') }
end
end
更新 6: 在另一个上下文中,我有这个 let:
let(:individual_training) { build :individual_training, trainer_id: work_schedule[:person_id] }
let(:ind2) do
build :individual_training,
trainer_id: work_schedule[:person_id],
date_of_training: Date.today.next_week.advance(days: 0),
start_on: Time.now - 1.hour,
end_on: Time.now
end
这个不错的作品。没有报错:RecordInvalid
这些可能是 "Invalid record error" -
背后的原因Reason - It usually happens when you use "create" and "build" together.
create method persists the instance while the build method keeps it only in memory.
首先,我会建议您使用构建方法,并请检查与之相关的验证。您的验证有问题。