Вставка нарушает ограничения внешнего ключа - PullRequest
2 голосов
/ 17 мая 2019

Мои модели:

class Team < ApplicationRecord
    belongs_to :objective
    belongs_to :consultancy
    has_one :seminar, :through => :consultancy

    belongs_to  :consultant, class_name: "Student"

    has_and_belongs_to_many  :users
end

class User < ApplicationRecord
    has_and_belongs_to_many  :teams
end

Моя функция:

def find_placement(student)
    team = @consultancy.teams.detect{|x| x.has_room && student.objective_students.find_by(:objective => x.objective).obj_ready_and_willing?}
    team.users << student if team && team.valid? && team.persisted?
    return team
end

И эта ошибка, которую я сейчас получаю:

PG::ForeignKeyViolation: ERROR: insert or update on table "teams_users" violates foreign key constraint "fk_rails_8299e376e9" DETAIL: Key (team_id)=(3396) is not present in table "teams". : INSERT INTO "teams_users" ("user_id", "team_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4)

Эта ошибка возникает только в производственной среде, а не в разработке или тестировании. Я пытался использовать режим консоли, чтобы вручную запустить каждую строку функции. Ошибка не вызывается.

Из этого вопроса https://dba.stackexchange.com/questions/29147/postgresql-insert-update-violates-foreign-key-constraints, Я нашел это объяснение.

"Если вставлена ​​новая строка, проверьте DataID и Address: если они содержат ненулевое значение (скажем, 27856), то проверьте Table1 для DataID˙ и Table2 для Address. Если такого значения в эти таблицы, а затем вернуть ошибку. "

Если я правильно понимаю этот абзац, моя функция - попытаться включить ученика в команду, которой не существует. Но разве «если команда && team.valid? && team.persisted?» часть моего кода позаботится об этом? Если нет, то как лучше вставить ученика в команду, но только если команда уже существует.

Заранее спасибо за понимание.

Ответы [ 2 ]

1 голос
/ 18 мая 2019

Ключом к преодолению этого было перезагрузить.

Раньше @consultancy собирал все команды, включая некоторые, которые были уничтожены.

@consultancy.reload.teams

собирает только те команды, которые еще существуют.

Я бы не пришел к такому выводу без комментария @SergioTulentsev и ответа от @lacostenycoder. Спасибо!

1 голос
/ 18 мая 2019

Метод valid? не проверяет постоянство базы данных, поэтому он может вам понадобиться или не понадобиться. Возможно, вы захотите убедиться, что модель team сохраняется и не удаляется из таблицы команд. Чтобы быть в безопасности, вы можете проверить оба. ActiveRecord#persisted? метод:

def find_placement(student)
  if team = @consultancy.teams.detect{|x| x.has_room && student.objective_students.find_by(:objective => x.objective).obj_ready_and_willing?}
    team.users << student if team.valid? && team.persisted?
  end
  team
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...