Рельсы подтверждает, что уникальность терпит неудачу странным образом

У меня 2 модели:

class PollAnswer < ActiveRecord::Base

  belongs_to :poll, inverse_of: :poll_answers

  # Validations
  validates :answer, presence: true, uniqueness: { scope: :poll_id, case_sensitive: false }

  validates :votes_number, presence: true
  validates :poll, presence: true
end

class Poll < ActiveRecord::Base
  # Associations
  has_many :poll_answers, inverse_of: :poll, dependent: :destroy

  # Attributes
  accepts_nested_attributes_for :poll_answers, reject_if: :all_blank, allow_destroy: true

  # Validations
  validates :question, presence: true
  validate :has_minimum_2_poll_answers

  private

  def has_minimum_2_poll_answers
    remaining_poll_answers = poll_answers.reject(&:marked_for_destruction?)
    if remaining_poll_answers.size < 2
      errors.add :poll_answers, I18n.t(:minimum_2_poll_answers, scope: "activerecord.errors.models.polls")
    end
  end
end

и простой тест:

let(:new_poll_answer) { build(:poll_answer) }
let(:new_poll_answer1) { build(:poll_answer) }
let(:new_poll) { create(:poll) }

it "validates the uniqueness of an answer scoped to poll_id" do
  new_poll_answer.answer = "andre"
  new_poll_answer.poll = new_poll
  new_poll_answer1.answer = "andre"
  new_poll_answer1.poll = new_poll
  expect(new_poll_answer.valid?).to eq(false)
end

и это не удается:

1) PollAnswer validations validates the uniqueness of an answer scoped to poll_id
     Failure/Error: expect(new_poll_answer.valid?).to eq(false)

   expected: false
        got: true

   (compared using ==)

 # ./spec/models/poll_answer_spec.rb:22:in `block (3 levels) in <top (required)>'
 # -e:1:in `<main>'

Есть идеи почему?

ОБНОВИТЬ:

После комментария Марека Липки я вижу, что это именно моя проблема, потому что именно так работает accepts_nested_attributes_for. так что это не подтверждает уникальность.

Я пытался с этим тестом:

it "validates the uniqueness of an answer scoped to poll_id" do
  new_poll_answer.answer = "andre"
  new_poll_answer.poll = new_poll
  new_poll_answer1.answer = "andre"
  new_poll_answer1.poll = new_poll
  new_poll.save
  puts "#{new_poll.inspect}"
  puts "#{new_poll_answer.inspect}"
  puts "#{new_poll_answer1.inspect}"
  expect(new_poll_answer1.valid?).to eq(false)
end

и я получаю это:

#<Poll id: 62, question: "Question", created_at: "2014-04-08 12:31:06", updated_at: "2014-04-08 12:31:06", active: true, published_at: "2014-04-08 11:31:06">
#<PollAnswer id: nil, answer: "andre", votes_number: 0, poll_id: 62, created_at: nil, updated_at: nil>
#<PollAnswer id: nil, answer: "andre", votes_number: 0, poll_id: 62, created_at: nil, updated_at: nil>

Failures:

  1) PollAnswer validations validates the uniqueness of an answer scoped to poll_id
     Failure/Error: expect(new_poll_answer1.valid?).to eq(false)

       expected: false
            got: true

       (compared using ==)

Что для меня все еще странно, если вы посмотрите на мою пользовательскую проверку для класса опроса has_minimum_2_poll_answers.

Как я могу правильно проверить, что опрос должен быть создан, только если нет poll_answers с тем же ответом?

2 ответа

Вы не сохранили свой первый new_poll_answerпроверка уникальности не работает против несохраненных записей. Вам нужно сделать:

new_poll_answer.save

перед тестированием new_poll_answer1 для действительности.

Также обратите внимание, что помимо требования, чтобы одна из записей была предварительно сохранена, невозможно гарантировать проверку уникальности на прикладном уровне. Проверка уникальности может быть гарантирована только с использованием ограничений уровня базы данных (то есть уникальных индексов).

Выдержка из документации по Rails:

Параллельность и целостность

Использование этого метода проверки в сочетании с ActiveRecord::Validations#save не гарантирует отсутствие дублирующих вставок записей, поскольку проверки уникальности на уровне приложения по своей природе подвержены условиям гонки. Например, предположим, что два пользователя пытаются опубликовать комментарий одновременно, а заголовок комментария должен быть уникальным. На уровне базы данных действия, выполняемые этими пользователями, могут чередоваться следующим образом:

Другие вопросы по тегам