Skip to content

Instantly share code, notes, and snippets.

@ktimothy
Last active January 14, 2019 08:18
Show Gist options
  • Save ktimothy/84740eb5f509036c8f5d575a3b0dad4a to your computer and use it in GitHub Desktop.
Save ktimothy/84740eb5f509036c8f5d575a3b0dad4a to your computer and use it in GitHub Desktop.
Route.where {
Sequel.earth_distance(:start_point, :end_point).km <= 5
}
Route.where {
Sequel.earth_distance(:start_point, { lat: 10.234123, lng: 25.234782 }).mi >= 100
}
Route.where {
Sequel.earth_distance(:start_point, [10.234123, 25.234782]).mi <= 1000 # [lng, lat]
}
# frozen-string-literal: true
#
# The pg_earth_distance extension adds support to Sequel's DSL to calculate
# earth distance between GPS points.
#
module Sequel
module Postgres
class EarthDistance < Sequel::SQL::NumericExpression
def initialize(from, to)
super(
:NOOP,
Sequel::SQL::PlaceholderLiteralString.new(
['(', ' <@> ', ')'].freeze,
[_parse_argument(from), _parse_argument(to)]
)
)
end
def miles
self
end
def km
Sequel.*(self, 1.609344)
end
private
def _parse_argument(arg)
# TODO: maybe convert to sequel expression where possible?
if arg.is_a?(Symbol)
Sequel.lit("point (#{arg}[1], #{arg}[0])")
elsif arg.is_a?(Array)
Sequel.lit("point (#{arg[1]}, #{arg[0]})")
elsif arg.is_a?(Hash)
Sequel.lit("point (#{arg[:lng]}, #{arg[:lat]})")
else
Sequel.lit(arg)
end
end
end
end
module SQL
module Builders
def earth_distance(from, to)
Postgres::EarthDistance.new(from, to)
end
end
end
end
# frozen_string_literal: true
Sequel.migration do
up do
run 'CREATE EXTENSION IF NOT EXISTS "cube";'
run 'CREATE EXTENSION IF NOT EXISTS "earthdistance";'
end
down do
run 'DROP EXTENSION IF EXISTS "earthdistance";'
run 'DROP EXTENSION IF EXISTS "cube";'
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment