]> git.openstreetmap.org Git - rails.git/blobdiff - app/controllers/api_controller.rb
Upgrade to rails 3.1.0
[rails.git] / app / controllers / api_controller.rb
index ec5674e94542487074ca29d986161762b357fea8..35fc86c520576dd9b502a03463f7c136a842df48 100644 (file)
@@ -1,8 +1,8 @@
 class ApiController < ApplicationController
 
-  session :off
   before_filter :check_api_readable, :except => [:capabilities]
   after_filter :compress_output
+  around_filter :api_call_handle_error, :api_call_timeout
 
   # Help methods for checking boundary sanity and area size
   include MapBoundary
@@ -11,17 +11,14 @@ class ApiController < ApplicationController
   # within the specified bounding box, and in the specified page.
   def trackpoints
     #retrieve the page number
-    page = params['page'].to_i
-    unless page
-        page = 0;
-    end
+    page = params['page'].to_s.to_i
 
     unless page >= 0
         report_error("Page number must be greater than or equal to 0")
         return
     end
 
-    offset = page * APP_CONFIG['tracepoints_per_page']
+    offset = page * TRACEPOINTS_PER_PAGE
 
     # Figure out the bbox
     bbox = params['bbox']
@@ -42,28 +39,75 @@ class ApiController < ApplicationController
     end
 
     # get all the points
-    points = Tracepoint.find_by_area(min_lat, min_lon, max_lat, max_lon, :offset => offset, :limit => APP_CONFIG['tracepoints_per_page'], :order => "timestamp DESC" )
+    points = Tracepoint.bbox(min_lat, min_lon, max_lat, max_lon).offset(offset).limit(TRACEPOINTS_PER_PAGE).order("gpx_id DESC, trackid ASC, timestamp ASC")
 
     doc = XML::Document.new
     doc.encoding = XML::Encoding::UTF_8
     root = XML::Node.new 'gpx'
     root['version'] = '1.0'
     root['creator'] = 'OpenStreetMap.org'
-    root['xmlns'] = "http://www.topografix.com/GPX/1/0/"
+    root['xmlns'] = "http://www.topografix.com/GPX/1/0"
     
     doc.root = root
 
-    track = XML::Node.new 'trk'
-    doc.root << track
-
-    trkseg = XML::Node.new 'trkseg'
-    track << trkseg
+    # initialise these variables outside of the loop so that they
+    # stay in scope and don't get free'd up by the GC during the
+    # loop.
+    gpx_id = -1
+    trackid = -1
+    track = nil
+    trkseg = nil
+    anon_track = nil
+    anon_trkseg = nil
+    gpx_file = nil
+    timestamps = false
 
     points.each do |point|
-      trkseg << point.to_xml_node()
+      if gpx_id != point.gpx_id
+        gpx_id = point.gpx_id
+        trackid = -1
+        gpx_file = Trace.find(gpx_id)
+
+        if gpx_file.trackable?
+          track = XML::Node.new 'trk'
+          doc.root << track
+          timestamps = true
+
+          if gpx_file.identifiable?
+            track << (XML::Node.new("name") << gpx_file.name)
+            track << (XML::Node.new("desc") << gpx_file.description)
+            track << (XML::Node.new("url") << url_for(:controller => 'trace', :action => 'view', :id => gpx_file.id))
+          end
+        else
+          # use the anonymous track segment if the user hasn't allowed
+          # their GPX points to be tracked.
+          timestamps = false
+          if anon_track.nil? 
+            anon_track = XML::Node.new 'trk'
+            doc.root << anon_track
+          end
+          track = anon_track
+        end
+      end
+      
+      if trackid != point.trackid
+        if gpx_file.trackable?
+          trkseg = XML::Node.new 'trkseg'
+          track << trkseg
+          trackid = point.trackid
+        else
+          if anon_trkseg.nil? 
+            anon_trkseg = XML::Node.new 'trkseg'
+            anon_track << anon_trkseg
+          end
+          trkseg = anon_trkseg
+        end
+      end
+
+      trkseg << point.to_xml_node(timestamps)
     end
 
-    response.headers["Content-Disposition"] = "attachment; filename=\"map.osm\""
+    response.headers["Content-Disposition"] = "attachment; filename=\"tracks.gpx\""
 
     render :text => doc.to_s, :content_type => "text/xml"
   end
@@ -101,14 +145,14 @@ class ApiController < ApplicationController
     end
 
     # FIXME um why is this area using a different order for the lat/lon from above???
