Skip to content

Instantly share code, notes, and snippets.

@JoshDoody
Created March 13, 2014 15:50
Show Gist options
  • Save JoshDoody/9531033 to your computer and use it in GitHub Desktop.
Save JoshDoody/9531033 to your computer and use it in GitHub Desktop.
Failing tests for Rails 4 unscoped when used with eager loading (includes). Two assertions should fail: Line 88 and Line 110. Line 88 should pass in Rails 3, but won't in Rails 4. Line 110 leverages the 'unscoped association' added in Rails 4, but still fails.
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'
# 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 :checklists do |t|
t.integer :tenant_id
end
create_table :submissions do |t|
t.integer :checklist_id
t.integer :tenant_id
end
create_table :tenants do |t|
end
end
class Checklist < ActiveRecord::Base
default_scope { where(tenant_id: Tenant.current_id) }
has_many :submissions
belongs_to :tenant
end
class Submission < ActiveRecord::Base
default_scope { where(tenant_id: Tenant.current_id) }
belongs_to :checklist
###### This unscoped association is my workaround in Rails 4
###### You'll want comment out if testing in Rails 3
belongs_to :unscoped_checklist, -> { unscope(where: :tenant_id) }, foreign_key: :checklist_id, class_name: "Checklist"
belongs_to :tenant
end
class Tenant < ActiveRecord::Base
cattr_accessor :current_id
has_many :checklists
has_many :submissions
end
class BugTest < Minitest::Test
def test_association_stuff
tenant = Tenant.create!
checklist = Checklist.create!(tenant_id: tenant.id)
submission = Submission.create!(tenant_id: tenant.id, checklist_id: checklist.id)
s = nil
c = nil
Tenant.current_id = tenant.id
assert_equal 1, Submission.count
assert_equal 1, Checklist.count
assert_equal 1, Checklist.first.submissions.count
assert_equal checklist.id, Submission.first.checklist.id
Tenant.current_id = nil
assert_equal 0, Checklist.count
assert_equal 0, Submission.count
assert_equal 1, Checklist.unscoped.count
assert_equal 1, Submission.unscoped.count
####### Should find submission and preload its checklist
Submission.unscoped { Checklist.unscoped { s = Submission.includes(:checklist).find(submission.id) }}
assert_equal submission.id, s.id
####### I believe this will pass in Rails 3.2.17, but fail in Rails 4 (undefined method 'id' for nil object)
assert_equal checklist.id, s.checklist.id
####### Everything below this line is Rails 4 specific
####### (relates to unscoped_checklist association on Submission class)
s = Submission.unscoped.find(submission.id)
assert_equal submission.id, s.id
####### This works...
assert_equal checklist.id, s.unscoped_checklist.id
####### This works (using an unscoped block explicitly)
s = Submission.unscoped.find(submission.id)
assert_equal submission.id, s.id
Checklist.unscoped do
c = s.checklist
end
assert_equal checklist.id, c.id
s = Submission.unscoped.includes(:unscoped_checklist).find(submission.id)
assert_equal submission.id, s.id
###### This doesn't... The 'unscoped' call actually defeats the preloaded unscoped association
###### The default_scope for the Checklist class is applied even though it's specifically
###### overriden in this assocation.
###### Also fails with 'preload'
assert_equal checklist.id, s.unscoped_checklist.id
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment