협회를 통한 belongs_to


141

다음과 같은 연관성을 고려할 때 Questiona ChoiceChoice모델 에서 연결되어 있음 을 참조해야합니다 . belongs_to :question, through: :answer이 작업을 수행하는 데 사용하려고했습니다 .

class User
  has_many :questions
  has_many :choices
end

class Question
  belongs_to :user
  has_many :answers
  has_one :choice, :through => :answer
end

class Answer
  belongs_to :question
end

class Choice
  belongs_to :user
  belongs_to :answer
  belongs_to :question, :through => :answer

  validates_uniqueness_of :answer_id, :scope => [ :question_id, :user_id ]
end

나는 얻고있다

NameError 초기화되지 않은 상수 User::Choice

내가 할 때 current_user.choices

내가 포함하지 않으면 잘 작동합니다.

belongs_to :question, :through => :answer

그러나 나는 그것을 할 수 있기를 원하기 때문에 그것을 사용하고 싶습니다. validates_uniqueness_of

아마도 간단한 것을 간과하고있을 것입니다. 도움을 주시면 감사하겠습니다.


1
수락 된 답변을 대리인에게 변경하는 것이 가치가 있습니까?
23inhouse

답변:


60

belongs_to협회는 할 수 없습니다 :through옵션을 선택합니다. 당신은 캐싱 더 낫다 question_idChoice테이블에 고유 인덱스를 추가 (특히 때문에이 validates_uniqueness_of경쟁 조건하는 경향이있다).

편집증 환자라면 Choice답변의 question_id일치 여부 를 확인 하는 사용자 지정 유효성 검사를 추가 하지만 최종 사용자에게 이러한 종류의 불일치를 생성하는 데이터를 제출할 기회가 주어지지 않는 것처럼 들립니다.


고마워 Stephen, 나는 정말로 question_id와 직접 연결하고 싶지는 않지만 가장 쉬운 방법이라고 생각합니다. 내 원래 생각은 "답변"이 "질문"에 속하기 때문에 항상 "답변"을 통해 "질문"에 도달 할 수 있습니다. 그러나 그렇게하기가 쉽지 않다고 생각합니까, 아니면 단지 잘못된 스키마라고 생각합니까?
vinhboy

고유 제한 조건 / 확인을 원하는 경우 범위가 지정된 필드가 동일한 테이블에 존재해야합니다. 경쟁 조건이 있음을 기억하십시오.
stephencelis

1
>> 최종 사용자에게 이런 종류의 불일치가 발생하는 데이터를 제출할 기회가 주어지지 않아야 할 것 같습니다. -서버 측에서 명시 적으로 확인하지 않으면 사용자가 "무언가를 수행 할 기회가 없다"고 보장 할 수 없습니다.
Konstantin

376

다음을 위임 할 수도 있습니다.

class Company < ActiveRecord::Base
  has_many :employees
  has_many :dogs, :through => :employees
end

class Employee < ActiveRescord::Base
  belongs_to :company
  has_many :dogs
end

class Dog < ActiveRecord::Base
  belongs_to :employee

  delegate :company, :to => :employee, :allow_nil => true
end

27
+1, 이것이 가장 깨끗한 방법입니다. (적어도 내가 생각할 수있는)
Orlando

9
너무 많은 쿼리를 사용하지 않도록 JOIN 으로이 작업을 수행하는 방법이 있습니까?
Tallboy

1
나 자신을 알고 싶습니다. 내가 시도한 모든 것은 3 선택을 해고했습니다. 연관에 "-> {joins : something}"람다를 지정할 수 있습니다. 조인은 해고되었지만 결과적으로 다른 선택이 발생합니다. 나는 이것을 조정할 수 없었다.
Renra

2
@Tallboy 기본 키에 대해 완벽하게 색인화 된 일부 선택 쿼리는 거의 모든 단일 JOIN 쿼리보다 좋습니다. 조인하면 데이터베이스가 제대로 작동합니다.
Ryan McGeary

1
allow_nil은 무엇을합니까? 직원이 항상 회사를 가져서는 안됩니까?
aaron-coding

115

다음 과 같이 has_one대신 대신 사용 하십시오.belongs_to:through

class Choice
  belongs_to :user
  belongs_to :answer
  has_one :question, :through => :answer
end

관련이 없지만 데이터베이스에서 적절한 고유 제약 조건을 사용하는 대신 validates_uniqueness_of를 사용하는 것이 주저합니다. 루비에서이 작업을 수행하면 경쟁 조건이 있습니다.


38
이 솔루션에 대한 큰 경고. 선택 사항을 저장할 때마다 autosave: false설정되어 있지 않으면 항상 질문 이 저장 됩니다.
Chris Nicola

@ChrisNicola 당신이 무슨 뜻인지 설명해 주시겠습니까?
aks

내가 어디에서 무엇을 의미 했습니까? 적절한 고유 제한 조건을 의미하는 경우 데이터베이스에서 고유해야하는 열 / 필드에 UNIQUE 색인을 추가하는 것을 의미합니다.
Chris Nicola

4

내 접근법은 데이터베이스 열을 추가하는 대신 가상 속성을 만드는 것이 었습니다.

class Choice
  belongs_to :user
  belongs_to :answer

  # ------- Helpers -------
  def question
    answer.question
  end

  # extra sugar
  def question_id
    answer.question_id
  end
end

이 방법은 매우 간단하지만 단점이 있습니다. answerDB에서 Rails를로드 한 다음에 로드해야합니다 question. 나중에 필요한 연결을 열망하여 나중에 최적화 할 수 c = Choice.first(include: {answer: :question})있지만,이 최적화가 필요한 경우 stephencelis의 답변이 더 나은 성능 결정일 것입니다.

특정 선택을위한 시간과 장소가 있으며, 프로토 타입을 만들 때이 선택이 더 낫다고 생각합니다. 자주 사용하지 않는 경우가 아니라면 프로덕션 코드에 사용하지 않습니다.


1

질문이 많은 사용자가 원하는 것 같습니다.
질문에는 많은 답변이 있으며 그중 하나가 사용자의 선택입니다.

이것이 당신이 무엇을하고 있습니까?

이 라인을 따라 이와 같은 것을 모델링합니다.

class User
  has_many :questions
end

class Question
  belongs_to :user
  has_many   :answers
  has_one    :choice, :class_name => "Answer"

  validates_inclusion_of :choice, :in => lambda { answers }
end

class Answer
  belongs_to :question
end

1

그래서 당신은 당신이 원하는 행동을 할 수 없지만 당신은 그것과 같은 느낌을 줄 수 있습니다. 당신은 할 수 있기를 원합니다Choice.first.question

내가 과거에 한 일은 다음과 같습니다

class Choice
  belongs_to :user
  belongs_to :answer
  validates_uniqueness_of :answer_id, :scope => [ :question_id, :user_id ]
  ...
  def question
    answer.question
  end
end

이 방법으로 당신은 지금 선택에 대한 질문을 할 수 있습니다


-1

이 아닌 has_many :choices이라는 이름의 연결을 만듭니다 . 대신 사용해보십시오 .choiceschoicecurrent_user.choices

마법 에 대한 정보 는 ActiveRecord :: Associations 문서를 참조하십시오 has_many.


1
하지만 도와 주셔서 감사합니다. Michael, 그것은 저의 오타입니다. 이미 current_user.choices를하고 있습니다. 이 오류는 사용자와 질문에 belongs_to를 할당하고 싶은 것과 관련이 있습니다.
vinhboy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.