Skip to content

Commit

Permalink
Adds array overlap arel operator
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan McClain committed Sep 10, 2012
1 parent cfe6c0a commit 73e119e
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 1 deletion.
5 changes: 5 additions & 0 deletions lib/postgres_ext/arel/nodes/contained_within.rb
Expand Up @@ -10,5 +10,10 @@ class ArrayAnyEq < Arel::Nodes::Binary
alias :operand1 :left
alias :operand2 :right
end

class ArrayOverlap < Arel::Nodes::Binary
alias :operand1 :left
alias :operand2 :right
end
end
end
4 changes: 4 additions & 0 deletions lib/postgres_ext/arel/predications.rb
Expand Up @@ -9,5 +9,9 @@ def contained_within(other)
def array_any_eq(other)
Nodes::ArrayAnyEq.new self, other
end

def array_overlap(other)
Nodes::ArrayOverlap.new self, other
end
end
end
17 changes: 17 additions & 0 deletions lib/postgres_ext/arel/visitors/to_sql.rb
Expand Up @@ -11,9 +11,26 @@ def visit_Arel_Nodes_ArrayAnyEq o
"#{visit o.right} = ANY(#{visit o.left})"
end

def visit_Arel_Nodes_ArrayOverlap o
if Array === o.right
right = "{#{o.right.map{|v| change_string(visit(v))}.join(',')}}"
"#{visit o.left} && '#{right}'"
else
"#{visit o.left} && #{visit o.right}"
end
end

def visit_IPAddr value
"'#{value.to_s}/#{value.instance_variable_get(:@mask_addr).to_s(2).count('1')}'"
end

def change_string value
if value.match /"|,|{/
value.gsub(/"/, "\"").gsub(/'/,'"')
else
value.gsub(/'/,'')
end
end
end
end
end
21 changes: 20 additions & 1 deletion spec/arel/array_spec.rb
Expand Up @@ -18,7 +18,7 @@ class ArelArray < ActiveRecord::Base
Object.send(:remove_const, :ArelArray)
end

describe 'Array Any' do
describe 'Array Any Equal' do
it 'converts Arel array_any_eq statement' do
arel_table = ArelArray.arel_table

Expand All @@ -33,4 +33,23 @@ class ArelArray < ActiveRecord::Base
ArelArray.where(arel_table[:tags].array_any_eq('one')).should include(one)
end
end

describe 'Array Overlap' do
it 'converts Arel array_overlap statment' do
arel_table = ArelArray.arel_table

arel_table.where(arel_table[:tags].array_overlap(['tag','tag 2'])).to_sql.should match /&& '\{tag,tag 2\}'/
end

it 'returns matched records' do
one = ArelArray.create!(:tags => ['one'])
two = ArelArray.create!(:tags => ['two'])
arel_table = ArelArray.arel_table

ArelArray.where(arel_table[:tags].array_overlap(['one'])).should include(one)
ArelArray.where(arel_table[:tags].array_overlap(['two'])).should include(two)
ArelArray.where(arel_table[:tags].array_overlap(['two','one'])).should include(two)
ArelArray.where(arel_table[:tags].array_overlap(['two','one'])).should include(one)
end
end
end

0 comments on commit 73e119e

Please sign in to comment.