'한 가지 질문이 있습니다.'

최근에 논문을 쓰고 있는데 Rails에서has one 연결을 사용할 때 재미있는 문제가 생겼어요.하지만 시작하기 전에 Rails에서 어떻게 작동하는지 알아보기 위해 한 발 물러서겠습니다.

철도 협회


나는 본문을 읽는 모든 사람들이 데이터베이스와 대상 관계 맵을 알고 있거나 깊이 이해한다고 가정하지 않기 때문에 가능한 한 간단명료하고 간단하게 유지할 것이다.만약 당신이 더욱 깊이 이해하고 싶다면Rails docs은 특정한 배경에서 이 점을 이해하는 좋은 출발점이다.
만약에 콘텐츠 사이트를 만들고 싶다면 서로 다른 창설자가 그 중에서 댓글을 만들 수 있다. 당신은 관계 데이터베이스를 만들 수 있다. 그 중에서 두 개의 테이블Creator와 Post가 있는데 이렇게 보일 수 있다.

creator 테이블은 만든 항목마다 ID와Name 열이 있고 post 테이블은 항목마다 ID, 타이틀, 타입, 바디 열이 있습니다.각 열에서 마스터 키는 각 레코드의 고유한 식별자이기 때문에 ID 열입니다.primary key는 관련표를 작성할 때 매우 중요하다. 왜냐하면 이것은 관련표의 foreign key를 충당하기 때문이다.
현재 우리는 이 두 표 사이의 관계를 결정해야 한다. 왜냐하면 우리는 어떤 창설자가 어떤 댓글을 만들었는지 알고 싶기 때문이다.너는 몇 가지 다른 관련을 만들 수 있지만, 나는 단지 두 가지만 이야기할 것이다.

너는 많다


A는 여러 가지 연관이 있는데 이것은 한 테이블의 한 항목이 다른 테이블의 많은 항목과 연관될 수 있음을 나타낸다.예를 들어 시스템이 표준 컨텐트 작성 시스템인 경우 작성자가 여러 게시물을 작성할 수 있기 때문에 작성자가 여러 게시물을 작성할 수 있습니다. 이 경우 Rails의 연관성은 다음과 같습니다.
class Creator < ApplicationRecord
  has_many :posts
end
class Post < ApplicationRecord
  belongs_to :creator
end
데이터베이스는 다음과 같습니다.
creator_idid열에서 추출됩니다. 이 열은creator표의 메인 키이고post표의 외부 키를 충당합니다.따라서 Tiffany Pollard에서 만든 모든 게시물을 찾으려면 게시물표에서 검색해야 합니다. 그 중 creator_id은creator 표의 Tiffany Pollardid와 일치합니다.

있다

has_one 관계는 한 표의 한 항목이 다른 표의 한 항목과 연결될 수 있고 한 항목을 초과할 수 없다는 것을 나타낸다.작성자가 게시물 한 편만 작성할 수 있는 시스템을 만들려고 할 수 있습니다. 이 경우 Rails 코드는 다음과 같습니다.
class Creator < ApplicationRecord
  has_one :post
end
class Post < ApplicationRecord
  belongs_to :creator
end
창설자has_one 게시물과 창설자belongs_to 게시물.데이터베이스는 이전과 같습니다.
has_many와 마찬가지로 creator_id는post표의 창설자id의 외키입니다.
네, 지금부터 이 문제를 토론하겠습니다.
...

문제.


Rails에서 연결has_one을 만들 때 한 작성자가 하나의 게시물만 있을 수 있다는 것을 이해할 수 있습니다.그렇다면 한 창설자가 다른 댓글을 만들려고 시도할 때 어떤 일이 일어날까요?한 편의 댓글이 존재하는지 확인하고, 창작자에게 댓글을 바꾸고 싶은지, 아니면 이것이 창작자의 의도라고 가정해서 댓글을 바꾸고 싶은지 물어보길 바란다.그러나 사실은 그렇지 않다. 반대로 너는 이런 실수를 당할 것이다.

이것은 has_one의 흔히 볼 수 있는 오류로 issue:

This is because prior to deleting, the foreign key of the target association is set to nil and a save operation is performed on the target.


왜 이런 상황이 발생했는지는 아직 알 수 없다. 만약 당신이 이 문제를 자세히 연구한다면, 2014년에 창립되었고, 토론은 여전히 진행 중이라는 것을 발견할 수 있을 것이다.이것은 버그에서 시작된 것 같지만, 이미 필요한 기능으로 변했을 수도 있다.

복구



이 문제를 해결할 수 있는 많은 방법이 있는데, 이것은 너의 시스템에 달려 있다.기본적으로 새 연결을 만들기 전에 오래된 연결을 삭제해야 합니다.그래서 너는 너의 모형에서 이렇게 할 수 있다.
class Creator < ApplicationRecord
  has_one :post, dependent: :destroy
end
class Post < ApplicationRecord
  belongs_to :creator
end
또는 리소스를 만드는 방법(컨트롤러 또는 특정lib 파일)에서 다음을 실행할 수 있습니다.
creator = Creator.find_by_id(id)
creator.post&.delete
게시물을 작성하기 전에앤디 크롤(Andy Croll)은 표지책에서 추천rolling things up in a transaction했고, GitHub issue에서도 더 많은 조언이 있었다.

한층 더 읽다

  • Be Careful Assigning has_one Relations
  • Building a has_one association fails on save if target has a validation on foreign_key
  • BBC Bitesize: Introducing Databases
  • Rails ActiveRecord Associations
  • 좋은 웹페이지 즐겨찾기