2013-10-26 5 views
0

has_one 연관 메소드가 일관성없이 실행되고 있으며 이유를 알지 못합니다. 이 반환레일 : 왜 has_one 연관 메소드가 일관성없이 동작합니까?

container = Container.create 
... 

container.build_super 
... 
=> #<Super id: nil, container_id: 1, content: nil, created_at: nil, updated_at: nil> 

container.super 
=> #<Super id: nil, container_id: 1, content: nil, created_at: nil, updated_at: nil> 

당신이 위의 코드에 container.super를 호출 할 때 : 예상대로

class Container < ActiveRecord::Base 
    has_one: :super 
end 

class Super < ActiveRecord::Base 
    belongs_to: :container 
end 

다음 코드는 작동 :

는 서로 연관되어 두 가지 간단한 모델을 가지고 Super 클래스의 새로 작성된 인스턴스

다음 코드 그러나 작동하지 않습니다 : 그것은 DB를 슈퍼의 인스턴스를 찾고있을 나타나기 때문에

Container.create 
... 
=> #<Container id: 1, created_at: "2013-10-26 20:31:26", updated_at: "2013-10-26 20:31:26"> 

Container.first.build_super 
... 
=> #<Super id: nil, container_id: 1, content: nil, created_at: nil, updated_at: nil> 

Container.first.super 
    Container Load (0.2ms) SELECT "containers".* FROM "containers" ORDER BY "containers"."id" ASC LIMIT 1 
    Super Load (0.1ms) SELECT "supers".* FROM "supers" WHERE "supers"."container_id" = ? ORDER BY "supers"."id" ASC LIMIT 1 [["container_id", 1]] 
=> nil 

Container.first.super이 전무를 반환합니다. 그러나 인스턴스는 아직 커밋되지 않았습니다.

하지만 container == Container.first 일 때 container.super와 Container.first.super가 같은 결과를 얻지 못하는 이유는 무엇입니까?

+0

는 save'에'호출 시도 되세요 'build_super'에 의해 생성 된 인스턴스? 이것이 Container.first.super가없는 이유입니다. 또한, 나는 그것이 아마도 _ 여기에 문제가 아니라는 것을 알고 있지만, 슈퍼는 예약어이며 어떤 광기를 유발할 수 있습니다. – struthersneil

+0

무슨 일이 일어나고있는간에'container.super'는 연결에서 방금 생성 한 객체에 대한 참조를 저장하지 않은 경우에도 참조를 가진다는 것입니다. 'Container.first.super'는 실제로 읽기를 수행해야합니다. – struthersneil

답변

2

Container.first.build_super은 컨테이너 레코드의 복사본을 가져 와서 연관 인스턴스를 작성하고이 연관 인스턴스를 해당 컨테이너 레코드 사본에 캐시합니다.

이 후 Container.first.super을 호출하면 컨테이너 레코드의 별도 복사본이 반입되며 :super에 대해 아무 것도 발견되지 않습니다. 기본적으로

, 당신은이 일을하고 있습니다 :

a = Container.first # New instance 
a.build_super   # Assign to :super 

b = Container.first # Separate instance 
b.super    # Nothing in :super 

당신이 아마하고 싶은 것은 다른 복사본을 가져 오는 대신 변수에이를 할당 할 수 있습니다 :

container = Container.first 
container.build_super 
container.super 
+0

위대한 설명! Container.first를 호출 할 때마다 새로운 사본을 작성하는 것을 보지 못했지만 의미가 있습니다. – earksiinni

2

첫 번째 예제에서 수퍼 개체는 메모리에 내장되어 있으며 데이터베이스에서 다시로드하면 손실됩니다 (두 번째 예제에서와 같이). container.reload.super을 첫 번째 예제에서 데이터베이스에서로드하려면 메모리 내 개체가 손실되고 nil이됩니다.

사이드 노트 : "슈퍼"라는 이름을 붙이는 것은 정말 좋은 생각입니다. 이것은 서브 클래스가 서브 클래스를 오버라이드 할 때 부모 클래스의 메소드를 호출하기 위해 Ruby에서 예약 된 키워드입니다.

+0

+1 "super". – kristinalim

+0

* 머리를 쓰다듬어 * 그래, 슈퍼가 정확히 최고의 선택이 아니었다 ... – earksiinni