ultra-fast-mod 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/geocoder-1.8.6/CHANGELOG.md +669 -0
  3. data/geocoder-1.8.6/LICENSE +20 -0
  4. data/geocoder-1.8.6/README.md +827 -0
  5. data/geocoder-1.8.6/bin/console +13 -0
  6. data/geocoder-1.8.6/bin/geocode +5 -0
  7. data/geocoder-1.8.6/examples/app_defined_lookup_services.rb +22 -0
  8. data/geocoder-1.8.6/examples/cache_bypass.rb +48 -0
  9. data/geocoder-1.8.6/examples/reverse_geocode_job.rb +40 -0
  10. data/geocoder-1.8.6/lib/easting_northing.rb +171 -0
  11. data/geocoder-1.8.6/lib/generators/geocoder/config/config_generator.rb +14 -0
  12. data/geocoder-1.8.6/lib/generators/geocoder/config/templates/initializer.rb +27 -0
  13. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/geolite_city_generator.rb +30 -0
  14. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/geolite_country_generator.rb +30 -0
  15. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
  16. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
  17. data/geocoder-1.8.6/lib/generators/geocoder/migration_version.rb +15 -0
  18. data/geocoder-1.8.6/lib/geocoder/cache.rb +77 -0
  19. data/geocoder-1.8.6/lib/geocoder/cache_stores/base.rb +40 -0
  20. data/geocoder-1.8.6/lib/geocoder/cache_stores/generic.rb +35 -0
  21. data/geocoder-1.8.6/lib/geocoder/cache_stores/redis.rb +34 -0
  22. data/geocoder-1.8.6/lib/geocoder/calculations.rb +420 -0
  23. data/geocoder-1.8.6/lib/geocoder/cli.rb +121 -0
  24. data/geocoder-1.8.6/lib/geocoder/configuration.rb +151 -0
  25. data/geocoder-1.8.6/lib/geocoder/configuration_hash.rb +11 -0
  26. data/geocoder-1.8.6/lib/geocoder/esri_token.rb +38 -0
  27. data/geocoder-1.8.6/lib/geocoder/exceptions.rb +40 -0
  28. data/geocoder-1.8.6/lib/geocoder/ip_address.rb +36 -0
  29. data/geocoder-1.8.6/lib/geocoder/kernel_logger.rb +25 -0
  30. data/geocoder-1.8.6/lib/geocoder/logger.rb +47 -0
  31. data/geocoder-1.8.6/lib/geocoder/lookup.rb +155 -0
  32. data/geocoder-1.8.6/lib/geocoder/lookups/abstract_api.rb +46 -0
  33. data/geocoder-1.8.6/lib/geocoder/lookups/amap.rb +63 -0
  34. data/geocoder-1.8.6/lib/geocoder/lookups/amazon_location_service.rb +58 -0
  35. data/geocoder-1.8.6/lib/geocoder/lookups/azure.rb +56 -0
  36. data/geocoder-1.8.6/lib/geocoder/lookups/baidu.rb +63 -0
  37. data/geocoder-1.8.6/lib/geocoder/lookups/baidu_ip.rb +30 -0
  38. data/geocoder-1.8.6/lib/geocoder/lookups/ban_data_gouv_fr.rb +143 -0
  39. data/geocoder-1.8.6/lib/geocoder/lookups/base.rb +351 -0
  40. data/geocoder-1.8.6/lib/geocoder/lookups/bing.rb +82 -0
  41. data/geocoder-1.8.6/lib/geocoder/lookups/db_ip_com.rb +52 -0
  42. data/geocoder-1.8.6/lib/geocoder/lookups/esri.rb +114 -0
  43. data/geocoder-1.8.6/lib/geocoder/lookups/freegeoip.rb +62 -0
  44. data/geocoder-1.8.6/lib/geocoder/lookups/geoapify.rb +78 -0
  45. data/geocoder-1.8.6/lib/geocoder/lookups/geocoder_ca.rb +53 -0
  46. data/geocoder-1.8.6/lib/geocoder/lookups/geocodio.rb +42 -0
  47. data/geocoder-1.8.6/lib/geocoder/lookups/geoip2.rb +49 -0
  48. data/geocoder-1.8.6/lib/geocoder/lookups/geoportail_lu.rb +65 -0
  49. data/geocoder-1.8.6/lib/geocoder/lookups/google.rb +100 -0
  50. data/geocoder-1.8.6/lib/geocoder/lookups/google_places_details.rb +64 -0
  51. data/geocoder-1.8.6/lib/geocoder/lookups/google_places_search.rb +75 -0
  52. data/geocoder-1.8.6/lib/geocoder/lookups/google_premier.rb +61 -0
  53. data/geocoder-1.8.6/lib/geocoder/lookups/here.rb +73 -0
  54. data/geocoder-1.8.6/lib/geocoder/lookups/ip2location.rb +71 -0
  55. data/geocoder-1.8.6/lib/geocoder/lookups/ip2location_io.rb +62 -0
  56. data/geocoder-1.8.6/lib/geocoder/lookups/ip2location_lite.rb +40 -0
  57. data/geocoder-1.8.6/lib/geocoder/lookups/ipapi_com.rb +82 -0
  58. data/geocoder-1.8.6/lib/geocoder/lookups/ipbase.rb +49 -0
  59. data/geocoder-1.8.6/lib/geocoder/lookups/ipdata_co.rb +62 -0
  60. data/geocoder-1.8.6/lib/geocoder/lookups/ipgeolocation.rb +51 -0
  61. data/geocoder-1.8.6/lib/geocoder/lookups/ipinfo_io.rb +44 -0
  62. data/geocoder-1.8.6/lib/geocoder/lookups/ipinfo_io_lite.rb +42 -0
  63. data/geocoder-1.8.6/lib/geocoder/lookups/ipqualityscore.rb +50 -0
  64. data/geocoder-1.8.6/lib/geocoder/lookups/ipregistry.rb +68 -0
  65. data/geocoder-1.8.6/lib/geocoder/lookups/ipstack.rb +63 -0
  66. data/geocoder-1.8.6/lib/geocoder/lookups/latlon.rb +58 -0
  67. data/geocoder-1.8.6/lib/geocoder/lookups/location_iq.rb +54 -0
  68. data/geocoder-1.8.6/lib/geocoder/lookups/mapbox.rb +60 -0
  69. data/geocoder-1.8.6/lib/geocoder/lookups/mapquest.rb +58 -0
  70. data/geocoder-1.8.6/lib/geocoder/lookups/maxmind.rb +90 -0
  71. data/geocoder-1.8.6/lib/geocoder/lookups/maxmind_geoip2.rb +70 -0
  72. data/geocoder-1.8.6/lib/geocoder/lookups/maxmind_local.rb +71 -0
  73. data/geocoder-1.8.6/lib/geocoder/lookups/melissa_street.rb +41 -0
  74. data/geocoder-1.8.6/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
  75. data/geocoder-1.8.6/lib/geocoder/lookups/nominatim.rb +64 -0
  76. data/geocoder-1.8.6/lib/geocoder/lookups/opencagedata.rb +65 -0
  77. data/geocoder-1.8.6/lib/geocoder/lookups/osmnames.rb +57 -0
  78. data/geocoder-1.8.6/lib/geocoder/lookups/pc_miler.rb +87 -0
  79. data/geocoder-1.8.6/lib/geocoder/lookups/pdok_nl.rb +43 -0
  80. data/geocoder-1.8.6/lib/geocoder/lookups/pelias.rb +63 -0
  81. data/geocoder-1.8.6/lib/geocoder/lookups/photon.rb +89 -0
  82. data/geocoder-1.8.6/lib/geocoder/lookups/pickpoint.rb +41 -0
  83. data/geocoder-1.8.6/lib/geocoder/lookups/pointpin.rb +69 -0
  84. data/geocoder-1.8.6/lib/geocoder/lookups/postcode_anywhere_uk.rb +50 -0
  85. data/geocoder-1.8.6/lib/geocoder/lookups/postcodes_io.rb +31 -0
  86. data/geocoder-1.8.6/lib/geocoder/lookups/smarty_streets.rb +68 -0
  87. data/geocoder-1.8.6/lib/geocoder/lookups/telize.rb +75 -0
  88. data/geocoder-1.8.6/lib/geocoder/lookups/tencent.rb +59 -0
  89. data/geocoder-1.8.6/lib/geocoder/lookups/test.rb +49 -0
  90. data/geocoder-1.8.6/lib/geocoder/lookups/twogis.rb +58 -0
  91. data/geocoder-1.8.6/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
  92. data/geocoder-1.8.6/lib/geocoder/lookups/yandex.rb +61 -0
  93. data/geocoder-1.8.6/lib/geocoder/models/active_record.rb +51 -0
  94. data/geocoder-1.8.6/lib/geocoder/models/base.rb +39 -0
  95. data/geocoder-1.8.6/lib/geocoder/models/mongo_base.rb +62 -0
  96. data/geocoder-1.8.6/lib/geocoder/models/mongo_mapper.rb +26 -0
  97. data/geocoder-1.8.6/lib/geocoder/models/mongoid.rb +32 -0
  98. data/geocoder-1.8.6/lib/geocoder/query.rb +125 -0
  99. data/geocoder-1.8.6/lib/geocoder/railtie.rb +26 -0
  100. data/geocoder-1.8.6/lib/geocoder/request.rb +114 -0
  101. data/geocoder-1.8.6/lib/geocoder/results/abstract_api.rb +146 -0
  102. data/geocoder-1.8.6/lib/geocoder/results/amap.rb +87 -0
  103. data/geocoder-1.8.6/lib/geocoder/results/amazon_location_service.rb +62 -0
  104. data/geocoder-1.8.6/lib/geocoder/results/azure.rb +65 -0
  105. data/geocoder-1.8.6/lib/geocoder/results/baidu.rb +75 -0
  106. data/geocoder-1.8.6/lib/geocoder/results/baidu_ip.rb +62 -0
  107. data/geocoder-1.8.6/lib/geocoder/results/ban_data_gouv_fr.rb +282 -0
  108. data/geocoder-1.8.6/lib/geocoder/results/base.rb +79 -0
  109. data/geocoder-1.8.6/lib/geocoder/results/bing.rb +52 -0
  110. data/geocoder-1.8.6/lib/geocoder/results/db_ip_com.rb +58 -0
  111. data/geocoder-1.8.6/lib/geocoder/results/esri.rb +78 -0
  112. data/geocoder-1.8.6/lib/geocoder/results/freegeoip.rb +40 -0
  113. data/geocoder-1.8.6/lib/geocoder/results/geoapify.rb +179 -0
  114. data/geocoder-1.8.6/lib/geocoder/results/geocoder_ca.rb +60 -0
  115. data/geocoder-1.8.6/lib/geocoder/results/geocodio.rb +78 -0
  116. data/geocoder-1.8.6/lib/geocoder/results/geoip2.rb +76 -0
  117. data/geocoder-1.8.6/lib/geocoder/results/geoportail_lu.rb +71 -0
  118. data/geocoder-1.8.6/lib/geocoder/results/google.rb +150 -0
  119. data/geocoder-1.8.6/lib/geocoder/results/google_places_details.rb +39 -0
  120. data/geocoder-1.8.6/lib/geocoder/results/google_places_search.rb +52 -0
  121. data/geocoder-1.8.6/lib/geocoder/results/google_premier.rb +6 -0
  122. data/geocoder-1.8.6/lib/geocoder/results/here.rb +77 -0
  123. data/geocoder-1.8.6/lib/geocoder/results/ip2location.rb +22 -0
  124. data/geocoder-1.8.6/lib/geocoder/results/ip2location_io.rb +21 -0
  125. data/geocoder-1.8.6/lib/geocoder/results/ip2location_lite.rb +47 -0
  126. data/geocoder-1.8.6/lib/geocoder/results/ipapi_com.rb +45 -0
  127. data/geocoder-1.8.6/lib/geocoder/results/ipbase.rb +40 -0
  128. data/geocoder-1.8.6/lib/geocoder/results/ipdata_co.rb +40 -0
  129. data/geocoder-1.8.6/lib/geocoder/results/ipgeolocation.rb +59 -0
  130. data/geocoder-1.8.6/lib/geocoder/results/ipinfo_io.rb +48 -0
  131. data/geocoder-1.8.6/lib/geocoder/results/ipinfo_io_lite.rb +16 -0
  132. data/geocoder-1.8.6/lib/geocoder/results/ipqualityscore.rb +54 -0
  133. data/geocoder-1.8.6/lib/geocoder/results/ipregistry.rb +304 -0
  134. data/geocoder-1.8.6/lib/geocoder/results/ipstack.rb +60 -0
  135. data/geocoder-1.8.6/lib/geocoder/results/latlon.rb +71 -0
  136. data/geocoder-1.8.6/lib/geocoder/results/location_iq.rb +6 -0
  137. data/geocoder-1.8.6/lib/geocoder/results/mapbox.rb +80 -0
  138. data/geocoder-1.8.6/lib/geocoder/results/mapquest.rb +48 -0
  139. data/geocoder-1.8.6/lib/geocoder/results/maxmind.rb +130 -0
  140. data/geocoder-1.8.6/lib/geocoder/results/maxmind_geoip2.rb +9 -0
  141. data/geocoder-1.8.6/lib/geocoder/results/maxmind_local.rb +44 -0
  142. data/geocoder-1.8.6/lib/geocoder/results/melissa_street.rb +46 -0
  143. data/geocoder-1.8.6/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
  144. data/geocoder-1.8.6/lib/geocoder/results/nominatim.rb +121 -0
  145. data/geocoder-1.8.6/lib/geocoder/results/opencagedata.rb +100 -0
  146. data/geocoder-1.8.6/lib/geocoder/results/osmnames.rb +56 -0
  147. data/geocoder-1.8.6/lib/geocoder/results/pc_miler.rb +98 -0
  148. data/geocoder-1.8.6/lib/geocoder/results/pdok_nl.rb +62 -0
  149. data/geocoder-1.8.6/lib/geocoder/results/pelias.rb +58 -0
  150. data/geocoder-1.8.6/lib/geocoder/results/photon.rb +119 -0
  151. data/geocoder-1.8.6/lib/geocoder/results/pickpoint.rb +6 -0
  152. data/geocoder-1.8.6/lib/geocoder/results/pointpin.rb +40 -0
  153. data/geocoder-1.8.6/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
  154. data/geocoder-1.8.6/lib/geocoder/results/postcodes_io.rb +40 -0
  155. data/geocoder-1.8.6/lib/geocoder/results/smarty_streets.rb +142 -0
  156. data/geocoder-1.8.6/lib/geocoder/results/telize.rb +40 -0
  157. data/geocoder-1.8.6/lib/geocoder/results/tencent.rb +72 -0
  158. data/geocoder-1.8.6/lib/geocoder/results/test.rb +33 -0
  159. data/geocoder-1.8.6/lib/geocoder/results/twogis.rb +76 -0
  160. data/geocoder-1.8.6/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
  161. data/geocoder-1.8.6/lib/geocoder/results/yandex.rb +292 -0
  162. data/geocoder-1.8.6/lib/geocoder/sql.rb +110 -0
  163. data/geocoder-1.8.6/lib/geocoder/stores/active_record.rb +329 -0
  164. data/geocoder-1.8.6/lib/geocoder/stores/base.rb +115 -0
  165. data/geocoder-1.8.6/lib/geocoder/stores/mongo_base.rb +58 -0
  166. data/geocoder-1.8.6/lib/geocoder/stores/mongo_mapper.rb +13 -0
  167. data/geocoder-1.8.6/lib/geocoder/stores/mongoid.rb +13 -0
  168. data/geocoder-1.8.6/lib/geocoder/util.rb +29 -0
  169. data/geocoder-1.8.6/lib/geocoder/version.rb +3 -0
  170. data/geocoder-1.8.6/lib/geocoder.rb +48 -0
  171. data/geocoder-1.8.6/lib/maxmind_database.rb +109 -0
  172. data/geocoder-1.8.6/lib/tasks/geocoder.rake +54 -0
  173. data/geocoder-1.8.6/lib/tasks/maxmind.rake +73 -0
  174. data/ultra-fast-mod.gemspec +12 -0
  175. metadata +214 -0
