Skip to content

Instantly share code, notes, and snippets.

@naw
Created March 3, 2015 00:47
Show Gist options
  • Save naw/fa55816dae7805355efd to your computer and use it in GitHub Desktop.
Save naw/fa55816dae7805355efd to your computer and use it in GitHub Desktop.
ThroughAssociation using same table twice (STI type and default_scope condition) problem
unless File.exist?('Gemfile')
File.write('Gemfile', <<-GEMFILE)
source 'https://rubygems.org'
gem 'rails', github: 'rails/rails'
gem 'arel', github: 'rails/arel'
gem 'sqlite3'
GEMFILE
system 'bundle'
end
require 'bundler'
Bundler.setup(:default)
require 'active_record'
require 'minitest/autorun'
require 'logger'
# Ensure backward compatibility with Minitest 4
Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
# 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 :people, force: true do |t|
t.string :type
t.boolean :active, default: true
t.integer :parent_id
end
create_table :toys, force: true do |t|
t.integer :child_id
end
end
class Person < ActiveRecord::Base
end
class Parent < Person
end
class Child < Person
default_scope { where(active: true) }
belongs_to :parent
end
class Toy < ActiveRecord::Base
belongs_to :child
has_one :parent, through: :child
end
class BugTest < Minitest::Test
def test_has_one_through_sti_1
# should get parent, but doesn't (in Rails 4.2) because STI type child is incorrectly
# applied to `people` table instead of `children_parent_join` table in query
# Fails in Rails 4.2
# Passes in Rails master, but probably only due to a side effect of something else
parent = Parent.create!
child = Child.create!(parent: parent)
toy = Toy.create!(child: child)
assert_equal toy.parent, parent
end
def test_has_one_through_sti_2
# should get parent, but doesn't because default_scope active
# is incorrectly applied to `people` table insetad of `children_parent_join` table in query
# Fails in Rails 4.2 and master
parent = Parent.create!(active: false)
child = Child.create!(parent: parent)
toy = Toy.create!(child: child)
assert_equal toy.parent, parent
end
def test_has_one_through_sti_3
# should not get parent because child association is nil (due to default scope active)
# but the query puts the default scope on the wrong table, so child is found even though he is inactive
# and his parent is found too.
#
# Passes in Rails 4.2 (for the wrong reasons)
# Fails in master
parent = Parent.create!
child = Child.create!(parent: parent, active: false)
toy = Toy.create!(child: child)
toy.reload
assert_nil toy.child
assert_nil toy.parent
end
end
gem 'activerecord', '4.2.0'
require 'active_record'
require 'minitest/autorun'
require 'logger'
# Ensure backward compatibility with Minitest 4
Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
# 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 :people, force: true do |t|
t.string :type
t.boolean :active, default: true
t.integer :parent_id
end
create_table :toys, force: true do |t|
t.integer :child_id
end
end
class Person < ActiveRecord::Base
end
class Parent < Person
end
class Child < Person
default_scope { where(active: true) }
belongs_to :parent
end
class Toy < ActiveRecord::Base
belongs_to :child
has_one :parent, through: :child
end
class BugTest < Minitest::Test
def test_has_one_through_sti_1
# should get parent, but doesn't (in Rails 4.2) because STI type child is incorrectly
# applied to `people` table instead of `children_parent_join` table in query
# Fails in Rails 4.2
# Passes in Rails master, but probably only due to a side effect of something else
parent = Parent.create!
child = Child.create!(parent: parent)
toy = Toy.create!(child: child)
assert_equal toy.parent, parent
end
def test_has_one_through_sti_2
# should get parent, but doesn't because default_scope active
# is incorrectly applied to `people` table insetad of `children_parent_join` table in query
# Fails in Rails 4.2 and master
parent = Parent.create!(active: false)
child = Child.create!(parent: parent)
toy = Toy.create!(child: child)
assert_equal toy.parent, parent
end
def test_has_one_through_sti_3
# should not get parent because child association is nil (due to default scope active)
# but the query puts the default scope on the wrong table, so child is found even though he is inactive
# and his parent is found too.
#
# Passes in Rails 4.2 (for the wrong reasons)
# Fails in master
parent = Parent.create!
child = Child.create!(parent: parent, active: false)
toy = Toy.create!(child: child)
toy.reload
assert_nil toy.child
assert_nil toy.parent
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment