Fix relation merger issue with `left_outer_joins`. #27860
The problem: If you want to merge a relation which contains
Here is the test script you can see current behaviour;
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 'activerecord', '5.0.1' 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 :preferences, force: true do |t| t.string :author_id t.boolean :is_public end create_table :authors, force: true do |t| t.string :name end create_table :posts, force: true do |t| t.string :title t.string :body t.integer :author_id end end class Preference < ActiveRecord::Base scope :some_scope, -> do where(id: nil).or(where(is_public: true)) end end class Author < ActiveRecord::Base has_one :preference has_many :posts scope :some_scope, -> do left_joins(:preference) .merge(Preference.some_scope) end end class Post < ActiveRecord::Base belongs_to :author has_many :comments scope :some_scope, -> do joins(:author).merge(Author.some_scope) end end class BugTest < Minitest::Test def test_association_stuff author = Author.create(name: 'John Doe') post = Post.create(title: 'Foo', body: 'Bar', author: author) assert_equal Post.some_scope.count, 1 end end
Without this pr, AR tries to join Preference model with Post model and raises exception because there is no relation declared between Preference and Post directly.
Using merge to share logic between scopes are the best way to keep models clean so this is why I think this should work as expected. Btw I think this is not a regression since