Skip to content

Instantly share code, notes, and snippets.

@jonatack
Last active July 30, 2016 13:43
Show Gist options
  • Save jonatack/1b64c924a81283e3ec83 to your computer and use it in GitHub Desktop.
Save jonatack/1b64c924a81283e3ec83 to your computer and use it in GitHub Desktop.
Ransack issue #628 - two associations where the second one is part of the default scope generates invalid SQL.
# two_associations_one_with_default_scope.rb
# Run it in your console with: `ruby two_associations_one_with_default_scope.rb`
# If you change the gem dependencies, run it with:
# `rm gemfile* && ruby two_associations_one_with_default_scope.rb`
unless File.exist?('Gemfile')
File.write('Gemfile', <<-GEMFILE)
source 'https://rubygems.org'
# Rails master
gem 'rails', github: 'rails/rails'
# Rails release
# gem 'rails', '5.0.0'
gem 'sqlite3'
gem 'ransack', github: 'activerecord-hackery/ransack'
gem 'polyamorous', github: 'activerecord-hackery/polyamorous'
GEMFILE
system 'bundle install'
end
require 'bundler'
Bundler.setup(:default)
require 'active_record'
require 'minitest/autorun'
require 'logger'
require 'ransack'
# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = Logger.new(STDOUT)
# Display versions.
message = "Running test case with Ruby #{RUBY_VERSION}, Active Record #{
::ActiveRecord::VERSION::STRING}, Arel #{Arel::VERSION} and #{
::ActiveRecord::Base.connection.adapter_name}"
line = '=' * message.length
puts line, message, line
ActiveRecord::Schema.define do
create_table "documents", force: true do |t|
t.string "code"
t.string "title"
end
create_table "revisions", force: true do |t|
t.integer "document_id"
t.string "code"
t.string "title"
end
create_table "file_assets", force: true do |t|
t.string "file_name"
t.integer "revision_id"
end
end
class Document < ActiveRecord::Base
has_many :revisions, inverse_of: :document
end
class FileAsset < ActiveRecord::Base
belongs_to :revision, inverse_of: :file_assets
end
class Revision < ActiveRecord::Base
belongs_to :document, inverse_of: :revisions
has_many :file_assets, inverse_of: :revision
default_scope { joins(:document) }
end
class BugTest < Minitest::Test
def setup
@query = <<-SQL
SELECT \"revisions\".* FROM \"revisions\"
INNER JOIN \"documents\"
ON \"documents\".\"id\" = \"revisions\".\"document_id\"
LEFT OUTER JOIN \"file_assets\"
ON \"file_assets\".\"revision_id\" = \"revisions\".\"id\"
WHERE ((\"file_assets\".\"file_name\" = 'AAA'
AND \"documents\".\"code\" = 'BBB'))
SQL
.squish!
end
def test_query
document = Document.create!(code: 'BBB', title: 'Second')
revision = document.revisions.create!(code: 'CCC', title: 'Third')
revision.file_assets.create!(file_name: 'AAA')
result = Revision.find_by_sql(@query)
assert_equal revision.id, result.first.id
end
def test_default_scope
# p Revision
# .joins(:document)
# .left_outer_join(:file_assets)
# .where(file_assets: { file_name: 'AAA' }, document: { code: 'BBB' })
# .to_sql
sql = Revision
.ransack({file_assets_file_name_eq: "AAA", document_code_eq: "BBB"})
.result
.to_sql
assert_equal(@query, sql)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment