]> git.openstreetmap.org Git - rails.git/blobdiff - app/models/trace.rb
Merge pull request #4536 from tomhughes/trace-size-limit
[rails.git] / app / models / trace.rb
index bdafdd9d5c9116f4340ddd0af108fa86abbf549a..818cc363b8629595bed5a4d842033f708598f14c 100644 (file)
@@ -31,11 +31,11 @@ class Trace < ApplicationRecord
   self.table_name = "gpx_files"
 
   belongs_to :user, :counter_cache => true
-  has_many :tags, :class_name => "Tracetag", :foreign_key => "gpx_id", :dependent => :delete_all
-  has_many :points, :class_name => "Tracepoint", :foreign_key => "gpx_id", :dependent => :delete_all
+  has_many :tags, :class_name => "Tracetag", :foreign_key => "gpx_id", :dependent => :delete_all, :inverse_of => :trace
+  has_many :points, :class_name => "Tracepoint", :foreign_key => "gpx_id", :dependent => :delete_all, :inverse_of => :trace
 
   scope :visible, -> { where(:visible => true) }
-  scope :visible_to, ->(u) { visible.where("visibility IN ('public', 'identifiable') OR user_id = ?", u) }
+  scope :visible_to, ->(u) { visible.where(:visibility => %w[public identifiable]).or(visible.where(:user => u)) }
   scope :visible_to_all, -> { where(:visibility => %w[public identifiable]) }
   scope :tagged, ->(t) { joins(:tags).where(:gpx_file_tags => { :tag => t }) }
 
@@ -43,13 +43,12 @@ class Trace < ApplicationRecord
   has_one_attached :image, :service => Settings.trace_image_storage
   has_one_attached :icon, :service => Settings.trace_icon_storage
 
-  validates :user, :presence => true, :associated => true
+  validates :user, :associated => true
   validates :name, :presence => true, :length => 1..255, :characters => true
   validates :description, :presence => { :on => :create }, :length => 1..255, :characters => true
   validates :timestamp, :presence => true
   validates :visibility, :inclusion => %w[private public trackable identifiable]
 
-  after_destroy :remove_files
   after_save :set_filename
 
   def tagstring
@@ -58,7 +57,7 @@ class Trace < ApplicationRecord
 
   def tagstring=(s)
     self.tags = if s.include? ","
-                  s.split(/\s*,\s*/).grep_v(/^\s*$/).collect do |tag|
+                  s.split(",").map(&:strip).reject(&:empty?).collect do |tag|
                     tt = Tracetag.new
                     tt.tag = tag
                     tt
@@ -98,47 +97,15 @@ class Trace < ApplicationRecord
   end
 
   def large_picture
-    if image.attached?
-      data = image.blob.download
-    else
-      f = File.new(large_picture_name, "rb")
-      data = f.sysread(File.size(f.path))
-      f.close
-    end
-
-    data
+    image.blob.download
   end
 
   def icon_picture
-    if icon.attached?
-      data = icon.blob.download
-    else
-      f = File.new(icon_picture_name, "rb")
-      data = f.sysread(File.size(f.path))
-      f.close
-    end
-
-    data
-  end
-
-  def large_picture_name
-    "#{Settings.gpx_image_dir}/#{id}.gif"
-  end
-
-  def icon_picture_name
-    "#{Settings.gpx_image_dir}/#{id}_icon.gif"
-  end
-
-  def trace_name
-    "#{Settings.gpx_trace_dir}/#{id}.gpx"
+    icon.blob.download
   end
 
   def mime_type
-    if file.attached?
-      file.content_type
-    else
-      content_type(trace_name)
-    end
+    file.content_type
   end
 
   def extension_name
@@ -198,8 +165,8 @@ class Trace < ApplicationRecord
   end
 
   def xml_file
-    with_trace_file do |trace_name|
-      filetype = Open3.capture2("/usr/bin/file", "-Lbz", trace_name).first.chomp
+    file.open do |tracefile|
+      filetype = Open3.capture2("/usr/bin/file", "-Lbz", tracefile.path).first.chomp
       gzipped = filetype.include?("gzip compressed")
       bzipped = filetype.include?("bzip2 compressed")
       zipped = filetype.include?("Zip archive")
@@ -209,22 +176,22 @@ class Trace < ApplicationRecord
         file = Tempfile.new("trace.#{id}")
 
         if tarred && gzipped
