Skip to content

Instantly share code, notes, and snippets.

@OrelSokolov
Created August 12, 2015 17:40
Show Gist options
  • Select an option

  • Save OrelSokolov/311575750577fddb2f4b to your computer and use it in GitHub Desktop.

Select an option

Save OrelSokolov/311575750577fddb2f4b to your computer and use it in GitHub Desktop.
test
require_relative 'helpers/handle_errors'
require 'ostruct'
require 'phone'
class ParsedStore < OpenStruct
include HandleErrorsHelper
def initialize(*args)
super(*args)
end
def validate_country! countries
self if countries.include? self.country
end
def filter_by_keywords keywords_list
klass = self.keywords.class
if klass == Array
self if keywords_list.any?{ |keyword| self.keywords.any? { |k| k =~ %r{#{keyword}}i } }
elsif klass == String
self if keywords_list.any?{ |keyword| self.keywords =~ %r{#{keyword}}i }
end
end
def apply_opening_times(store, item)
unless item.opening_times.empty?
item.opening_times.each do |t|
time = t.merge(store: store)
similar = OpeningTime.all(time)
if similar.empty?
opening_time = OpeningTime.new(time)
else
opening_time = similar.first
end
if opening_time.valid?
store.opening_times << opening_time
else
errors = opening_time.errors.map{|e| e.to_s}.join(', ')
ScroogeLogger.message :error, "Ignoring opening_time, because #{errors}"
end
end
store.save
store.opening_times.each do |op|
if !(op.closed || op.full_day)
ScroogeLogger.message :trace, "#{op.day}: #{op.from.hour}:#{op.from.min} - #{op.to.hour}:#{op.to.min}"
elsif op.closed
ScroogeLogger.message :trace, "#{op.day}: Closed"
else
ScroogeLogger.message :trace, "#{op.day}: 24 hrs"
end
end
end
end
def formatted_phone
begin
gb_country_code = '44'
Phoner::Phone.parse(Phoner::Phone.normalize(self.phone), country_code: gb_country_code).format(:europe)
rescue Exception
self.phone
end
end
def save(company, logger)
store = Store.new
store.status = :open
store.name = self.name
store.keyword_list = self.keywords
store.phone = formatted_phone
store.geohash = self.geohash
store.latitude = self.latitude
store.longitude = self.longitude
store.address = self.address
store.street = self.try :street
store.locality = self.try :locality
store.region = self.try :region
store.department = self.try :department
store.country = self.try :country
store.house_number = self.try :number
store.code = self.try :code
store.company = company
if store.valid?
logger.message :success, "Saving record to Database (#{self.company.to_s}, #{self.address.to_s})"
store.save
apply_opening_times(store, self)
else
errors = store.errors.map{|e| e.to_s}.join(', ')
logger.message :warning, "Ignoring store, because #{errors}"
end
end
# @fn def geocode input # {{{
# @brief Geocode input data set
def geocode geocoder, logger
handle_errors puts: 'Geocoding exception', and_return: [] do
address = self.address.to_s
logger.message :trace, "Geocoding (#{address}))"
info = geocoder.get_info address
unless info.nil?
def get info, type, key = 'long_name'
info.address_components.select{|comps| comps['types'].include?(type) }.first.try(:[], key)
end
self.geohash = Geohash36.to_geohash(latitude: info.latitude, longitude: info.longitude)
self.latitude = info.latitude
self.longitude = info.longitude
self.street = get(info, 'route')
self.house_number = get(info, 'street_number')
self.code = get(info, 'postal_code')
self.country = get(info, 'country', 'short_name')
self.locality = get(info, 'locality')
self.region = get(info, 'administrative_area_level_2')
self.department = get(info, 'administrative_area_level_1')
end
logger.message :debug, "Geocoding result (#{address})) (#{self.geohash})"
self
end # of handle_errors
end # }}}
end
require 'colorize'
require 'geohash36'
require_relative 'helpers/handle_errors'
class Stores < Array
include HandleErrorsHelper
def filter_by_general_info
end
def filter_by_brand brand
handle_errors and_return: self do
if brand.nil?
self
else
Stores.new self.select{ |s| s.name.downcase == brand.downcase }
end
end
end
def filter_by_state state
handle_errors and_return: self do
if state.nil?
self
else
raise ArgumentError, "Invalid state: #{state.inspect}" unless Store::STATUSES.include? state
Stores.new self.select{ |s| s.status == state }
end
end
end
# Search type can be :address, :coordinates, :auto
def filter_by_coordinates search_type, parameters, options
handle_errors and_return: self do
if parameters.try(:geohash_radius)
geohash = get_geohash_from_params search_type, parameters, options
geohash_regex = get_geohash_regex geohash, parameters
Stores.new self.select { |s| s.geohash =~ geohash_regex }
else
self
end
end
end
private
# Return geohash mask for search in DB
def get_geohash_regex geohash, parameters
radius = parameters.try(:geohash_radius).to_i
raise ArgumentError, 'Bad radius value' unless (0...10).include? radius
/^#{geohash.slice(0, 10-radius)}/
end
def get_geohash_from_params search_type, parameters, options, verbose = true
case search_type
when :address
# Use pure address
geohash = get_geohash_from_address(parameters, options, verbose)
when :coordinates
# Fetch geohash from location struct
geohash = get_geohash_from_location_struct(parameters)
when :auto
# try to use geohash.
# If not present, use address. If not present, raise exception
if location_present?(parameters)
geohash = get_geohash_from_location_struct(parameters)
else
geohash = get_geohash_from_address(parameters, options, verbose)
end
else
raise ArgumentError, "Unknown search type passed: #{search_type.inspect}"
end
end
def get_geohash_from_address parameters, options, verbose = true
geocode = get_geocoder_instance(options.pretend)
address_fields = [:house_number, :street, :locality, :region, :department, :code]
address = address_fields.map{|f| parameters.try(:address).try(f)}.compact.join(', ')
raise ArgumentError, 'Address seems to be empty' if address.empty?
country_val = parameters.try(:address).try :country # Fetch integer value of country
country_short = Scrooge::Country::VALUE_MAP[country_val]
country = Scrooge::Country_List[country_short]
address = address+" #{country}"
coords = geocode.get_coordinates(address)
if verbose
puts country_val
puts country_short
puts "ADDR: #{address}"
puts "COORDS: #{coords.inspect}".yellow
end
geohash = Geohash36.to_geohash(coords.symbolize_keys)
end
# Try to use location struct to fetch geohash or raise error
def get_geohash_from_location_struct(parameters)
if parameters.try(:location).try(:geohash).nil?
lat = parameters.try(:location).try(:latitude)
lon = parameters.try(:location).try(:longitude)
unless lat && lon
raise ArgumentError, "Bad location passed to get geohash: lat: #{lat.inspect}, long: #{lon.inspect}"
end
geohash = Geohash36.to_geohash(latitude: lat, longitude: lon)
else
geohash = parameters.location.geohash
end
geohash
end
def location_present? parameters
geohash = parameters.try(:location).try(:geohash)
lat = parameters.try(:location).try(:latitude)
lon = parameters.try(:location).try(:longitude)
(lat && lon) || geohash
end
def get_geocoder_instance(pretend)
if pretend
Geocode.new( logger: ScroogeLogger, lookup: :test, dev: @options.try(:development), options: @options)
else
Geocode.new( logger: ScroogeLogger, lookup: :google, dev: @options.try(:development), options: @options )
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment