레일스 : 레일에서 has_one 연관으로 빌드 사용


143

이 예에서는 userno profile로을 만든 다음 나중에 profile해당 사용자에 대한을 만듭니다 . has_one협회 와 함께 빌드를 사용해 보았지만 폭발했습니다. 이 작업을 보는 유일한 방법은has_many 입니다. 는 user단지 대부분의 일에있을 예정이다 profile.

나는 이것을 시도했다. 나는 가지고있다:

class User < ActiveRecord::Base
  has_one :profile
end

class Profile < ActiveRecord::Base
  belongs_to :user
end

그러나 내가 할 때 :

user.build_profile 

오류가 발생합니다.

ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'profiles.user_id' in 'where clause': SELECT * FROM `profiles` WHERE (`profiles`.user_id = 4)  LIMIT 1

레일에 0 또는 1의 연관성을 갖는 방법이 있습니까?


정확히 무엇을 시도 했습니까? 코드를 게시 해 주시겠습니까?
Ju Nogueira

답변:


359

build메소드 서명은 다르다 has_onehas_many 협회.

class User < ActiveRecord::Base
  has_one :profile
  has_many :messages
end

에 대한 빌드 구문 has_many연관을 :

user.messages.build

에 대한 빌드 구문 has_one연관을 :

user.build_profile  # this will work

user.profile.build  # this will throw error

자세한 내용 은 has_one연결 설명서 를 읽으십시오 .


28
has_one에 대한 다른 구문은 항상 나를 잡아냅니다 ... 젠장!
Galaxy

11
여기서 최고 등급의 승인 된 답변이 OP가 요청한 것과 다른 질문에 어떻게 대답하는지는 재미 있습니다.
Ajedi32

아마도 사용자가 프로파일에 속한 경우 (사용자 테이블에 테이블에 foreign_key profile_id가 있음을 의미) 사용자에 대한 프로파일 작성은 위에서 언급 한 것처럼 작동하지만 user.build_profile 편집 전용의 새로운 조치 user.build_profile if user.profile.nil? 와 사용자를 작성하는 동안 프로파일을 작성하려는 경우에 작성 accepts_nested_attributes_for :profile하십시오. 사용자 모델. 그리고 어떤 사용자가 생성되고있는 형태로 이것을 작성 <%= f.simple_fields_for :profile do |p| %>하고 계속 진행하십시오.
열의

그러나 왜이 다른 행동이 has_one 또는 has_many에 대해 유지 되었습니까? 디자인하는 동안 어떤 이유가있을 것이라고 생각합니다.
호기심 많은

@ Ajedi32 답변은 질문의 제목과 일치하지만 본문은 아닙니다. build_<association>Rails에서는 이것이 ( ) 매우 이상하고 예상치 못한 행동 이라는 것을 감안할 때 , 내가 무슨 뜻인지 알면 실제 질문에 대한 답변보다이 답변을 찾는 사람들이 훨씬 더 많습니다.
Max Williams

19

오류 메시지를 잘보십시오. 프로파일 테이블user_id 에 필수 열이 없음을 알려 줍니다 . 모델의 관계 설정은 답의 일부일뿐입니다.

또한 user_id열을 프로파일 테이블에 추가하는 마이그레이션을 작성해야 합니다. Rails는 이것이있을 것으로 예상하고, 존재하지 않으면 프로파일에 액세스 할 수 없습니다.

자세한 내용은 다음 링크를 참조하십시오.

협회 기본


1
방금 내 문제를 알아 냈습니다. 내가 배우고있는 책은 외래 키 생성을 잘 설명하지 못했습니다. 모델에 외래 키를 추가하는 새로운 마이그레이션을 만들었습니다. 감사.
espinet

매번 열을 직접 만들어야합니까? 나는 그것이 자동적으로 일어난다는 생각을 가지고 있었다. 나는 그 아이디어를 어디서 얻었는지 모른다.
Rimian

명령 행을 사용하여 모델을 생성 할 때 다음과 같은 열을 추가 할 수 있습니다 rails g model profile user:references:index address:string bio:text.
duykhoa

1

유스 케이스에 따라 메소드를 랩하고 찾을 수 없을 때 자동으로 연관을 빌드하는 것이 편리 할 수 ​​있습니다.

old_profile = instance_method(:profile)
define_method(:profile) do
  old_profile.bind(self).call || build_profile
end

이제 #profile메소드를 호출하면 연관된 프로파일을 리턴하거나 새 인스턴스를 빌드합니다.

출처 : 원숭이가 메소드를 패치 할 때 새로운 구현에서 재정의 된 메소드를 호출 할 수 있습니까?


1
현재 레일 (6.0.2.2에서 테스트)에서이를 단순화 할 수 있습니다 def profile; super || build_profile; end.
glasz

-14

이어야합니다 has_one. 경우 build작동하지 않습니다, 당신은 사용할 수 있습니다 new:

ModelName.new( :owner => @owner )

와 같다

@owner.model_names.build

11
동일하지 않습니다. 빌드로 새 model_name을 작성하고 @owner를 저장하면 새 model_name도 저장됩니다. 따라서 빌드를 사용하여 함께 저장 될 부모와 자식을 만들 수 있습니다. .new로 model_name을 만드는 경우에는 해당되지 않습니다.
Max Williams
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.