-          system("tar", "-zxOf", trace_name, :out => file.path)
+          system("tar", "-zxOf", tracefile.path, :out => file.path)
         elsif tarred && bzipped
-          system("tar", "-jxOf", trace_name, :out => file.path)
+          system("tar", "-jxOf", tracefile.path, :out => file.path)
         elsif tarred
-          system("tar", "-xOf", trace_name, :out => file.path)
+          system("tar", "-xOf", tracefile.path, :out => file.path)
         elsif gzipped
-          system("gunzip", "-c", trace_name, :out => file.path)
+          system("gunzip", "-c", tracefile.path, :out => file.path)
         elsif bzipped
-          system("bunzip2", "-c", trace_name, :out => file.path)
+          system("bunzip2", "-c", tracefile.path, :out => file.path)
         elsif zipped
-          system("unzip", "-p", trace_name, "-x", "__MACOSX/*", :out => file.path, :err => "/dev/null")
+          system("unzip", "-p", tracefile.path, "-x", "__MACOSX/*", :out => file.path, :err => "/dev/null")
         end
 
         file.unlink
       else
-        file = File.open(trace_name)
+        file = File.open(tracefile.path)
       end
 
       file
@@ -234,15 +201,15 @@ class Trace < ApplicationRecord
   def import
     logger.info("GPX Import importing #{name} (#{id}) from #{user.email}")
 
-    with_trace_file do |trace_name|
-      gpx = GPX::File.new(trace_name)
+    file.open do |file|
+      gpx = GPX::File.new(file.path, :maximum_points => Settings.max_trace_size)
 
       f_lat = 0
       f_lon = 0
       first = true
 
       # If there are any existing points for this trace then delete them
-      Tracepoint.where(:gpx_id => id).delete_all
+      Tracepoint.where(:trace => id).delete_all
 
       gpx.points.each_slice(1_000) do |points|
         # Gather the trace points together for a bulk import
@@ -275,10 +242,10 @@ class Trace < ApplicationRecord
       end
 
       if gpx.actual_points.positive?
-        max_lat = Tracepoint.where(:gpx_id => id).maximum(:latitude)
-        min_lat = Tracepoint.where(:gpx_id => id).minimum(:latitude)
-        max_lon = Tracepoint.where(:gpx_id => id).maximum(:longitude)
-        min_lon = Tracepoint.where(:gpx_id => id).minimum(:longitude)
+        max_lat = Tracepoint.where(:trace => id).maximum(:latitude)
+        min_lat = Tracepoint.where(:trace => id).minimum(:latitude)
+        max_lon = Tracepoint.where(:trace => id).maximum(:longitude)
+        min_lon = Tracepoint.where(:trace => id).minimum(:longitude)
 
         max_lat = max_lat.to_f / 10000000
         min_lat = min_lat.to_f / 10000000
@@ -300,24 +267,12 @@ class Trace < ApplicationRecord
     end
   end
 
-  def migrate_to_storage!
-    file.attach(:io => File.open(trace_name),
-                :filename => name,
-                :content_type => content_type(trace_name),
-                :identify => false)
-
-    if inserted
-      image.attach(:io => File.open(large_picture_name),
-                   :filename => "#{id}.gif",
-                   :content_type => "image/gif")
-      icon.attach(:io => File.open(icon_picture_name),
-                  :filename => "#{id}_icon.gif",
-                  :content_type => "image/gif")
-    end
-
-    save!
+  def schedule_import
+    TraceImporterJob.new(self).enqueue(:priority => user.traces.where(:inserted => false).count)
+  end
 
-    remove_files
+  def schedule_destruction
+    TraceDestroyerJob.perform_later(self)
   end
 
   private
@@ -334,23 +289,7 @@ class Trace < ApplicationRecord
     end
   end
 
-  def with_trace_file
-    if file.attached?
-      file.open do |file|
-        yield file.path
-      end
-    else
-      yield trace_name
-    end
-  end
-
   def set_filename
     file.blob.update(:filename => "#{id}#{extension_name}") if file.attached?
   end
-
-  def remove_files
-    FileUtils.rm_f(trace_name)
-    FileUtils.rm_f(icon_picture_name)
-    FileUtils.rm_f(large_picture_name)
-  end
 end