Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lat_lng search (now with tests) #171

Merged
merged 1 commit into from
Jun 12, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions app/api/ohana.rb
Original file line number Diff line number Diff line change
Expand Up @@ -507,13 +507,14 @@ class API < Grape::API
`Peninsula Volunteers`, the search above will only return
locations that belong to `Peninsula Family Service`.

### location, radius
Queries that include the `location` parameter filter the results to
only include locations that are 5 miles (by default) from the
`location`.
### location, lat_lng, radius
Queries that include the `location` or `lat_lng` parameter filter the
results to only include locations that are 5 miles (by default)
from the `location` or `lat_lng`.
To search within a radius smaller or greater than 5 miles, use the
`radius` parameter. `radius` must be a Float between 0.1 and 50.
`location` can be an address (full or partial), or a 5-digit ZIP code.
`lat_lng` must be a comma-delimited lat,long pair of floats.
Results are sorted by distance.

Examples:
Expand All @@ -522,6 +523,8 @@ class API < Grape::API

`#{ENV['API_BASE_URL']}search?location=san mateo&radius=10`

`#{ENV['API_BASE_URL']}search?lat_lng=37.7756578,-122.4138115&radius=5`

`#{ENV['API_BASE_URL']}search?keyword=emergency&location=94403`

### language
Expand Down Expand Up @@ -584,6 +587,7 @@ class API < Grape::API
params do
optional :keyword, type: String
optional :location, type: String, desc: 'An address or 5-digit ZIP code'
optional :lat_lng, type: String, desc: 'A set of geo coordinates in the form lat,lng'
optional :radius, type: Float, desc: 'Distance in miles from the location parameter'
optional :language, type: String, desc: 'Languages other than English spoken at the location'
optional :category, type: String, desc: 'The service category based on the OpenEligibility taxonomy'
Expand Down
21 changes: 15 additions & 6 deletions app/models/location.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,20 @@ def needs_geocoding?
scope :has_keyword, ->(k) { keyword_search(k) if k.present? }
scope :has_category, ->(c) { joins(services: :categories).where(categories: { name: c }) if c.present? }

scope :is_near, (lambda do |l, r|
result = Geocoder.search(l, bounds: Settings.bounds) if l.present?
coords = result.first.coordinates if result.present?

near(coords, current_radius(r)) if l.present?
scope :is_near, (lambda do |loc, lat_lng, r|
if loc.present?
result = Geocoder.search(loc, bounds: Settings.bounds)
coords = result.first.coordinates if result.present?
near(coords, current_radius(r))
elsif lat_lng.present?
begin
coords = lat_lng.split(",").map{ |f| Float(f) }
rescue ArgumentError
error_msg = 'lat_lng must be a comma-delimited lat,long pair of floats'
error!(error_msg, 400)
end
near(coords, current_radius(r))
end
end)

scope :belongs_to_org, (lambda do |org|
Expand Down Expand Up @@ -220,7 +229,7 @@ def self.text_search(params = {})
belongs_to_org(params[:org_name]).
has_email(params[:email]).
has_domain(params[:domain]).
is_near(params[:location], params[:radius]).
is_near(params[:location], params[:lat_lng], params[:radius]).
has_keyword(params[:keyword])
end

Expand Down
39 changes: 39 additions & 0 deletions spec/api/search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,36 @@
end
end

context 'with invalid lat_lng parameter' do
before :each do
create(:location)
get 'api/search?lat_lng=37.6856578-122.4138119'
end

it 'returns a 400 status code' do
expect(response.status).to eq 400
end

it 'includes an error description' do
expect(json['error']).to eq 'lat_lng must be a comma-delimited lat,long pair of floats'
end
end

context 'with invalid (non-numeric) lat_lng parameter' do
before :each do
create(:location)
get 'api/search?lat_lng=Apple,Pear'
end

it 'returns a 400 status code' do
expect(response.status).to eq 400
end

it 'includes an error description' do
expect(json['error']).to eq 'lat_lng must be a comma-delimited lat,long pair of floats'
end
end

context 'when keyword only matches one location' do
it 'only returns 1 result' do
create(:location)
Expand All @@ -129,6 +159,15 @@
end
end

context 'lat_lng search' do
it 'returns one result' do
create(:location)
create(:farmers_market_loc)
get 'api/search?lat_lng=37.583939,-122.3715745'
expect(json.length).to eq 1
end
end

context 'with language parameter' do
it 'finds organizations that match the language' do
create(:location)
Expand Down