Skip to content

Commit

Permalink
Make PredicateVisitor create Or nodes the hard way. Fixes activerecor…
Browse files Browse the repository at this point in the history
  • Loading branch information
Ernie Miller committed Sep 7, 2011
1 parent c1708d8 commit 550fe6b
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 41 deletions.
1 change: 1 addition & 0 deletions lib/squeel/nodes/literal.rb
Expand Up @@ -7,6 +7,7 @@ module Nodes
# Literal nodes are a container for raw SQL.
class Literal
include PredicateMethods
include PredicateOperators
include Operators
include Aliasing

Expand Down
2 changes: 1 addition & 1 deletion lib/squeel/visitors/predicate_visitor.rb
Expand Up @@ -220,7 +220,7 @@ def visit_Squeel_Nodes_And(o, parent)
# @param parent The parent object in the context
# @return [Arel::Nodes::Or] An ARel Or node, with left and right sides visited
def visit_Squeel_Nodes_Or(o, parent)
visit(o.left, parent).or(visit(o.right, parent))
Arel::Nodes::Grouping.new(Arel::Nodes::Or.new(visit(o.left, parent), (visit(o.right, parent))))
end

def visit_Squeel_Nodes_Not(o, parent)
Expand Down
86 changes: 46 additions & 40 deletions spec/squeel/nodes/literal_spec.rb
Expand Up @@ -3,33 +3,39 @@
module Squeel
module Nodes
describe Literal do
before do
@l = Literal.new 'string'
end
subject { Literal.new 'string'}

it { should respond_to :& }
it { should respond_to :| }
it { should respond_to :-@ }

specify { (subject & subject).should be_a And }
specify { (subject | subject).should be_a Or }
specify { (-subject).should be_a Not }

it 'hashes like its expr' do
@l.hash.should eq 'string'.hash
subject.hash.should eq 'string'.hash
end

it 'returns nil when sent to_sym' do
@l.to_sym.should be_nil
subject.to_sym.should be_nil
end

it 'returns a string matching its expr when sent to_s' do
@l.to_s.should eq 'string'
subject.to_s.should eq 'string'
end

Squeel::Constants::PREDICATES.each do |method_name|
it "creates #{method_name} predicates with no value" do
predicate = @l.send(method_name)
predicate.expr.should eq @l
predicate = subject.send(method_name)
predicate.expr.should eq subject
predicate.method_name.should eq method_name
predicate.value?.should be_false
end

it "creates #{method_name} predicates with a value" do
predicate = @l.send(method_name, 'value')
predicate.expr.should eq @l
predicate = subject.send(method_name, 'value')
predicate.expr.should eq subject
predicate.method_name.should eq method_name
predicate.value.should eq 'value'
end
Expand All @@ -39,15 +45,15 @@ module Nodes
aliases.each do |aliaz|
['', '_any', '_all'].each do |suffix|
it "creates #{method_name.to_s + suffix} predicates with no value using the alias #{aliaz.to_s + suffix}" do
predicate = @l.send(aliaz.to_s + suffix)
predicate.expr.should eq @l
predicate = subject.send(aliaz.to_s + suffix)
predicate.expr.should eq subject
predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
predicate.value?.should be_false
end

it "creates #{method_name.to_s + suffix} predicates with a value using the alias #{aliaz.to_s + suffix}" do
predicate = @l.send((aliaz.to_s + suffix), 'value')
predicate.expr.should eq @l
predicate = subject.send((aliaz.to_s + suffix), 'value')
predicate.expr.should eq subject
predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
predicate.value.should eq 'value'
end
Expand All @@ -56,96 +62,96 @@ module Nodes
end

it 'creates eq predicates with ==' do
predicate = @l == 1
predicate.expr.should eq @l
predicate = subject == 1
predicate.expr.should eq subject
predicate.method_name.should eq :eq
predicate.value.should eq 1
end

it 'creates not_eq predicates with ^' do
predicate = @l ^ 1
predicate.expr.should eq @l
predicate = subject ^ 1
predicate.expr.should eq subject
predicate.method_name.should eq :not_eq
predicate.value.should eq 1
end

it 'creates not_eq predicates with !=' do
predicate = @l != 1
predicate.expr.should eq @l
predicate = subject != 1
predicate.expr.should eq subject
predicate.method_name.should eq :not_eq
predicate.value.should eq 1
end if respond_to?('!=')

it 'creates in predicates with >>' do
predicate = @l >> [1,2,3]
predicate.expr.should eq @l
predicate = subject >> [1,2,3]
predicate.expr.should eq subject
predicate.method_name.should eq :in
predicate.value.should eq [1,2,3]
end

it 'creates not_in predicates with <<' do
predicate = @l << [1,2,3]
predicate.expr.should eq @l
predicate = subject << [1,2,3]
predicate.expr.should eq subject
predicate.method_name.should eq :not_in
predicate.value.should eq [1,2,3]
end

it 'creates matches predicates with =~' do
predicate = @l =~ '%bob%'
predicate.expr.should eq @l
predicate = subject =~ '%bob%'
predicate.expr.should eq subject
predicate.method_name.should eq :matches
predicate.value.should eq '%bob%'
end

it 'creates does_not_match predicates with !~' do
predicate = @l !~ '%bob%'
predicate.expr.should eq @l
predicate = subject !~ '%bob%'
predicate.expr.should eq subject
predicate.method_name.should eq :does_not_match
predicate.value.should eq '%bob%'
end if respond_to?('!~')

it 'creates gt predicates with >' do
predicate = @l > 1
predicate.expr.should eq @l
predicate = subject > 1
predicate.expr.should eq subject
predicate.method_name.should eq :gt
predicate.value.should eq 1
end

it 'creates gteq predicates with >=' do
predicate = @l >= 1
predicate.expr.should eq @l
predicate = subject >= 1
predicate.expr.should eq subject
predicate.method_name.should eq :gteq
predicate.value.should eq 1
end

it 'creates lt predicates with <' do
predicate = @l < 1
predicate.expr.should eq @l
predicate = subject < 1
predicate.expr.should eq subject
predicate.method_name.should eq :lt
predicate.value.should eq 1
end

it 'creates lteq predicates with <=' do
predicate = @l <= 1
predicate.expr.should eq @l
predicate = subject <= 1
predicate.expr.should eq subject
predicate.method_name.should eq :lteq
predicate.value.should eq 1
end

it 'creates ascending orders' do
order = @l.asc
order = subject.asc
order.should be_ascending
end

it 'creates descending orders' do
order = @l.desc
order = subject.desc
order.should be_descending
end

it 'creates as nodes with #as' do
as = @l.as('other_name')
as = subject.as('other_name')
as.should be_a Squeel::Nodes::As
as.left.should eq @l
as.left.should eq subject
as.right.should be_a Arel::Nodes::SqlLiteral
as.right.should eq 'other_name'
end
Expand Down
6 changes: 6 additions & 0 deletions spec/squeel/visitors/predicate_visitor_spec.rb
Expand Up @@ -55,6 +55,12 @@ module Visitors
predicate.should eq '1=1'
end

it 'creates OR nodes against a Literal' do
predicate = @v.accept(dsl{`blah` | `blah`})
predicate.should be_a Arel::Nodes::Grouping
predicate.to_sql.should eq '(blah OR blah)'
end

it 'generates IS NULL for hash keys with a value of [nil]' do
predicate = @v.accept(:id => [nil])
predicate.to_sql.should be_like '"people"."id" IS NULL'
Expand Down

0 comments on commit 550fe6b

Please sign in to comment.