Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions lib/ransack/nodes/condition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,13 @@ def attributes
def attributes=(args)
case args
when Array
args.each do |name|
build_attribute(name)
args.each do |attr|
if attr.is_a?(Hash) && (attr.key?(:name) || attr.key?("name"))
attr = attr.with_indifferent_access
build_attribute(attr[:name], attr[:ransacker_args])
else
build_attribute(attr)
end
end
when Hash
args.each do |index, attrs|
Expand All @@ -104,8 +109,10 @@ def values=(args)
case args
when Array
args.each do |val|
val = Value.new(@context, val)
self.values << val
if val.is_a?(Hash) && (val.key?(:value) || val.key?("value"))
val = val.with_indifferent_access[:value]
end
self.values << Value.new(@context, val)
end
when Hash
args.each do |index, attrs|
Expand Down
32 changes: 32 additions & 0 deletions spec/ransack/search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,38 @@ module Ransack
.to eq [Nodes::Condition, Nodes::Condition]
end

# Regression test for https://github.com/activerecord-hackery/ransack/issues/1150
# The low-level `c:` API previously only worked when `a:` and `v:` were given
# in their Hash form (`{"0" => {name: ...}}`). When supplied as Arrays of
# attribute / value envelopes (`[{name: ...}]`, `[{value: ...}]`) the parser
# silently dropped the attribute or treated the entire envelope hash as the
# value.
context 'low-level c: API with Array of envelope hashes' do
it 'extracts :name from each attribute hash inside an Array' do
s = Search.new(Person,
c: [{ a: [{ name: 'name' }], p: 'cont', v: [{ value: 'Ernie' }] }]
)
field = "#{quote_table_name('people')}.#{quote_column_name('name')}"
expect(s.result.to_sql).to match(/#{field} I?LIKE '%Ernie%'/)
end

it 'extracts :value from each value hash inside an Array' do
s = Search.new(Person,
c: [{ a: { '0' => { name: 'name' } }, p: 'cont', v: [{ value: 'Ernie' }] }]
)
field = "#{quote_table_name('people')}.#{quote_column_name('name')}"
expect(s.result.to_sql).to match(/#{field} I?LIKE '%Ernie%'/)
end

it 'still accepts plain Array of names/values (canonical form)' do
s = Search.new(Person,
c: [{ a: ['name'], p: 'cont', v: ['Ernie'] }]
)
field = "#{quote_table_name('people')}.#{quote_column_name('name')}"
expect(s.result.to_sql).to match(/#{field} I?LIKE '%Ernie%'/)
end
end

it 'creates conditions for custom predicates that take arrays' do
Ransack.configure do |config|
config.add_predicate 'ary_pred', wants_array: true
Expand Down
Loading