-    @nodes = Node.find_by_area(min_lat, min_lon, max_lat, max_lon, :conditions => {:visible => true}, :include => :node_tags, :limit => APP_CONFIG['max_number_of_nodes']+1)
+    @nodes = Node.bbox(min_lat, min_lon, max_lat, max_lon).where(:visible => true).includes(:node_tags).limit(MAX_NUMBER_OF_NODES+1)
     # get all the nodes, by tag not yet working, waiting for change from NickB
     # need to be @nodes (instance var) so tests in /spec can be performed
     #@nodes = Node.search(bbox, params[:tag])
 
     node_ids = @nodes.collect(&:id)
-    if node_ids.length > APP_CONFIG['max_number_of_nodes']
-      report_error("You requested too many nodes (limit is #{APP_CONFIG['max_number_of_nodes']}). Either request a smaller area, or use planet.osm")
+    if node_ids.length > MAX_NUMBER_OF_NODES
+      report_error("You requested too many nodes (limit is #{MAX_NUMBER_OF_NODES}). Either request a smaller area, or use planet.osm")
       return
     end
     if node_ids.length == 0
@@ -147,7 +191,7 @@ class ApiController < ApplicationController
     nodes_to_fetch = (list_of_way_nodes.uniq - node_ids) - [0]
 
     if nodes_to_fetch.length > 0
-      @nodes += Node.find(nodes_to_fetch, :include => :node_tags)
+      @nodes += Node.includes(:node_tags).find(nodes_to_fetch)
     end
 
     visible_nodes = {}
@@ -169,15 +213,15 @@ class ApiController < ApplicationController
       end
     end 
 
-    relations = Relation.find_for_nodes(visible_nodes.keys, :conditions => {:visible => true}) +
-                Relation.find_for_ways(way_ids, :conditions => {:visible => true})
+    relations = Relation.nodes(visible_nodes.keys).visible +
+                Relation.ways(way_ids).visible
 
     # we do not normally return the "other" partners referenced by an relation, 
     # e.g. if we return a way A that is referenced by relation X, and there's 
     # another way B also referenced, that is not returned. But we do make 
     # an exception for cases where an relation references another *relation*; 
     # in that case we return that as well (but we don't go recursive here)
-    relations += Relation.find_for_relations(relations.collect { |r| r.id }, :conditions => {:visible => true})
+    relations += Relation.relations(relations.collect { |r| r.id }).visible
 
     # this "uniq" may be slightly inefficient; it may be better to first collect and output
     # all node-related relations, then find the *not yet covered* way-related ones etc.
@@ -208,8 +252,7 @@ class ApiController < ApplicationController
        endtime > starttime and endtime - starttime <= 24.hours
       mask = (1 << zoom) - 1
 
-      tiles = Node.count(:conditions => ["timestamp BETWEEN ? AND ?", starttime, endtime],
-                         :group => "maptile_for_point(latitude, longitude, #{zoom})")
+      tiles = Node.where(:timestamp => starttime .. endtime).group("maptile_for_point(latitude, longitude, #{zoom})").count
 
       doc = OSM::API.new.get_xml_doc
       changes = XML::Node.new 'changes'
@@ -251,17 +294,20 @@ class ApiController < ApplicationController
     version['maximum'] = "#{API_VERSION}";
     api << version
     area = XML::Node.new 'area'
-    area['maximum'] = APP_CONFIG['max_request_area'].to_s;
+    area['maximum'] = MAX_REQUEST_AREA.to_s;
     api << area
     tracepoints = XML::Node.new 'tracepoints'
-    tracepoints['per_page'] = APP_CONFIG['tracepoints_per_page'].to_s
+    tracepoints['per_page'] = TRACEPOINTS_PER_PAGE.to_s
     api << tracepoints
     waynodes = XML::Node.new 'waynodes'
-    waynodes['maximum'] = APP_CONFIG['max_number_of_way_nodes'].to_s
+    waynodes['maximum'] = MAX_NUMBER_OF_WAY_NODES.to_s
     api << waynodes
     changesets = XML::Node.new 'changesets'
     changesets['maximum_elements'] = Changeset::MAX_ELEMENTS.to_s
     api << changesets
+    timeout = XML::Node.new 'timeout'
+    timeout['seconds'] = API_TIMEOUT.to_s
+    api << timeout
     
     doc.root << api