Skip to content

Instantly share code, notes, and snippets.

@dskecse
Created February 12, 2015 14:57
Show Gist options
  • Save dskecse/07fed1bec56d8c68a9a2 to your computer and use it in GitHub Desktop.
Save dskecse/07fed1bec56d8c68a9a2 to your computer and use it in GitHub Desktop.
diff --git a/config/initializers/postgres_ext.rb b/config/initializers/postgres_ext.rb
new file mode 100644
index 0000000..8b49f77
--- /dev/null
+++ b/config/initializers/postgres_ext.rb
@@ -0,0 +1 @@
+require './lib/postgres_ext/postgres_ext'
diff --git a/lib/postgres_ext/postgres_ext.rb b/lib/postgres_ext/postgres_ext.rb
new file mode 100644
index 0000000..c4957a6
--- /dev/null
+++ b/lib/postgres_ext/postgres_ext.rb
@@ -0,0 +1,7 @@
+require_relative 'postgres_ext/active_record'
+require_relative 'postgres_ext/arel'
diff --git a/lib/postgres_ext/postgres_ext/active_record.rb b/lib/postgres_ext/postgres_ext/active_record.rb
new file mode 100644
index 0000000..5d0c2f2
--- /dev/null
+++ b/lib/postgres_ext/postgres_ext/active_record.rb
@@ -0,0 +1,7 @@
+require 'active_record'
+require_relative 'active_record/relation'
diff --git a/lib/postgres_ext/postgres_ext/active_record/relation.rb b/lib/postgres_ext/postgres_ext/active_record/relation.rb
new file mode 100644
index 0000000..3bef1d5
--- /dev/null
+++ b/lib/postgres_ext/postgres_ext/active_record/relation.rb
@@ -0,0 +1,6 @@
+require_relative 'relation/query_methods'
diff --git a/lib/postgres_ext/postgres_ext/active_record/relation/query_methods.rb b/lib/postgres_ext/postgres_ext/active_record/relation/query_methods.rb
new file mode 100644
index 0000000..818f943
--- /dev/null
+++ b/lib/postgres_ext/postgres_ext/active_record/relation/query_methods.rb
@@ -0,0 +1,32 @@
+module ActiveRecord
+ module QueryMethods
+ class WhereChain
+ def overlap(opts, *rest)
+ substitute_comparisons(opts, rest, Arel::Nodes::Overlap, 'overlap')
+ end
+
+ private
+
+ def build_where_chain(opts, rest, &block)
+ where_value = @scope.send(:build_where, opts, rest).map(&block)
+ @scope.where_values += where_value
+ @scope
+ end
+
+ def substitute_comparisons(opts, rest, arel_node_class, method)
+ build_where_chain(opts, rest) do |rel|
+ case rel
+ when Arel::Nodes::In, Arel::Nodes::Equality
+ arel_node_class.new(rel.left, rel.right)
+ else
+ raise ArgumentError, "Invalid argument for .where.#{method}(), got #{rel.class}"
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/postgres_ext/postgres_ext/arel.rb b/lib/postgres_ext/postgres_ext/arel.rb
new file mode 100644
index 0000000..1e57b3e
--- /dev/null
+++ b/lib/postgres_ext/postgres_ext/arel.rb
@@ -0,0 +1,8 @@
+require_relative 'arel/nodes'
+require_relative 'arel/predications'
+require_relative 'arel/visitors'
diff --git a/lib/postgres_ext/postgres_ext/arel/nodes.rb b/lib/postgres_ext/postgres_ext/arel/nodes.rb
new file mode 100644
index 0000000..afd3540
--- /dev/null
+++ b/lib/postgres_ext/postgres_ext/arel/nodes.rb
@@ -0,0 +1,6 @@
+require_relative 'nodes/array_nodes'
diff --git a/lib/postgres_ext/postgres_ext/arel/nodes/array_nodes.rb b/lib/postgres_ext/postgres_ext/arel/nodes/array_nodes.rb
new file mode 100644
index 0000000..70cf563
--- /dev/null
+++ b/lib/postgres_ext/postgres_ext/arel/nodes/array_nodes.rb
@@ -0,0 +1,14 @@
+require 'arel/nodes/binary'
+
+module Arel
+ module Nodes
+ class Overlap < Arel::Nodes::Binary
+ def operator; '&&' end
+ end
+ end
+end
diff --git a/lib/postgres_ext/postgres_ext/arel/predications.rb b/lib/postgres_ext/postgres_ext/arel/predications.rb
new file mode 100644
index 0000000..c93df32
--- /dev/null
+++ b/lib/postgres_ext/postgres_ext/arel/predications.rb
@@ -0,0 +1,14 @@
+require 'arel/predications'
+
+module Arel
+ module Predications
+ def overlap(other)
+ Nodes::Overlap.new self, other
+ end
+ end
+end
diff --git a/lib/postgres_ext/postgres_ext/arel/visitors.rb b/lib/postgres_ext/postgres_ext/arel/visitors.rb
new file mode 100644
index 0000000..6ec0e79
--- /dev/null
+++ b/lib/postgres_ext/postgres_ext/arel/visitors.rb
@@ -0,0 +1,6 @@
+require_relative 'visitors/postgresql'
diff --git a/lib/postgres_ext/postgres_ext/arel/visitors/postgresql.rb b/lib/postgres_ext/postgres_ext/arel/visitors/postgresql.rb
new file mode 100644
index 0000000..a39de8e
--- /dev/null
+++ b/lib/postgres_ext/postgres_ext/arel/visitors/postgresql.rb
@@ -0,0 +1,27 @@
+require 'arel/visitors/postgresql'
+
+module Arel
+ module Visitors
+ class PostgreSQL
+ private
+
+ def visit_Array o, a
+ column = a.relation.engine.connection.schema_cache.columns(a.relation.name).find { |col| col.name == a.name.to_s } if a
+ if column && column.respond_to?(:array) && column.array
+ quoted o, a
+ else
+ o.empty? ? 'NULL' : o.map { |x| visit x }.join(', ')
+ end
+ end
+
+ def visit_Arel_Nodes_Overlap o, a = nil
+ "#{visit o.left, a} && #{visit o.right, o.left}"
+ end
+ end
+ end
+end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment