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