Skip to content

Commit

Permalink
Fix overly aggressive escaping on databases that are not PostgreSQL
Browse files Browse the repository at this point in the history
I am unsure if this is necessary for any other databases.

Relevant to #171
Fixes #176
Fixes spree/spree#3936
  • Loading branch information
radar committed Nov 6, 2013
1 parent 810a954 commit 6060acf
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 24 deletions.
10 changes: 6 additions & 4 deletions lib/ransack/constants.rb
Expand Up @@ -23,10 +23,12 @@ module Constants
module_function
# replace % \ to \% \\
def escape_wildcards(unescaped)
if ActiveRecord::VERSION::MAJOR == 3
unescaped.to_s.gsub(/([\\|\%|.])/, '\\\\\\1')
else
unescaped.to_s.gsub(/\\/){ "\\\\" }.gsub(/%/, "\\%")
case ActiveRecord::Base.connection.adapter_name
when "SQLite"
unescaped
else
# Necessary for PostgreSQL
unescaped.to_s.gsub(/([\\|\%|.])/, '\\\\\\1')
end
end

Expand Down
7 changes: 7 additions & 0 deletions spec/helpers/ransack_helper.rb
@@ -1,2 +1,9 @@
module RansackHelper
def quote_table_name(table)
ActiveRecord::Base.connection.quote_table_name(table)
end

def quote_column_name(column)
ActiveRecord::Base.connection.quote_column_name(column)
end
end
33 changes: 30 additions & 3 deletions spec/ransack/adapters/active_record/base_spec.rb
Expand Up @@ -20,6 +20,15 @@ module ActiveRecord
end

describe '#ransacker' do
# For infix tests
def self.sane_adapter?
case ::ActiveRecord::Base.connection.adapter_name
when "SQLite3" || "PostgreSQL"
true
else
false
end
end
# in schema.rb, class Person:
# ransacker :reversed_name, :formatter => proc {|v| v.reverse} do |parent|
# parent.table[:name]
Expand All @@ -36,18 +45,36 @@ module ActiveRecord

it 'can be accessed through associations' do
s = Person.search(:children_reversed_name_eq => 'htimS cirA')
s.result.to_sql.should match /"children_people"."name" = 'Aric Smith'/

s.result.to_sql.should match /#{quote_table_name("children_people")}.#{quote_column_name("name")} = 'Aric Smith'/
end

it 'allows an "attribute" to be an InfixOperation' do
s = Person.search(:doubled_name_eq => 'Aric SmithAric Smith')
s.result.first.should eq Person.find_by_name('Aric Smith')
end if defined?(Arel::Nodes::InfixOperation)
end if defined?(Arel::Nodes::InfixOperation) && sane_adapter?

it "doesn't break #count if using InfixOperations" do
s = Person.search(:doubled_name_eq => 'Aric SmithAric Smith')
s.result.count.should eq 1
end if defined?(Arel::Nodes::InfixOperation)
end if defined?(Arel::Nodes::InfixOperation) && sane_adapter?

it "should function correctly when using fields with dots in them" do
s = Person.search(email_cont: "example.com")
s.result.exists?.should be_true
end

it "should function correctly when using fields with % in them" do
Person.create!(name: "110%-er")
s = Person.search(name_cont: "10%")
s.result.exists?.should be_true
end

it "should function correctly when using fields with backslashes in them" do
Person.create!(name: "\\WINNER\\")
s = Person.search(name_cont: "\\WINNER\\")
s.result.exists?.should be_true
end
end

describe '#ransackable_attributes' do
Expand Down
28 changes: 11 additions & 17 deletions spec/ransack/predicate_spec.rb
Expand Up @@ -13,13 +13,7 @@ module Ransack
expect { subject.result }.to_not raise_error
end

it (
if ActiveRecord::VERSION::MAJOR == 3
"escapes '%', '.' and '\\\\' in value"
else
"escapes % and \\ in value"
end
) do
it "escapes '%', '.' and '\\\\' in value" do
subject.send(:"#{method}=", '%._\\')
subject.result.to_sql.should match(regexp)
end
Expand All @@ -44,34 +38,34 @@ module Ransack

describe 'cont' do

it_has_behavior 'wildcard escaping', :name_cont, (
if ActiveRecord::VERSION::MAJOR == 3
/"people"."name" LIKE '%\\%\\._\\\\%'/
it_has_behavior 'wildcard escaping', :name_cont,
(if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
/"people"."name" ILIKE '%\\%\\._\\\\%'/
else
/"people"."name" LIKE '%\\%._\\\\%'/
/"people"."name" LIKE '%%._\\%'/
end) do
subject { @s }
end

it 'generates a LIKE query with value surrounded by %' do
@s.name_cont = 'ric'
@s.result.to_sql.should match /"people"."name" LIKE '%ric%'/
@s.result.to_sql.should match /"people"."name" I?LIKE '%ric%'/
end
end

describe 'not_cont' do
it_has_behavior 'wildcard escaping', :name_not_cont, (
if ActiveRecord::VERSION::MAJOR == 3
/"people"."name" NOT LIKE '%\\%\\._\\\\%'/
it_has_behavior 'wildcard escaping', :name_not_cont,
(if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
/"people"."name" NOT ILIKE '%\\%\\._\\\\%'/
else
/"people"."name" NOT LIKE '%\\%._\\\\%'/
/"people"."name" NOT LIKE '%%._\\%'/
end) do
subject { @s }
end

it 'generates a NOT LIKE query with value surrounded by %' do
@s.name_not_cont = 'ric'
@s.result.to_sql.should match /"people"."name" NOT LIKE '%ric%'/
@s.result.to_sql.should match /"people"."name" NOT I?LIKE '%ric%'/
end
end

Expand Down

0 comments on commit 6060acf

Please sign in to comment.