GeoRSS aggregator and Layar augmented reality server
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 

75 lignes
1.8 KiB

  1. class Post < ActiveRecord::Base
  2. belongs_to :feed
  3. validates :title, :presence => true
  4. validates :lat, :numericality => { :greater_than_or_equal_to => -90, :less_than_or_equal_to => 90 }
  5. validates :lon, :numericality => { :greater_than_or_equal_to => -180, :less_than_or_equal_to => 180 }
  6. EARTH_RADIUS_METRES = 6378000
  7. def self.near(lat, lon, radius_metres, layer_id)
  8. # Santize inputs. Is this necessary?
  9. lat = lat.to_f
  10. lon = lon.to_f
  11. radius_metres = radius_metres.to_i
  12. layer_id = layer_id.to_i
  13. # Calculate distance using the Haversine formula
  14. self.find_by_sql(<<-ENDQUERY
  15. SELECT
  16. p.id,
  17. p.title,
  18. p.summary,
  19. p.url,
  20. p.lat,
  21. p.lon,
  22. p.published,
  23. p.feed_id,
  24. f.title as feed_title,
  25. ( #{EARTH_RADIUS_METRES}
  26. * acos( cos( radians('#{lat}') )
  27. * cos( radians( p.lat ) )
  28. * cos( radians( p.lon )
  29. - radians('#{lon}') )
  30. + sin( radians('#{lat}') )
  31. * sin( radians( p.lat ) ) ) )
  32. As distance
  33. FROM posts p
  34. INNER JOIN feeds f
  35. ON p.feed_id = f.id
  36. WHERE
  37. p.id IN
  38. ( -- Subquery returns a list of post_ids for posts on this layer
  39. SELECT p.id
  40. FROM subscriptions s
  41. INNER JOIN feeds f
  42. ON s.feed_id = f.id
  43. INNER JOIN posts p
  44. ON p.feed_id = f.id
  45. WHERE s.layer_id = #{layer_id}
  46. )
  47. AND
  48. (
  49. #{EARTH_RADIUS_METRES}
  50. * acos( cos( radians('#{lat}') )
  51. * cos( radians( p.lat ) )
  52. * cos( radians( p.lon )
  53. - radians('#{lon}') )
  54. + sin( radians('#{lat}') )
  55. * sin( radians( p.lat ) ) )
  56. )
  57. <= #{radius_metres}
  58. ORDER BY distance
  59. ENDQUERY
  60. )
  61. end
  62. end