source: subversion/sites/rails_port/app/models/trace.rb @ 3375

Last change on this file since 3375 was 3371, checked in by tomhughes, 13 years ago

Split the rest action into sparate read, update and delete actions thus
allowing authorization to be done on a per-action basis without worring
about the method. This should make the user API work.

Also do a lot of cleanup of the controllers.

File size: 5.1 KB
Line 
1class Trace < ActiveRecord::Base
2  set_table_name 'gpx_files'
3
4  validates_presence_of :user_id, :name, :timestamp
5  validates_presence_of :description, :on => :create
6#  validates_numericality_of :latitude, :longitude
7  validates_inclusion_of :public, :inserted, :in => [ true, false]
8 
9  belongs_to :user
10  has_many :tags, :class_name => 'Tracetag', :foreign_key => 'gpx_id', :dependent => :delete_all
11  has_many :points, :class_name => 'Tracepoint', :foreign_key => 'gpx_id', :dependent => :delete_all
12
13  def destroy
14    super
15    FileUtils.rm_f(trace_name)
16    FileUtils.rm_f(icon_picture_name)
17    FileUtils.rm_f(large_picture_name)
18  end
19
20  def tagstring
21    return tags.collect {|tt| tt.tag}.join(" ")
22  end
23
24  def tagstring=(s)
25    self.tags = s.split().collect {|tag|
26      tt = Tracetag.new
27      tt.tag = tag
28      tt
29    }
30  end
31 
32  def large_picture= (data)
33    f = File.new(large_picture_name, "wb")
34    f.syswrite(data)
35    f.close
36  end
37 
38  def icon_picture= (data)
39    f = File.new(icon_picture_name, "wb")
40    f.syswrite(data)
41    f.close
42  end
43
44  def large_picture
45    f = File.new(large_picture_name, "rb")
46    logger.info "large picture file: '#{f.path}', bytes: #{File.size(f.path)}"
47    data = f.sysread(File.size(f.path))
48    logger.info "have read data, bytes: '#{data.length}'"
49    f.close
50    data
51  end
52 
53  def icon_picture
54    f = File.new(icon_picture_name, "rb")
55    logger.info "icon picture file: '#{f.path}'"
56    data = f.sysread(File.size(f.path))
57    f.close
58    data
59  end
60 
61  # FIXME change to permanent filestore area
62  def large_picture_name
63    "/home/osm/icons/#{id}.gif"
64  end
65
66  # FIXME change to permanent filestore area
67  def icon_picture_name
68    "/home/osm/icons/#{id}_icon.gif"
69  end
70
71  def trace_name
72    "/home/osm/gpx/#{id}.gpx"
73  end
74
75  def mime_type
76    return `file -bi #{trace_name}`.chomp
77  end
78
79  def to_xml
80    doc = OSM::API.new.get_xml_doc
81    doc.root << to_xml_node()
82    return doc
83  end
84
85  def to_xml_node
86    el1 = XML::Node.new 'gpx_file'
87    el1['id'] = self.id.to_s
88    el1['name'] = self.name.to_s
89    el1['lat'] = self.latitude.to_s
90    el1['lon'] = self.longitude.to_s
91    el1['user'] = self.user.display_name
92    el1['public'] = self.public.to_s
93    el1['pending'] = (!self.inserted).to_s
94    el1['timestamp'] = self.timestamp.xmlschema
95    return el1
96  end
97
98  def import
99    begin
100      logger.info("GPX Import importing #{name} (#{id}) from #{user.email}")
101
102      # TODO *nix specific, could do to work on windows... would be functionally inferior though - check for '.gz'
103      filetype = `file -bz #{trace_name}`.chomp
104      gzipped = filetype =~ /gzip compressed/
105      bzipped = filetype =~ /bzip2 compressed/
106      zipped = filetype =~ /Zip archive/
107      tarred = filetype =~ /tar archive/
108
109      if tarred and gzipped then
110        filename = tempfile = "/tmp/#{rand}"
111        system("tar -zxOf #{trace_name} > #{filename}")
112      elsif tarred and bzipped then
113        filename = tempfile = "/tmp/#{rand}"
114        system("tar -jxOf #{trace_name} > #{filename}")
115      elsif tarred
116        filename = tempfile = "/tmp/#{rand}"
117        system("tar -xOf #{trace_name} > #{filename}")
118      elsif gzipped
119        filename = tempfile = "/tmp/#{rand}"
120        system("gunzip -c #{trace_name} > #{filename}")
121      elsif bzipped
122        filename = tempfile = "/tmp/#{rand}"
123        system("bunzip2 -c #{trace_name} > #{filename}")
124      elsif zipped
125        filename = tempfile = "/tmp/#{rand}"
126        system("unzip -p #{trace_name} > #{filename}")
127      else
128        filename = trace_name
129      end
130
131      gpx = OSM::GPXImporter.new(filename)
132
133      f_lat = 0
134      f_lon = 0
135      first = true
136
137      Tracepoint.delete_all(['gpx_id = ?', self.id])
138
139      gpx.points do |point|
140        if first
141          f_lat = point['latitude']
142          f_lon = point['longitude']
143        end
144
145        tp = Tracepoint.new
146        tp.lat = point['latitude'].to_f
147        tp.lng = point['longitude'].to_f
148        tp.altitude = point['altitude'].to_f
149        tp.timestamp = point['timestamp']
150        tp.user_id = user.id
151        tp.gpx_id = id
152        tp.trackid = point['segment'].to_i
153        tp.save!
154      end
155
156      if gpx.actual_points > 0
157        max_lat = Tracepoint.maximum('latitude', :conditions => ['gpx_id = ?', id])
158        min_lat = Tracepoint.minimum('latitude', :conditions => ['gpx_id = ?', id])
159        max_lon = Tracepoint.maximum('longitude', :conditions => ['gpx_id = ?', id])
160        min_lon = Tracepoint.minimum('longitude', :conditions => ['gpx_id = ?', id])
161
162        max_lat = max_lat.to_f / 1000000
163        min_lat = min_lat.to_f / 1000000
164        max_lon = max_lon.to_f / 1000000
165        min_lon = min_lon.to_f / 1000000
166
167        self.latitude = f_lat
168        self.longitude = f_lon
169        self.large_picture = gpx.get_picture(min_lat, min_lon, max_lat, max_lon, gpx.actual_points)
170        self.icon_picture = gpx.get_icon(min_lat, min_lon, max_lat, max_lon)
171        self.size = gpx.actual_points
172        self.inserted = true
173        self.save
174      end
175
176      logger.info "done trace #{id}"
177
178      return gpx
179    ensure
180      FileUtils.rm_f(tempfile) if tempfile
181    end
182  end
183end
Note: See TracBrowser for help on using the repository browser.