Skip to content

Commit

Permalink
Improve syntax for sifters -- can now be appended to keypaths
Browse files Browse the repository at this point in the history
  • Loading branch information
ernie committed Sep 29, 2011
1 parent 6212c65 commit dcf818d
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 2 deletions.
5 changes: 5 additions & 0 deletions lib/squeel/nodes/join.rb
Expand Up @@ -34,6 +34,11 @@ def polymorphic?
_klass
end

# Implemented for equality testing
def hash
[_name, _type, _klass].hash
end

# Compare with other objects
def eql?(other)
self.class.eql?(other.class) &&
Expand Down
16 changes: 15 additions & 1 deletion lib/squeel/nodes/key_path.rb
Expand Up @@ -109,7 +109,21 @@ def /(other)
# @param other The right hand side of the operation
# @return [Operation] An operation with the given custom operator, the KeyPath on its left and the other object on the right.
def op(operator, other)
endpoint.respond_to?(:op) ? super : no_method_error(:/)
endpoint.respond_to?(:op) ? super : no_method_error(:op)
end

# Allow KeyPath to have a sifter as its endpoint, if the endpoint is a
# chainable node (Stub or Join)
# @param [Symbol] name The name of the sifter
# @return [KeyPath] This keypath, with a sifter as its endpoint
def sift(name, *args)
if Stub === endpoint || Join === endpoint
@path << endpoint
@endpoint = Sifter.new(name, args)
self
else
no_method_error :sift
end
end

# Set the absolute flag on this KeyPath
Expand Down
13 changes: 13 additions & 0 deletions lib/squeel/nodes/sifter.rb
Expand Up @@ -9,6 +9,19 @@ def initialize(name, args)
@name, @args = name, args
end

# Implemented for equality testing
def hash
[name, args].hash
end

# Compare with other objects
def eql?(other)
self.class.eql?(other.class) &&
self.name.eql?(other.name) &&
self.args.eql?(other.args)
end
alias :== :eql?

end
end
end
6 changes: 6 additions & 0 deletions lib/squeel/nodes/stub.rb
Expand Up @@ -108,6 +108,12 @@ def inner
Join.new(self.symbol, Arel::InnerJoin)
end

# Create a keypath with a sifter as its endpoint
# @return [KeyPath] The new KeyPath
def sift(name, *args)
KeyPath.new(self, Sifter.new(name, args))
end

# Create an outer Join node for the association named by this Stub
# @return [Join] The new outer Join node
def outer
Expand Down
2 changes: 1 addition & 1 deletion lib/squeel/version.rb
@@ -1,3 +1,3 @@
module Squeel
VERSION = "0.9.1"
VERSION = "0.9.2"
end
6 changes: 6 additions & 0 deletions spec/squeel/nodes/key_path_spec.rb
Expand Up @@ -55,6 +55,12 @@ module Nodes
as.right.should eq 'other_name'
end

it 'creates sifter nodes with #sift' do
@k.sift(:blah, 1)
sifter = @k.endpoint
sifter.should be_a Sifter
end

it 'creates AND nodes with & if the endpoint responds to &' do
node = @k.third.fourth.eq('Bob') & Stub.new(:attr).eq('Joe')
node.should be_a And
Expand Down
6 changes: 6 additions & 0 deletions spec/squeel/nodes/stub_spec.rb
Expand Up @@ -39,6 +39,12 @@ module Nodes
keypath.path_with_endpoint.should eq [@s, Join.new(:another, Arel::InnerJoin, Person)]
end

it 'creates a KeyPath with a sifter endpoint when sent #sift' do
keypath = @s.sift(:blah, 1)
keypath.should be_a KeyPath
keypath.path_with_endpoint.should eq [@s, Sifter.new(:blah, [1])]
end

it 'creates an absolute keypath with just an endpoint with ~' do
node = ~@s
node.should be_a KeyPath
Expand Down
9 changes: 9 additions & 0 deletions spec/squeel/visitors/predicate_visitor_spec.rb
Expand Up @@ -272,6 +272,15 @@ module Visitors
expr.right.to_sql.should match /"children_people"."name" LIKE '%smith'/
end

it 'visits sifters in a keypath' do
predicate = @v.accept(dsl {children.sift(:name_starts_or_ends_with, 'smith')})
predicate.should be_a Arel::Nodes::Grouping
expr = predicate.expr
expr.should be_a Arel::Nodes::Or
expr.left.to_sql.should match /"children_people"."name" LIKE 'smith%'/
expr.right.to_sql.should match /"children_people"."name" LIKE '%smith'/
end

it 'honors an explicit table in string keys' do
predicate = @v.accept('things.attribute' => 'retro')
predicate.should be_a Arel::Nodes::Equality
Expand Down

0 comments on commit dcf818d

Please sign in to comment.