Skip to content

Instantly share code, notes, and snippets.

@Midnighter
Created August 29, 2016 23:12
Show Gist options
  • Save Midnighter/8ddfad43ea22515f8a4bf3d480d6d58e to your computer and use it in GitHub Desktop.
Save Midnighter/8ddfad43ea22515f8a4bf3d480d6d58e to your computer and use it in GitHub Desktop.
Show unscope behavior on subqueries
begin
require "bundler/inline"
rescue LoadError => e
$stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
raise e
end
gemfile(true) do
source "https://rubygems.org"
gem "rails", github: "rails/rails"
gem "sqlite3"
end
require "active_record"
require "minitest/autorun"
require "logger"
# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :posts, force: true do |t|
t.integer :num_comments
end
create_table :posts_relations, force: true do |t|
t.integer :subject_id
t.integer :object_id
end
create_table :comments, force: true do |t|
t.integer :post_id
end
add_foreign_key :comments, :posts
add_foreign_key :posts_relations, :posts, column: :subject_id
add_foreign_key :posts_relations, :posts, column: :object_id
end
class Post < ActiveRecord::Base
has_and_belongs_to_many :children, join_table: 'posts_relations', class_name: 'Post', association_foreign_key: :object_id, foreign_key: :subject_id
end
class Comment < ActiveRecord::Base
belongs_to :post
end
(2..4).each do |i|
post = Post.create!(num_comments: i)
i.times do
Comment.create!(post: post)
end
end
posts = Post.order(:id).all
posts[0].children = posts[1..-1]
posts[0].save
class BugTest < Minitest::Test
def test_sanity
assert_equal 3, Post.count
assert_equal 9, Comment.count
Post.find_each do |p|
assert_equal p.num_comments, Comment.where(post: p).count
end
end
def test_direct_unscope
p1 = Post.first
p2 = Post.last
refute_equal p1, p2
query = Comment.where(post: p1).unscope(where: :post_id).where(post: p2)
assert_equal p2.num_comments, query.count
end
def test_subquery_unscope
posts = Post.order(:id).all
p2 = posts[0].children.where(id: 2)
p3 = posts[0].children.where(id: 3)
refute_equal p2, p3
query = Comment.where(post: p2).unscope(where: :post_id).where(post: p3)
assert_equal p3.first.num_comments, query.count
end
def test_avoid_subquery_unscope
posts = Post.order(:id).all
p2 = posts[0].children.where(id: 2)
p3 = posts[0].children.where(id: 3)
refute_equal p2, p3
query = Comment.where(post: p2.first).unscope(where: :post_id).where(post: p3)
assert_equal p3.first.num_comments, query.count
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment