diff --git a/lib/ransack/adapters/active_record/context.rb b/lib/ransack/adapters/active_record/context.rb index 8acf8962..3b2c55a2 100644 --- a/lib/ransack/adapters/active_record/context.rb +++ b/lib/ransack/adapters/active_record/context.rb @@ -143,6 +143,7 @@ def remove_association(association) stashed.eql?(association) } @object.joins_values.delete_if { |jd| + jd.instance_variables.include?(:@join_root) && jd.instance_variable_get(:@join_root).children.map(&:object_id) == [association.object_id] } end diff --git a/spec/ransack/adapters/active_record/base_spec.rb b/spec/ransack/adapters/active_record/base_spec.rb index b17bceb4..44ecc270 100644 --- a/spec/ransack/adapters/active_record/base_spec.rb +++ b/spec/ransack/adapters/active_record/base_spec.rb @@ -77,6 +77,16 @@ module ActiveRecord expect(s.result.to_sql).to (include 'active = 1') end + it 'applies scopes that define string SQL joins' do + allow(Article) + .to receive(:ransackable_scopes) + .and_return([:latest_comment_cont]) + + # Including a negative condition to test removing the scope + s = Search.new(Article, notes_note_not_eq: 'Test', latest_comment_cont: 'Test') + expect(s.result.to_sql).to include 'latest_comment' + end + context "with sanitize_custom_scope_booleans set to false" do before(:all) do Ransack.configure { |c| c.sanitize_custom_scope_booleans = false } diff --git a/spec/support/schema.rb b/spec/support/schema.rb index f818d8c7..72626138 100644 --- a/spec/support/schema.rb +++ b/spec/support/schema.rb @@ -138,6 +138,22 @@ class Article < ActiveRecord::Base alias_attribute :content, :body default_scope { where("'default_scope' = 'default_scope'") } + scope :latest_comment_cont, lambda { |msg| + join = <<-SQL + (LEFT OUTER JOIN ( + SELECT + comments.*, + row_number() OVER (PARTITION BY comments.article_id ORDER BY comments.id DESC) AS rownum + FROM comments + ) AS latest_comment + ON latest_comment.article_id = article.id + AND latest_comment.rownum = 1 + ) + SQL + .squish + + joins(join).where("latest_comment.body ILIKE ?", "%#{msg}%") + } ransacker :title_type, formatter: lambda { |tuples| title, type = JSON.parse(tuples)