Skip to content

Instantly share code, notes, and snippets.

@hovsater
Last active October 22, 2021 16:25
Show Gist options
  • Save hovsater/2bc94639fdd0c95231bda7ca429112a9 to your computer and use it in GitHub Desktop.
Save hovsater/2bc94639fdd0c95231bda7ca429112a9 to your computer and use it in GitHub Desktop.
Potential bug

Let's imagine a User model with a has many posts relationship. It has an associated scope to ensure we only get relevant posts (i.e., posts not yet deleted).

class User
  has_many :posts, -> { not_deleted }, inverse_of :user
end

class Post
  belongs_to :user, inverse_of: :posts
  
  scope :not_deleted, -> { where(deleted: false) }
end

Now, the following exercises the "bug".

user = User.create(...)
user.posts.create(deleted: false)
user.posts.create(deleted: true)

# This seems correct
user.posts # => [Post]

# This does not
user.posts.to_a # => [Post, Post]

I think I've tracked it down to ActiveRecord::Associations::CollectionAssociation#merge_target_lists. merge_target_lists take a persisted collection and a memory collection and consolidate them. The problem (as I see it) is that we have persisted records in the memory collection that aren't in the persisted collection, but we're still adding them together blindly. Since the persisted collection should be an up-to-date collection of the persisted records, any in-memory records that are persisted should not be accounted for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment