Skip to content

Commit

Permalink
Check type before sending #value message to predicate
Browse files Browse the repository at this point in the history
The previous implementation was giving for granted that every predicate
respond  to `#value`, but that doesn't seem to be the case at least when
having a `Arel::SelectManager`.

by simply inverting the terms of the existing AND check we can fix the issue
without introducing unknown side effects.

In order to test the change, a new ransacker has been added to the Person model.
  • Loading branch information
spaghetticode committed Jan 8, 2024
1 parent cc624b9 commit e7c8250
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/ransack/nodes/condition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ def in_predicate?(predicate)
end

def casted_array?(predicate)
predicate.value.is_a?(Array) && predicate.is_a?(Arel::Nodes::Casted)
predicate.is_a?(Arel::Nodes::Casted) && predicate.value.is_a?(Array)
end

def format_values_for(predicate)
Expand Down
9 changes: 9 additions & 0 deletions spec/ransack/adapters/active_record/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,15 @@ def self.simple_escaping?
expect(s.result.map(&:id)).to eq [3, 2, 1]
end

it 'should function correctly with HABTM associations' do
article = Article.first
tag = article.tags.first
s = Person.ransack(article_tags_in: [tag.id])

expect(s.result.count).to be 1
expect(s.result.map(&:id)).to eq [article.person.id]
end

it 'should function correctly when passing an array of strings' do
a, b = Person.select(:id).order(:id).limit(2).map { |a| a.id.to_s }

Expand Down
11 changes: 11 additions & 0 deletions spec/support/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,17 @@ class Person < ApplicationRecord
Arel.sql(query)
end

ransacker :article_tags, formatter: proc { |id|
if Tag.exists?(id)
joins(articles: :tags)
.where(tags: { id: id })
.distinct
.select(:id).arel
end
} do |parent|
parent.table[:id]
end

def self.ransackable_attributes(auth_object = nil)
if auth_object == :admin
authorizable_ransackable_attributes - ['only_sort']
Expand Down

0 comments on commit e7c8250

Please sign in to comment.