association_proxy.is_a?(Array), acts like an array, but doesn't save like an array
Sep 26, 2007
So, how many times have you had the urge to write:
@post.comments.reject!(&:spam?)
@post.save
Lots? Me too. So, I think it's worth clearing the air on our good friend association proxy. He really, really wants you to believe he's an array. He'll even tell you he is.
assert @post.comments.is_a?(Array)
But, don't believe him, because a lot of his array functionality is useless to us. Your favourite rubyisms (reject!, select!, etc) will modify the collection, but will not modify the associations. This test passes:
def test_association_proxy_really_looks_like_an_array_but_it_isnt
assert Post.find(1).comments.is_a?(Array)
assert Post.find(1).comments.select(&:spam?).length > 0
post = Post.find(1)
post.comments.reject!(&:spam?)
post.save!
assert_equal [], post.comments.select(&:spam?)
assert Post.find(1).comments.select(&:spam?).length > 0
end
Instead, of course, you have to use the delete method.
post.comments.delete(post.comments.select(&:spam?))
Association proxy is tricky.