문제

나는 내가 이해하지 못하는 일부 레일 2.3.5 activerecord 동작에 빠지고있다. 객체는 일관되지 않은 방식으로 연결 ID를 업데이트 할 수있는 것으로 보입니다.

이것은 예를 들어 가장 잘 설명됩니다.

a Post 문자열 속성이있는 모델 'title' 그리고 a Comment 문자열 속성이있는 모델 'content'.

협회는 다음과 같습니다.

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

시나리오 #1 : 다음 코드에서 하나를 만듭니다. Post 관련 Comment, 두 번째를 만듭니다 Post ~에 의해 find'첫 번째, 두 번째를 추가하십시오 Comment 첫 번째 Post 그리고 두 번째를 발견하십시오 Post 두 번째가 있습니다 Comment 명시적인 할당없이 그것과 관련이 있습니다.

post1 = Post.new
post1 = Post.new(:title => 'Post 1')
comment1 = Comment.new(:content => 'content 1')
post1.comments << comment1
post1.save
# Create a second Post object by find'ing the first
post2 = Post.find_by_title('Post 1')
# Add a new Comment to the first Post object
comment2 = Comment.new(:content => 'content 2')
post1.comments << comment2 
# Note that both Comments are associated with both Post objects even
# though I never explicitly associated it with post2.
post1.comment_ids # => [12, 13]
post2.comment_ids # => [12, 13]

시나리오 #2 : 위의 명령을 다시 실행하지만 이번에는 결과에 영향을 미치지 않아야하는 추가 명령을 삽입합니다. 추가 명령은입니다 post2.comments 발생합니다 ~ 후에 창조 comment2 그리고 ~ 전에 첨가 comment2 에게 post1.

post1 = Post.new
post1 = Post.new(:title => 'Post 1A')
comment1 = Comment.new(:content => 'content 1A')
post1.comments << comment1
post1.save
# Create a second Post object by find'ing the first
post2 = Post.find_by_title('Post 1A')
# Add a new Comment to the first Post object
comment2 = Comment.new(:content => 'content 2A')
post2.comments # !! THIS IS THE EXTRA COMMAND !!
post1.comments << comment2 
# Note that both Comments are associated with both Post objects even
# though I never explicitly associated it with post2.
post1.comment_ids # => [14, 15]
post2.comment_ids # => [14]

전용이 있습니다 하나 관련 댓글 post2 이 시나리오에는 시나리오 1에는 두 가지가있었습니다.

큰 질문 : 왜 실행되는지 post2.comments 새를 추가하기 전에 Comment 에게 post1 의견이 관련된 차이를 만듭니다 post2?

도움이 되었습니까?

해결책

이는 활성 레코드가 캐시를 캐시하는 방식과 has_many 연관성을 처리하는 방식과 관련이 있습니다.

협회가 다음과 같은 옵션을 포함하는 경우 협회에 열망하지 않는 한. Rails는 필요할 때까지 발견 된 기록에 대한 협회를 채우지 않습니다. 협회가 필요할 때 메모 화 실행 된 SQL 쿼리 수를 줄이기 위해 수행됩니다.

질문의 코드를 통해 발전 :

post1 = Post.new(:title => 'Post 1')
comment1 = Comment.new(:content => 'content 1')
post1.comments << comment1  # updates post1's internal comments cache
post1.save 

# Create a second Post object by find'ing the first
post2 = Post.find_by_title('Post 1') 

# Add a new Comment to the first Post object
comment2 = Comment.new(:content => 'content 2')
post1.comments << comment2   # updates post1's internal comments cache

# Note that both Comments are associated with both Post objects even
# though I never explicitly associated it with post2.
post1.comment_ids # => [12, 13]

# this is the first time post2.comments are loaded. 
# SELECT comments.* FROM comments JOIN comments.post_id = posts.id WHERE posts.id = #{post2.id}
post2.comment_ids # => [12, 13]

시나리오 2 :

post1 = Post.new(:title => 'Post 1A')
comment1 = Comment.new(:content => 'content 1A')
post1.comments << comment1
post1.save

# Create a second Post object by find'ing the first
post2 = Post.find_by_title('Post 1A')

# Add a new Comment to the first Post object
comment2 = Comment.new(:content => 'content 2A')

# first time post2.comments are loaded. 
# SELECT comments.* FROM comments JOIN comments.post_id = posts.id WHERE 
#   posts.id = post2.comments #=> Returns one comment (id = 14)
# cached internally.

post1.comments << comment2 
# Note that both Comments are associated with both Post objects even
# though I never explicitly associated it with post2.
post1.comment_ids # => [14, 15]

# post2.comment has already been cached, so the SQL query is not executed again.

post2.comment_ids # => [14]

NB post2.comment_ids 내부적으로 정의됩니다 post2.comments.map(&:id)

추신 : 내 대답 이 질문 Post2가 만지지 않더라도 업데이트되는 이유를 이해하는 데 도움이 될 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top