diff --git a/lib/ransack/adapters/active_record/ransack/constants.rb b/lib/ransack/adapters/active_record/ransack/constants.rb index 7ff87c1cd..6531ac596 100644 --- a/lib/ransack/adapters/active_record/ransack/constants.rb +++ b/lib/ransack/adapters/active_record/ransack/constants.rb @@ -104,7 +104,7 @@ def escape_wildcards(unescaped) case ActiveRecord::Base.connection.adapter_name when "Mysql2".freeze, "PostgreSQL".freeze # Necessary for PostgreSQL and MySQL - unescaped.to_s.gsub(/([\\|\%|.])/, '\\\\\\1') + unescaped.to_s.gsub(/([\\|\%|_|.])/, '\\\\\\1') else unescaped end diff --git a/spec/ransack/adapters/active_record/base_spec.rb b/spec/ransack/adapters/active_record/base_spec.rb index 3bc85e6af..957a66fc9 100644 --- a/spec/ransack/adapters/active_record/base_spec.rb +++ b/spec/ransack/adapters/active_record/base_spec.rb @@ -190,6 +190,30 @@ def self.sane_adapter? expect(s.result.to_a).to eq [p] end + context 'searching by underscores' do + # when escaping is supported right in LIKE expression without adding extra expressions + def self.simple_escaping? + case ::ActiveRecord::Base.connection.adapter_name + when "Mysql2", "PostgreSQL" + true + else + false + end + end + + it "should search correctly if matches exist" do + p = Person.create!(:name => "name_with_underscore") + s = Person.ransack(:name_cont => "name_") + expect(s.result.to_a).to eq [p] + end if simple_escaping? + + it "should return empty result if no matches" do + Person.create!(:name => "name_with_underscore") + s = Person.ransack(:name_cont => "n_") + expect(s.result.to_a).to eq [] + end if simple_escaping? + end + context "searching on an `in` predicate with a ransacker" do it "should function correctly when passing an array of ids" do s = Person.ransack(array_users_in: true) diff --git a/spec/ransack/predicate_spec.rb b/spec/ransack/predicate_spec.rb index f3b893bb6..3bc10bb33 100644 --- a/spec/ransack/predicate_spec.rb +++ b/spec/ransack/predicate_spec.rb @@ -16,7 +16,7 @@ module Ransack expect { subject.result }.to_not raise_error end - it "escapes '%', '.' and '\\\\' in value" do + it "escapes '%', '.', '_' and '\\\\' in value" do subject.send(:"#{method}=", '%._\\') expect(subject.result.to_sql).to match(regexp) end @@ -124,9 +124,9 @@ module Ransack describe 'cont' do it_has_behavior 'wildcard escaping', :name_cont, (if ActiveRecord::Base.connection.adapter_name == "PostgreSQL" - /"people"."name" ILIKE '%\\%\\._\\\\%'/ + /"people"."name" ILIKE '%\\%\\.\\_\\\\%'/ elsif ActiveRecord::Base.connection.adapter_name == "Mysql2" - /`people`.`name` LIKE '%\\\\%\\\\._\\\\\\\\%'/ + /`people`.`name` LIKE '%\\\\%\\\\.\\\\_\\\\\\\\%'/ else /"people"."name" LIKE '%%._\\%'/ end) do @@ -143,9 +143,9 @@ module Ransack describe 'not_cont' do it_has_behavior 'wildcard escaping', :name_not_cont, (if ActiveRecord::Base.connection.adapter_name == "PostgreSQL" - /"people"."name" NOT ILIKE '%\\%\\._\\\\%'/ + /"people"."name" NOT ILIKE '%\\%\\.\\_\\\\%'/ elsif ActiveRecord::Base.connection.adapter_name == "Mysql2" - /`people`.`name` NOT LIKE '%\\\\%\\\\._\\\\\\\\%'/ + /`people`.`name` NOT LIKE '%\\\\%\\\\.\\\\_\\\\\\\\%'/ else /"people"."name" NOT LIKE '%%._\\%'/ end) do