@@ -0,0 +1,329 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'geocoder/sql'
3
+ require 'geocoder/stores/base'
4
+
5
+ ##
6
+ # Add geocoding functionality to any ActiveRecord object.
7
+ #
8
+ module Geocoder::Store
9
+ module ActiveRecord
10
+ include Base
11
+
12
+ ##
13
+ # Implementation of 'included' hook method.
14
+ #
15
+ def self.included(base)
16
+ base.extend ClassMethods
17
+ base.class_eval do
18
+
19
+ # scope: geocoded objects
20
+ scope :geocoded, lambda {
21
+ where("#{table_name}.#{geocoder_options[:latitude]} IS NOT NULL " +
22
+ "AND #{table_name}.#{geocoder_options[:longitude]} IS NOT NULL")
23
+ }
24
+
25
+ # scope: not-geocoded objects
26
+ scope :not_geocoded, lambda {
27
+ where("#{table_name}.#{geocoder_options[:latitude]} IS NULL " +
28
+ "OR #{table_name}.#{geocoder_options[:longitude]} IS NULL")
29
+ }
30
+
31
+ # scope: not-reverse geocoded objects
32
+ scope :not_reverse_geocoded, lambda {
33
+ where("#{table_name}.#{geocoder_options[:fetched_address]} IS NULL")
34
+ }
35
+
36
+ ##
37
+ # Find all objects within a radius of the given location.
38
+ # Location may be either a string to geocode or an array of
39
+ # coordinates (<tt>[lat,lon]</tt>). Also takes an options hash
40
+ # (see Geocoder::Store::ActiveRecord::ClassMethods.near_scope_options
41
+ # for details).
42
+ #
43
+ scope :near, lambda{ |location, *args|
44
+ latitude, longitude = Geocoder::Calculations.extract_coordinates(location)
45
+ if Geocoder::Calculations.coordinates_present?(latitude, longitude)
46
+ options = near_scope_options(latitude, longitude, *args)
47
+ select(options[:select]).where(options[:conditions]).
48
+ order(options[:order])
49
+ else
50
+ # If no lat/lon given we don't want any results, but we still
51
+ # need distance and bearing columns so you can add, for example:
52
+ # .order("distance")
53
+ select(select_clause(nil, null_value, null_value)).where(false_condition)
54
+ end
55
+ }
56
+
57
+ ##
58
+ # Find all objects within the area of a given bounding box.
59
+ # Bounds must be an array of locations specifying the southwest
60
+ # corner followed by the northeast corner of the box
61
+ # (<tt>[[sw_lat, sw_lon], [ne_lat, ne_lon]]</tt>).
62
+ #
63
+ scope :within_bounding_box, lambda{ |*bounds|
64
+ sw_lat, sw_lng, ne_lat, ne_lng = bounds.flatten if bounds
65
+ if sw_lat && sw_lng && ne_lat && ne_lng
66
+ where(Geocoder::Sql.within_bounding_box(
67
+ sw_lat, sw_lng, ne_lat, ne_lng,
68
+ full_column_name(geocoder_options[:latitude]),
69
+ full_column_name(geocoder_options[:longitude])
70
+ ))
71
+ else
72
+ select(select_clause(nil, null_value, null_value)).where(false_condition)
73
+ end
74
+ }
75
+ end
76
+ end
77
+
78
+ ##
79
+ # Methods which will be class methods of the including class.
80
+ #
81
+ module ClassMethods
82
+
83
+ def distance_from_sql(location, *args)
84
+ latitude, longitude = Geocoder::Calculations.extract_coordinates(location)
85
+ if Geocoder::Calculations.coordinates_present?(latitude, longitude)
86
+ distance_sql(latitude, longitude, *args)
87
+ end
88
+ end
89
+
90
+ ##
91
+ # Get options hash suitable for passing to ActiveRecord.find to get
92
+ # records within a radius (in kilometers) of the given point.
93
+ # Options hash may include:
94
+ #
95
+ # * +:units+ - <tt>:mi</tt> or <tt>:km</tt>; to be used.
96
+ # for interpreting radius as well as the +distance+ attribute which
97
+ # is added to each found nearby object.
98
+ # Use Geocoder.configure[:units] to configure default units.
99
+ # * +:bearing+ - <tt>:linear</tt> or <tt>:spherical</tt>.
100
+ # the method to be used for calculating the bearing (direction)
101
+ # between the given point and each found nearby point;
102
+ # set to false for no bearing calculation. Use
103
+ # Geocoder.configure[:distances] to configure default calculation method.
104
+ # * +:select+ - string with the SELECT SQL fragment (e.g. “id, name”)
105
+ # * +:select_distance+ - whether to include the distance alias in the
106
+ # SELECT SQL fragment (e.g. <formula> AS distance)
107
+ # * +:select_bearing+ - like +:select_distance+ but for bearing.
108
+ # * +:order+ - column(s) for ORDER BY SQL clause; default is distance;
109
+ # set to false or nil to omit the ORDER BY clause
110
+ # * +:exclude+ - an object to exclude (used by the +nearbys+ method)
111
+ # * +:distance_column+ - used to set the column name of the calculated distance.
112
+ # * +:bearing_column+ - used to set the column name of the calculated bearing.
113
+ # * +:min_radius+ - the value to use as the minimum radius.
114
+ # ignored if database is sqlite.
115
+ # default is 0.0
116
+ #
117
+ def near_scope_options(latitude, longitude, radius = 20, options = {})
118
+ if options[:units]
119
+ options[:units] = options[:units].to_sym
120
+ end
121
+ latitude_attribute = options[:latitude] || geocoder_options[:latitude]
122
+ longitude_attribute = options[:longitude] || geocoder_options[:longitude]
123
+ options[:units] ||= (geocoder_options[:units] || Geocoder.config.units)
124
+ select_distance = options.fetch(:select_distance) { true }
125
+ options[:order] = "" if !select_distance && !options.include?(:order)
126
+ select_bearing = options.fetch(:select_bearing) { true }
127
+ bearing = bearing_sql(latitude, longitude, options)
128
+ distance = distance_sql(latitude, longitude, options)
129
+ distance_column = options.fetch(:distance_column) { 'distance' }
130
+ bearing_column = options.fetch(:bearing_column) { 'bearing' }
131
+
132
+ # If radius is a DB column name, bounding box should include
133
+ # all rows within the maximum radius appearing in that column.
134
+ # Note: performance is dependent on variability of radii.
135
+ radius_is_column = radius.is_a?(Symbol) || (defined?(Arel::Nodes::SqlLiteral) && radius.is_a?(Arel::Nodes::SqlLiteral))
136
+ bb_radius = radius_is_column ? maximum(radius) : radius
137
+ b = Geocoder::Calculations.bounding_box([latitude, longitude], bb_radius, options)
138
+ args = b + [
139
+ full_column_name(latitude_attribute),
140
+ full_column_name(longitude_attribute)
141
+ ]
142
+ bounding_box_conditions = Geocoder::Sql.within_bounding_box(*args)
143
+
144
+ if using_unextended_sqlite?
145
+ conditions = bounding_box_conditions
146
+ else
147
+ min_radius = options.fetch(:min_radius, 0).to_f
148
+ # if radius is a DB column name,
149
+ # find rows between min_radius and value in column
150
+ if radius_is_column
151
+ c = "BETWEEN ? AND #{radius}"
152
+ a = [min_radius]
153
+ else
154
+ c = "BETWEEN ? AND ?"
155
+ a = [min_radius, radius]
156
+ end
157
+ conditions = [bounding_box_conditions + " AND (#{distance}) " + c] + a
158
+ end
159
+ {
160
+ :select => select_clause(options[:select],
161
+ select_distance ? distance : nil,
162
+ select_bearing ? bearing : nil,
163
+ distance_column,
164
+ bearing_column),
165
+ :conditions => add_exclude_condition(conditions, options[:exclude]),
166
+ :order => options.include?(:order) ? options[:order] : "#{distance_column} ASC"
167
+ }
168
+ end
169
+
170
+ ##
171
+ # SQL for calculating distance based on the current database's
172
+ # capabilities (trig functions?).
173
+ #
174
+ def distance_sql(latitude, longitude, options = {})
175
+ method_prefix = using_unextended_sqlite? ? "approx" : "full"
176
+ Geocoder::Sql.send(
177
+ method_prefix + "_distance",
178
+ latitude, longitude,
179
+ full_column_name(options[:latitude] || geocoder_options[:latitude]),
180
+ full_column_name(options[:longitude]|| geocoder_options[:longitude]),
181
+ options
182
+ )
183
+ end
184
+
185
+ ##
186
+ # SQL for calculating bearing based on the current database's
187
+ # capabilities (trig functions?).
188
+ #
189
+ def bearing_sql(latitude, longitude, options = {})
190
+ if !options.include?(:bearing)
191
+ options[:bearing] = Geocoder.config.distances
192
+ end
193
+ if options[:bearing]
194
+ method_prefix = using_unextended_sqlite? ? "approx" : "full"
195
+ Geocoder::Sql.send(
196
+ method_prefix + "_bearing",
197
+ latitude, longitude,
198
+ full_column_name(options[:latitude] || geocoder_options[:latitude]),
199
+ full_column_name(options[:longitude]|| geocoder_options[:longitude]),
200
+ options
201
+ )
202
+ end
203
+ end
204
+
205
+ ##
206
+ # Generate the SELECT clause.
207
+ #
208
+ def select_clause(columns, distance = nil, bearing = nil, distance_column = 'distance', bearing_column = 'bearing')
209
+ if columns == :id_only
210
+ return full_column_name(primary_key)
211
+ elsif columns == :geo_only
212
+ clause = ""
213
+ else
214
+ clause = (columns || full_column_name("*"))
215
+ end
216
+ if distance
217
+ clause += ", " unless clause.empty?
218
+ clause += "#{distance} AS #{distance_column}"
219
+ end
220
+ if bearing
221
+ clause += ", " unless clause.empty?
222
+ clause += "#{bearing} AS #{bearing_column}"
223
+ end
224
+ clause
225
+ end
226
+
227
+ ##
228
+ # Adds a condition to exclude a given object by ID.
229
+ # Expects conditions as an array or string. Returns array.
230
+ #
231
+ def add_exclude_condition(conditions, exclude)
232
+ conditions = [conditions] if conditions.is_a?(String)
233
+ if exclude
234
+ conditions[0] << " AND #{full_column_name(primary_key)} != ?"
235
+ conditions << exclude.id
236
+ end
237
+ conditions
238
+ end
239
+
240
+ def using_unextended_sqlite?
241
+ using_sqlite? && !using_sqlite_with_extensions?
242
+ end
243
+
244
+ def using_sqlite?
245
+ !!connection.adapter_name.match(/sqlite/i)
246
+ end
247
+
248
+ def using_sqlite_with_extensions?
249
+ connection.adapter_name.match(/sqlite/i) &&
250
+ defined?(::SqliteExt) &&
251
+ %W(MOD POWER SQRT PI SIN COS ASIN ATAN2).all?{ |fn_name|
252
+ connection.raw_connection.function_created?(fn_name)
253
+ }
254
+ end
255
+
256
+ def using_postgres?
257
+ connection.adapter_name.match(/postgres/i)
258
+ end
259
+
260
+ ##
261
+ # Use OID type when running in PosgreSQL
262
+ #
263
+ def null_value
264
+ using_postgres? ? 'NULL::text' : 'NULL'
265
+ end
266
+
267
+ ##
268
+ # Value which can be passed to where() to produce no results.
269
+ #
270
+ def false_condition
271
+ using_unextended_sqlite? ? 0 : "false"
272
+ end
273
+
274
+ ##
275
+ # Prepend table name if column name doesn't already contain one.
276
+ #
277
+ def full_column_name(column)
278
+ column = column.to_s
279
+ column.include?(".") ? column : [table_name, column].join(".")
280
+ end
281
+ end
282
+
283
+ ##
284
+ # Get nearby geocoded objects.
285
+ # Takes the same options hash as the near class method (scope).
286
+ # Returns nil if the object is not geocoded.
287
+ #
288
+ def nearbys(radius = 20, options = {})
289
+ return nil unless geocoded?
290
+ options.merge!(:exclude => self) unless send(self.class.primary_key).nil?
291
+ self.class.near(self, radius, options)
292
+ end
293
+
294
+ ##
295
+ # Look up coordinates and assign to +latitude+ and +longitude+ attributes
296
+ # (or other as specified in +geocoded_by+). Returns coordinates (array).
297
+ #
298
+ def geocode
299
+ do_lookup(false) do |o,rs|
300
+ if r = rs.first
301
+ unless r.latitude.nil? or r.longitude.nil?
302
+ o.__send__ "#{self.class.geocoder_options[:latitude]}=", r.latitude
303
+ o.__send__ "#{self.class.geocoder_options[:longitude]}=", r.longitude
304
+ end
305
+ r.coordinates
306
+ end
307
+ end
308
+ end
309
+
310
+ alias_method :fetch_coordinates, :geocode
311
+
312
+ ##
313
+ # Look up address and assign to +address+ attribute (or other as specified
314
+ # in +reverse_geocoded_by+). Returns address (string).
315
+ #
316
+ def reverse_geocode
317
+ do_lookup(true) do |o,rs|
318
+ if r = rs.first
319
+ unless r.address.nil?
320
+ o.__send__ "#{self.class.geocoder_options[:fetched_address]}=", r.address
321
+ end
322
+ r.address
323
+ end
324
+ end
325
+ end
326
+
327
+ alias_method :fetch_address, :reverse_geocode
328
+ end
329
+ end
@@ -0,0 +1,115 @@
1
+ module Geocoder
2
+ module Store
3
+ module Base
4
+
5
+ ##
6
+ # Is this object geocoded? (Does it have latitude and longitude?)
7
+ #
8
+ def geocoded?
9
+ to_coordinates.compact.size == 2
10
+ end
11
+
12
+ ##
13
+ # Coordinates [lat,lon] of the object.
14
+ #
15
+ def to_coordinates
16
+ [:latitude, :longitude].map{ |i| send self.class.geocoder_options[i] }
17
+ end
18
+
19
+ ##
20
+ # Calculate the distance from the object to an arbitrary point.
21
+ # See Geocoder::Calculations.distance_between for ways of specifying
22
+ # the point. Also takes a symbol specifying the units
23
+ # (:mi or :km; can be specified in Geocoder configuration).
24
+ #
25
+ def distance_to(point, units = nil)
26
+ units ||= self.class.geocoder_options[:units]
27
+ return nil unless geocoded?
28
+ Geocoder::Calculations.distance_between(
29
+ to_coordinates, point, :units => units)
30
+ end
31
+
32
+ alias_method :distance_from, :distance_to
33
+
34
+ ##
35
+ # Calculate the bearing from the object to another point.
36
+ # See Geocoder::Calculations.distance_between for
37
+ # ways of specifying the point.
38
+ #
39
+ def bearing_to(point, options = {})
40
+ options[:method] ||= self.class.geocoder_options[:method]
41
+ return nil unless geocoded?
42
+ Geocoder::Calculations.bearing_between(
43
+ to_coordinates, point, options)
44
+ end
45
+
46
+ ##
47
+ # Calculate the bearing from another point to the object.
48
+ # See Geocoder::Calculations.distance_between for
49
+ # ways of specifying the point.
50
+ #
51
+ def bearing_from(point, options = {})
52
+ options[:method] ||= self.class.geocoder_options[:method]
53
+ return nil unless geocoded?
54
+ Geocoder::Calculations.bearing_between(
55
+ point, to_coordinates, options)
56
+ end
57
+
58
+ ##
59
+ # Look up coordinates and assign to +latitude+ and +longitude+ attributes
60
+ # (or other as specified in +geocoded_by+). Returns coordinates (array).
61
+ #
62
+ def geocode
63
+ fail
64
+ end
65
+
66
+ ##
67
+ # Look up address and assign to +address+ attribute (or other as specified
68
+ # in +reverse_geocoded_by+). Returns address (string).
69
+ #
70
+ def reverse_geocode
71
+ fail
72
+ end
73
+
74
+ private # --------------------------------------------------------------
75
+
76
+ ##
77
+ # Look up geographic data based on object attributes (configured in
78
+ # geocoded_by or reverse_geocoded_by) and handle the results with the
79
+ # block (given to geocoded_by or reverse_geocoded_by). The block is
80
+ # given two-arguments: the object being geocoded and an array of
81
+ # Geocoder::Result objects).
82
+ #
83
+ def do_lookup(reverse = false)
84
+ options = self.class.geocoder_options
85
+ if reverse and options[:reverse_geocode]
86
+ query = to_coordinates
87
+ elsif !reverse and options[:geocode]
88
+ query = send(options[:user_address])
89
+ else
90
+ return
91
+ end
92
+
93
+ query_options = [:lookup, :ip_lookup, :language, :params].inject({}) do |hash, key|
94
+ if options.has_key?(key)
95
+ val = options[key]
96
+ hash[key] = val.respond_to?(:call) ? val.call(self) : val
97
+ end
98
+ hash
99
+ end
100
+ results = Geocoder.search(query, query_options)
101
+
102
+ # execute custom block, if specified in configuration
103
+ block_key = reverse ? :reverse_block : :geocode_block
104
+ if custom_block = options[block_key]
105
+ custom_block.call(self, results)
106
+
107
+ # else execute block passed directly to this method,
108
+ # which generally performs the "auto-assigns"
109
+ elsif block_given?
110
+ yield(self, results)
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,58 @@
1
+ module Geocoder::Store
2
+ module MongoBase
3
+
4
+ def self.included_by_model(base)
5
+ base.class_eval do
6
+
7
+ scope :geocoded, lambda {
8
+ where(geocoder_options[:coordinates].ne => nil)
9
+ }
10
+
11
+ scope :not_geocoded, lambda {
12
+ where(geocoder_options[:coordinates] => nil)
13
+ }
14
+ end
15
+ end
16
+
17
+ ##
18
+ # Coordinates [lat,lon] of the object.
19
+ # This method always returns coordinates in lat,lon order,
20
+ # even though internally they are stored in the opposite order.
21
+ #
22
+ def to_coordinates
23
+ coords = send(self.class.geocoder_options[:coordinates])
24
+ coords.is_a?(Array) ? coords.reverse : []
25
+ end
26
+
27
+ ##
28
+ # Look up coordinates and assign to +latitude+ and +longitude+ attributes
29
+ # (or other as specified in +geocoded_by+). Returns coordinates (array).
30
+ #
31
+ def geocode
32
+ do_lookup(false) do |o,rs|
33
+ if r = rs.first
34
+ unless r.coordinates.nil?
35
+ o.__send__ "#{self.class.geocoder_options[:coordinates]}=", r.coordinates.reverse
36
+ end
37
+ r.coordinates
38
+ end
39
+ end
40
+ end
41
+
42
+ ##
43
+ # Look up address and assign to +address+ attribute (or other as specified
44
+ # in +reverse_geocoded_by+). Returns address (string).
45
+ #
46
+ def reverse_geocode
47
+ do_lookup(true) do |o,rs|
48
+ if r = rs.first
49
+ unless r.address.nil?
50
+ o.__send__ "#{self.class.geocoder_options[:fetched_address]}=", r.address
51
+ end
52
+ r.address
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,13 @@
1
+ require 'geocoder/stores/base'
2
+ require 'geocoder/stores/mongo_base'
3
+
4
+ module Geocoder::Store
5
+ module MongoMapper
6
+ include Base
7
+ include MongoBase
8
+
9
+ def self.included(base)
10
+ MongoBase.included_by_model(base)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'geocoder/stores/base'
2
+ require 'geocoder/stores/mongo_base'
3
+
4
+ module Geocoder::Store
5
+ module Mongoid
6
+ include Base
7
+ include MongoBase
8
+
9
+ def self.included(base)
10
+ MongoBase.included_by_model(base)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Geocoder
4
+ module Util
5
+ #
6
+ # Recursive version of Hash#merge!
7
+ #
8
+ # Adds the contents of +h2+ to +h1+,
9
+ # merging entries in +h1+ with duplicate keys with those from +h2+.
10
+ #
11
+ # Compared with Hash#merge!, this method supports nested hashes.
12
+ # When both +h1+ and +h2+ contains an entry with the same key,
13
+ # it merges and returns the values from both hashes.
14
+ #
15
+ # h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
16
+ # h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
17
+ # recursive_hash_merge(h1, h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
18
+ #
19
+ # Simply using Hash#merge! would return
20
+ #
21
+ # h1.merge!(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
22
+ #
23
+ def self.recursive_hash_merge(h1, h2)
24
+ h1.merge!(h2) do |_key, oldval, newval|
25
+ oldval.class == h1.class ? self.recursive_hash_merge(oldval, newval) : newval
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module Geocoder
2
+ VERSION = "1.8.6"
3
+ end
@@ -0,0 +1,48 @@
1
+ require "geocoder/configuration"
2
+ require "geocoder/logger"
3
+ require "geocoder/kernel_logger"
4
+ require "geocoder/query"
5
+ require "geocoder/calculations"
6
+ require "geocoder/exceptions"
7
+ require "geocoder/cache"
8
+ require "geocoder/request"
9
+ require "geocoder/lookup"
10
+ require "geocoder/ip_address"
11
+ require "geocoder/models/active_record" if defined?(::ActiveRecord)
12
+ require "geocoder/models/mongoid" if defined?(::Mongoid)
13
+ require "geocoder/models/mongo_mapper" if defined?(::MongoMapper)
14
+
15
+ module Geocoder
16
+
17
+ ##
18
+ # Search for information about an address or a set of coordinates.
19
+ #
20
+ def self.search(query, options = {})
21
+ query = Geocoder::Query.new(query, options) unless query.is_a?(Geocoder::Query)
22
+ query.blank? ? [] : query.execute
23
+ end
24
+
25
+ ##
26
+ # Look up the coordinates of the given street or IP address.
27
+ #
28
+ def self.coordinates(address, options = {})
29
+ if (results = search(address, options)).size > 0
30
+ results.first.coordinates
31
+ end
32
+ end
33
+
34
+ ##
35
+ # Look up the address of the given coordinates ([lat,lon])
36
+ # or IP address (string).
37
+ #
38
+ def self.address(query, options = {})
39
+ if (results = search(query, options)).size > 0
40
+ results.first.address
41
+ end
42
+ end
43
+ end
44
+
45
+ # load Railtie if Rails exists
46
+ if defined?(Rails)
47
+ require "geocoder/railtie"
48
+ end