Skip to content

Instantly share code, notes, and snippets.

@anoldguy
Last active December 21, 2015 15:08
Show Gist options
  • Save anoldguy/3315c080b6a66691fdcc to your computer and use it in GitHub Desktop.
Save anoldguy/3315c080b6a66691fdcc to your computer and use it in GitHub Desktop.

Given the ruby code in the script, I would expect user.groups to be scoped by both of the deleted_at conditions. This was the behavior up thru Rails f55c60f. This was changed in bc6ac8 to fix a regression. This issue persists thru master.

Rails f55c60f

SELECT "groups".* 
FROM "groups" 
INNER JOIN "assignments" 
ON "groups"."id" = "assignments"."assignable_id" 
WHERE "assignments"."deleted_at" IS NULL -- This is the missing clause
AND "assignments"."user_id" = 1 
AND "groups"."deleted_at" IS NULL 
AND "assignments"."assignable_type" = 'Group'

Rails bc6ac8

SELECT "groups".* 
FROM "groups" 
INNER JOIN "assignments" 
ON "groups"."id" = "assignments"."assignable_id" 
WHERE "assignments"."user_id" = 1 
AND "groups"."deleted_at" IS NULL 
AND "assignments"."assignable_type" = 'Group'

Rails HEAD

SELECT "groups".* 
FROM "groups" 
INNER JOIN "assignments" 
ON "groups"."id" = "assignments"."assignable_id" 
WHERE "assignments"."user_id" = 1 
AND "groups"."deleted_at" IS NULL 
AND "assignments"."assignable_type" = 'Group'
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'
  # Activate the gem you are reporting the issue against.
  gem 'activerecord', '5.0.0.beta1'
  gem 'sqlite3'
end

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 :users, force: true do |t|
    t.string :name

    t.timestamps
  end

  create_table :groups, force: true do |t|
    t.datetime :deleted_at
    t.string :name
  end

  create_table :assignments, force: true do |t|
    t.references :user
    t.references :assignable, polymorphic: true
    t.datetime :deleted_at
  end
end

class Group < ActiveRecord::Base
  has_many :assignments, -> { where deleted_at: nil }, :as => :assignable
  has_many :leaders, :through => :assignments, :source => :user
end

class Assignment < ActiveRecord::Base
  belongs_to :user
  belongs_to :assignable, polymorphic: true
end

class User < ActiveRecord::Base
  has_many :assignments, -> { where :deleted_at => nil }, :dependent => :destroy
  has_many :groups, -> { where :deleted_at => nil }, :through => :assignments, :source => :assignable, source_type: "Group"
end

class BugTest < Minitest::Test
  def test_association_stuff
    alice = User.create!(name: "Alice")
    bob = User.create!(name: "Bob")
    admins = Group.create!(name: "Admins")
    assignment1 = Assignment.create!(user: alice, assignable: admins, deleted_at: Time.now)
    assignment2 = Assignment.create!(user: bob, assignable: admins)

    assert admins.leaders.count == 1, "Admins should have only one leader"
    assert bob.groups.count == 1, "Bob should have one assignment"
    assert alice.groups.empty?, "Alice should have no assignments!"
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment