Created
March 18, 2020 22:51
-
-
Save bbonamin/47200c27a72aaf98ff8f66e290fe249f to your computer and use it in GitHub Desktop.
Rails EXISTS() subquery
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# https://github.com/rails/rails/pull/29619#issuecomment-392583498 | |
# Better approach than http://codesnik.github.io/rails/2015/09/03/activerecord-and-exists-subqueries.html | |
require 'bundler/inline' | |
gemfile(true) do | |
source 'https://rubygems.org' | |
gem 'rails', '5.2' | |
gem 'pg' | |
gem 'pry' | |
end | |
require 'active_record' | |
require 'minitest/autorun' | |
require 'logger' | |
ActiveRecord::Base.establish_connection(adapter: 'postgresql', database: 'test_exists') | |
ActiveRecord::Base.logger = Logger.new(STDOUT) | |
ActiveRecord::Schema.define do | |
create_table :posts, force: true do |t| | |
end | |
create_table :comments, force: true do |t| | |
t.references :post | |
t.string :text | |
end | |
end | |
class Post < ActiveRecord::Base | |
has_many :comments | |
end | |
class Comment < ActiveRecord::Base | |
belongs_to :post | |
end | |
class PostCommentsExistsInnerTest < ActiveSupport::TestCase | |
def setup | |
@post = Post.create! | |
@comment = @post.comments.create!(text: 'Foo') | |
@post_b = Post.create! | |
@query = Post.where(Comment.where('post_id = posts.id').where(text: 'Foo').arel.exists) | |
end | |
def test_post_is_included | |
assert_includes @query, @post | |
end | |
def test_post_b_is_not_included | |
refute_includes @query, @post_b | |
end | |
end | |
class PostCommentsExistsInterpolatedTest < ActiveSupport::TestCase | |
def setup | |
@post = Post.create! | |
@comment = @post.comments.create!(text: 'Foo') | |
@post_b = Post.create! | |
exists = Comment.where('comments.post_id = posts.id').where(text: 'Foo') | |
@query = Post.where("EXISTS (#{exists.to_sql})") | |
end | |
def test_post_is_included | |
assert_includes @query, @post | |
end | |
def test_post_b_is_not_included | |
refute_includes @query, @post_b | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment