質問

私は理解していないいくつかのRails 2.3.5のActiveRecordの行動に実行しています。オブジェクトがそのアソシエーションIDが一貫性のない方法で更新することができように思われます。

これは最良の例で説明されています:

文字列の属性Postと文字列の属性'title'Commentモデルと'content'モデルを作成します。

ここでは関連はあります:

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

シナリオ#1:私は関連Post有するものCommentを作成する次のコードでは、最初のPost'ingことにより、第2 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:再度、上記のコマンドを実行しますが、今回はそれの顔に、結果に影響を与えてはならない、1つの余分のコマンドを挿入します。余分なコマンドは、の後にの作成post2.commentscomment2を追加することが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]

シナリオ1二つがあったのに対し、このシナリオでpost2に関連付けられている唯一の 1 のコメントがあることに留意されたいです。

ビッグ質問:なぜコメントがpost2.commentsに関連付けされたに違いを作るCommentする新しいpost1を追加する前にpost2を実行しているのでしょうか?

役に立ちましたか?

解決

これは、アクティブレコードを要求し、has_manyの団体が処理される方法をキャッシュする方法に関係しています。

関連付けがでeagerloadedされていない場合:検索時のオプションが含まれています。必要になるまで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]

N.B。 post2.comment_idsが内部post2.comments.map(&:id)として定義されている。

P.S。私の答えはhref="https://stackoverflow.com/questions/2252743/calling-activerecords-relationship-ids-1-2-3-saves-immediately-any-workaro/2254992#2254992">にこの質問を POST2はあなたがそれに触れていないにも関わらず更新される理由を理解するのに役立つかもしれません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top