2016-08-20 4 views
4

У меня есть проблема с ошибкой:Factory Girl, проблема с ошибкой InvalidRecord

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 

Factory:

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={}> 

У вас есть предложение, как отлаживать, что запись является недействительным?

Update:

Полное сообщение об ошибке:

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)>' 

Update 2:

, когда я установил date_of_training Date.today на заводе ошибка исчезает. Я также попытался установить вручную дату, например, 2016-08-23, но она по-прежнему InvalidRecord. Также Date.today + 1.day не работает. Любая идея, что может быть неправильным? Возможно, date_of_training не является прямой проблемой.

Update 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 

Update 4: Я заметил, что если я первый выполнить ind.valid? - это будет правда, и ind2 будет RecordInvalid. Но когда я перезагружаю и проверяю ind2.valid? - теперь это правда и ind false.

Обновление 5: Я использовал то же let, но отдельно в другом контексте, и rspec прошел. Что может быть причиной того, что я не могу использовать два let в том же контексте?

IndividualTraining ассоциации

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 

Update 6: В другом контексте у меня есть это позволить:

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

+0

Вы уверены, что связанные объекты действительны? –

+0

Не могли бы вы добавить полное сообщение об ошибке, чтобы мы могли использовать такие строки, как номер строки, файл, полное сообщение об ошибке и т. Д.? – kcdragon

+0

@ MichałSzajbe да, я уверен, потому что я проверил эти заводы в других тестах. –

ответ

2

Это может быть причиной «Invalid ошибки рекорд» -

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. 

Во-первых, я предлагаю вам использовать метод сборки и проверьте валидаций, связанные с ним. В ваших проверках что-то не так.

Смежные вопросы