master
1class Gym < ApplicationRecord
2 validates_presence_of :name
3 has_one :location, as: :locatable, dependent: :destroy
4 accepts_nested_attributes_for :location
5 acts_as_mappable through: :location
6 delegate :full_address, to: :location, allow_nil: true
7
8 scope :closest_to, ->(location, distance: 100) do
9 if location.present? && location.coordinates.present?
10 joins(:location).
11 within(distance, units: :kms, origin: location.coordinates)
12 else
13 all
14 end
15 end
16
17 scope :search, ->(query) do
18 sql = [
19 "UPPER(gyms.name) LIKE :query",
20 "OR UPPER(locations.city) LIKE :query",
21 "OR UPPER(locations.region) LIKE :query",
22 "OR UPPER(locations.country) LIKE :query"
23 ].join(" ")
24 joins(:location).where(sql, { query: "%#{query.upcase}%" })
25 end
26
27 scope :search_with, ->(params) do
28 if params[:q].present?
29 if "yelp" == params[:source]
30 search_yelp(
31 q: params[:q],
32 categories: params[:categories],
33 city: params[:city],
34 page: (params[:page] || 1).to_i,
35 per_page: (params[:per_page] || 20).to_i
36 )
37 else
38 includes(:location).search(params[:q]).order(:name)
39 end
40 else
41 includes(:location).order(:name)
42 end
43 end
44
45 def self.search_yelp(q: "gym", categories: ["gyms"], city: , page: 1, per_page: 20)
46 Search.yelp.for(q, city, categories, page, per_page) do |result|
47 Gym.map_from(result)
48 end
49 end
50
51 def self.map_from(result)
52 Gym.new(
53 name: result.name,
54 yelp_id: result.id,
55 location_attributes: {
56 address: result.location.address.first,
57 city: result.location.city,
58 postal_code: result.location.postal_code,
59 region: result.location.state_code,
60 country: result.location.country_code,
61 latitude: result.location.coordinate.try(:latitude),
62 longitude: result.location.coordinate.try(:longitude),
63 }
64 )
65 end
66
67 def self.create_from_yelp!(id)
68 Gym.find_by(yelp_id: id) || Gym.map_from(Search.yelp.for_business(id))
69 end
70
71 def self.import(city, pages: 5)
72 return if city.blank?
73 return [] if Rails.env.test?
74 (1..pages).each do |page|
75 Gym.search_yelp(q: "gym", city: city, page: page).each(&:save!)
76 end
77 end
78
79 def map_url
80 params = [location.latitude, location.longitude, "12z"].join(",")
81 "https://maps.google.com/maps/place/#{name}/@#{params}"
82 end
83
84 def duplicate?(distance: 0.1)
85 return true if yelp_id.present? && Gym.where.not(id: id).exists?(yelp_id: yelp_id)
86 Gym.
87 closest_to(location, distance: distance).
88 where.not(id: id).
89 limit(1).
90 any?
91 end
92end