]> git.openstreetmap.org Git - rails.git/commitdiff
Switch traces to use ActiveStorage
authorTom Hughes <tom@compton.nu>
Sun, 17 Oct 2021 15:00:22 +0000 (16:00 +0100)
committerTom Hughes <tom@compton.nu>
Thu, 16 Dec 2021 18:45:31 +0000 (18:45 +0000)
app/controllers/api/traces_controller.rb
app/controllers/traces_controller.rb
app/models/trace.rb
config/settings.yml
config/settings/test.yml
lib/gpx.rb
test/controllers/api/traces_controller_test.rb
test/controllers/traces_controller_test.rb
test/factories/traces.rb
test/models/trace_test.rb

index 43bbeeb1d208361e6e236fb6cbab9e1486b89eb1..aa8a0600071c9c59546091011f568552f51d4767 100644 (file)
@@ -54,6 +54,8 @@ module Api
           send_data(trace.xml_file.read, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
         elsif request.format == Mime[:gpx]
           send_data(trace.xml_file.read, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
+        elsif trace.file.attached?
+          redirect_to rails_blob_path(trace.file, :disposition => "attachment")
         else
           send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment")
         end
@@ -97,12 +99,6 @@ module Api
       # Sanitise the user's filename
       name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, "_")
 
-      # Get a temporary filename...
-      filename = "/tmp/#{rand}"
-
-      # ...and save the uploaded file to that location
-      File.open(filename, "wb") { |f| f.write(file.read) }
-
       # Create the trace object, falsely marked as already
       # inserted to stop the import daemon trying to load it
       trace = Trace.new(
@@ -110,40 +106,14 @@ module Api
         :tagstring => tags,
         :description => description,
         :visibility => visibility,
-        :inserted => true,
+        :inserted => false,
         :user => current_user,
-        :timestamp => Time.now.getutc
+        :timestamp => Time.now.getutc,
+        :file => file
       )
 
-      if trace.valid?
-        Trace.transaction do
-          begin
-            # Save the trace object
-            trace.save!
-
-            # Rename the temporary file to the final name
-            FileUtils.mv(filename, trace.trace_name)
-          rescue StandardError
-            # Remove the file as we have failed to update the database
-            FileUtils.rm_f(filename)
-
-            # Pass the exception on
-            raise
-          end
-
-          begin
-            # Clear the inserted flag to make the import daemon load the trace
-            trace.inserted = false
-            trace.save!
-          rescue StandardError
-            # Remove the file as we have failed to update the database
-            FileUtils.rm_f(trace.trace_name)
-
-            # Pass the exception on
-            raise
-          end
-        end
-      end
+      # Save the trace object
+      trace.save!
 
       # Finally save the user's preferred privacy level
       if pref = current_user.preferences.where(:k => "gps.trace.visibility").first
index 9ebad161396300fde5ade76fc6989d2777cda2ba..a9dbc85396cb675381b074c88cfe8503e020fbe1 100644 (file)
@@ -99,12 +99,8 @@ class TracesController < ApplicationController
     logger.info(params[:trace][:gpx_file].class.name)
 
     if params[:trace][:gpx_file].respond_to?(:read)
-      begin
-        @trace = do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
-                           params[:trace][:description], params[:trace][:visibility])
-      rescue StandardError => e
-        logger.debug e
-      end
+      @trace = do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
+                         params[:trace][:description], params[:trace][:visibility])
 
       if @trace.id
         flash[:notice] = t ".trace_uploaded"
@@ -141,6 +137,8 @@ class TracesController < ApplicationController
         send_data(trace.xml_file.read, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
       elsif request.format == Mime[:gpx]
         send_data(trace.xml_file.read, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
+      elsif trace.file.attached?
+        redirect_to rails_blob_path(trace.file, :disposition => "attachment")
       else
         send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment")
       end
@@ -217,8 +215,12 @@ class TracesController < ApplicationController
 
     if trace.visible? && trace.inserted?
       if trace.public? || (current_user && current_user == trace.user)
-        expires_in 7.days, :private => !trace.public?, :public => trace.public?
-        send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => "image/gif", :disposition => "inline")
+        if trace.icon.attached?
+          redirect_to rails_blob_path(trace.image, :disposition => "inline")
+        else
+          expires_in 7.days, :private => !trace.public?, :public => trace.public?
+          send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => "image/gif", :disposition => "inline")
+        end
       else
         head :forbidden
       end
@@ -234,8 +236,12 @@ class TracesController < ApplicationController
 
     if trace.visible? && trace.inserted?
       if trace.public? || (current_user && current_user == trace.user)
-        expires_in 7.days, :private => !trace.public?, :public => trace.public?
-        send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => "image/gif", :disposition => "inline")
+        if trace.icon.attached?
+          redirect_to rails_blob_path(trace.icon, :disposition => "inline")
+        else
+          expires_in 7.days, :private => !trace.public?, :public => trace.public?
+          send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => "image/gif", :disposition => "inline")
+        end
       else
         head :forbidden
       end
@@ -252,62 +258,29 @@ class TracesController < ApplicationController
     # Sanitise the user's filename
     name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, "_")
 
-    # Get a temporary filename...
-    filename = "/tmp/#{rand}"
-
-    # ...and save the uploaded file to that location
-    File.open(filename, "wb") { |f| f.write(file.read) }
-
-    # Create the trace object, falsely marked as already
-    # inserted to stop the import daemon trying to load it
+    # Create the trace object
     trace = Trace.new(
       :name => name,
       :tagstring => tags,
       :description => description,
       :visibility => visibility,
-      :inserted => true,
+      :inserted => false,
       :user => current_user,
-      :timestamp => Time.now.getutc
+      :timestamp => Time.now.getutc,
+      :file => file
     )
 
-    if trace.valid?
-      Trace.transaction do
-        begin
-          # Save the trace object
-          trace.save!
-
-          # Rename the temporary file to the final name
-          FileUtils.mv(filename, trace.trace_name)
-        rescue StandardError
-          # Remove the file as we have failed to update the database
-          FileUtils.rm_f(filename)
-
-          # Pass the exception on
-          raise
-        end
-
-        begin
-          # Clear the inserted flag to make the import daemon load the trace
-          trace.inserted = false
-          trace.save!
-        rescue StandardError
-          # Remove the file as we have failed to update the database
-          FileUtils.rm_f(trace.trace_name)
-
-          # Pass the exception on
-          raise
-        end
+    # Save the trace object
+    if trace.save
+      # Finally save the user's preferred privacy level
+      if pref = current_user.preferences.where(:k => "gps.trace.visibility").first
+        pref.v = visibility
+        pref.save
+      else
+        current_user.preferences.create(:k => "gps.trace.visibility", :v => visibility)
       end
     end
 
-    # Finally save the user's preferred privacy level
-    if pref = current_user.preferences.where(:k => "gps.trace.visibility").first
-      pref.v = visibility
-      pref.save
-    else
-      current_user.preferences.create(:k => "gps.trace.visibility", :v => visibility)
-    end
-
     trace
   end
 
index b3d87fc0947be767264db9300b5426b909375415..17f8ebc1e12d70779f58bf66d5df7ff9e1cd0690 100644 (file)
@@ -39,6 +39,10 @@ class Trace < ApplicationRecord
   scope :visible_to_all, -> { where(:visibility => %w[public identifiable]) }
   scope :tagged, ->(t) { joins(:tags).where(:gpx_file_tags => { :tag => t }) }
 
+  has_one_attached :file, :service => Settings.trace_file_storage
+  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 :name, :presence => true, :length => 1..255, :characters => true
   validates :description, :presence => { :on => :create }, :length => 1..255, :characters => true
@@ -46,6 +50,7 @@ class Trace < ApplicationRecord
   validates :visibility, :inclusion => %w[private public trackable identifiable]
 
   after_destroy :remove_files
+  after_save :set_filename
 
   def tagstring
     tags.collect(&:tag).join(", ")
@@ -68,6 +73,18 @@ class Trace < ApplicationRecord
                 end
   end
 
+  def file=(attachable)
+    case attachable
+    when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile
+      super(:io => attachable,
+            :filename => attachable.original_filename,
+            :content_type => content_type(attachable.path),
+            :identify => false)
+    else
+      super(attachable)
+    end
+  end
+
   def public?
     visibility == "public" || visibility == "identifiable"
   end
@@ -80,29 +97,27 @@ class Trace < ApplicationRecord
     visibility == "identifiable"
   end
 
-  def large_picture=(data)
-    f = File.new(large_picture_name, "wb")
-    f.syswrite(data)
-    f.close
-  end
-
-  def icon_picture=(data)
-    f = File.new(icon_picture_name, "wb")
-    f.syswrite(data)
-    f.close
-  end
-
   def large_picture
-    f = File.new(large_picture_name, "rb")
-    data = f.sysread(File.size(f.path))
-    f.close
+    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
   end
 
   def icon_picture
-    f = File.new(icon_picture_name, "rb")
-    data = f.sysread(File.size(f.path))
-    f.close
+    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
 
@@ -119,46 +134,22 @@ class Trace < ApplicationRecord
   end
 
   def mime_type
-    filetype = Open3.capture2("/usr/bin/file", "-Lbz", trace_name).first.chomp
-    gzipped = filetype.include?("gzip compressed")
-    bzipped = filetype.include?("bzip2 compressed")
-    zipped = filetype.include?("Zip archive")
-    tarred = filetype.include?("tar archive")
-
-    if gzipped
-      "application/x-gzip"
-    elsif bzipped
-      "application/x-bzip2"
-    elsif zipped
-      "application/x-zip"
-    elsif tarred
-      "application/x-tar"
+    if file.attached?
+      file.content_type
     else
-      "application/gpx+xml"
+      content_type(trace_name)
     end
   end
 
   def extension_name
-    filetype = Open3.capture2("/usr/bin/file", "-Lbz", trace_name).first.chomp
-    gzipped = filetype.include?("gzip compressed")
-    bzipped = filetype.include?("bzip2 compressed")
-    zipped = filetype.include?("Zip archive")
-    tarred = filetype.include?("tar archive")
-
-    if tarred && gzipped
-      ".tar.gz"
-    elsif tarred && bzipped
-      ".tar.bz2"
-    elsif tarred
-      ".tar"
-    elsif gzipped
-      ".gpx.gz"
-    elsif bzipped
-      ".gpx.bz2"
-    elsif zipped
-      ".zip"
-    else
-      ".gpx"
+    case mime_type
+    when "application/x-tar+gzip" then ".tar.gz"
+    when "application/x-tar+x-bzip2" then ".tar.bz2"
+    when "application/x-tar" then ".tar"
+    when "application/zip" then ".zip"
+    when "application/gzip" then ".gpx.gz"
+    when "application/x-bzip2" then ".gpx.bz2"
+    else ".gpx"
     end
   end
 
@@ -207,105 +198,135 @@ class Trace < ApplicationRecord
   end
 
   def xml_file
-    filetype = Open3.capture2("/usr/bin/file", "-Lbz", trace_name).first.chomp
-    gzipped = filetype.include?("gzip compressed")
-    bzipped = filetype.include?("bzip2 compressed")
-    zipped = filetype.include?("Zip archive")
-    tarred = filetype.include?("tar archive")
-
-    if gzipped || bzipped || zipped || tarred
-      file = Tempfile.new("trace.#{id}")
-
-      if tarred && gzipped
-        system("tar", "-zxOf", trace_name, :out => file.path)
-      elsif tarred && bzipped
-        system("tar", "-jxOf", trace_name, :out => file.path)
-      elsif tarred
-        system("tar", "-xOf", trace_name, :out => file.path)
-      elsif gzipped
-        system("gunzip", "-c", trace_name, :out => file.path)
-      elsif bzipped
-        system("bunzip2", "-c", trace_name, :out => file.path)
-      elsif zipped
-        system("unzip", "-p", trace_name, "-x", "__MACOSX/*", :out => file.path, :err => "/dev/null")
+    with_trace_file do |trace_name|
+      filetype = Open3.capture2("/usr/bin/file", "-Lbz", trace_name).first.chomp
+      gzipped = filetype.include?("gzip compressed")
+      bzipped = filetype.include?("bzip2 compressed")
+      zipped = filetype.include?("Zip archive")
+      tarred = filetype.include?("tar archive")
+
+      if gzipped || bzipped || zipped || tarred
+        file = Tempfile.new("trace.#{id}")
+
+        if tarred && gzipped
+          system("tar", "-zxOf", trace_name, :out => file.path)
+        elsif tarred && bzipped
+          system("tar", "-jxOf", trace_name, :out => file.path)
+        elsif tarred
+          system("tar", "-xOf", trace_name, :out => file.path)
+        elsif gzipped
+          system("gunzip", "-c", trace_name, :out => file.path)
+        elsif bzipped
+          system("bunzip2", "-c", trace_name, :out => file.path)
+        elsif zipped
+          system("unzip", "-p", trace_name, "-x", "__MACOSX/*", :out => file.path, :err => "/dev/null")
+        end
+
+        file.unlink
+      else
+        file = File.open(trace_name)
       end
 
-      file.unlink
-    else
-      file = File.open(trace_name)
+      file
     end
-
-    file
   end
 
   def import
     logger.info("GPX Import importing #{name} (#{id}) from #{user.email}")
 
-    gpx = GPX::File.new(trace_name)
-
-    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
-
-    gpx.points.each_slice(1_000) do |points|
-      # Gather the trace points together for a bulk import
-      tracepoints = []
+    with_trace_file do |trace_name|
+      gpx = GPX::File.new(trace_name)
+
+      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
+
+      gpx.points.each_slice(1_000) do |points|
+        # Gather the trace points together for a bulk import
+        tracepoints = []
+
+        points.each do |point|
+          if first
+            f_lat = point.latitude
+            f_lon = point.longitude
+            first = false
+          end
+
+          tp = Tracepoint.new
+          tp.lat = point.latitude
+          tp.lon = point.longitude
+          tp.altitude = point.altitude
+          tp.timestamp = point.timestamp
+          tp.gpx_id = id
+          tp.trackid = point.segment
+          tracepoints << tp
+        end
 
-      points.each do |point|
-        if first
-          f_lat = point.latitude
-          f_lon = point.longitude
-          first = false
+        # Run the before_save and before_create callbacks, and then import them in bulk with activerecord-import
+        tracepoints.each do |tp|
+          tp.run_callbacks(:save) { false }
+          tp.run_callbacks(:create) { false }
         end
 
-        tp = Tracepoint.new
-        tp.lat = point.latitude
-        tp.lon = point.longitude
-        tp.altitude = point.altitude
-        tp.timestamp = point.timestamp
-        tp.gpx_id = id
-        tp.trackid = point.segment
-        tracepoints << tp
+        Tracepoint.import!(tracepoints)
       end
 
-      # Run the before_save and before_create callbacks, and then import them in bulk with activerecord-import
-      tracepoints.each do |tp|
-        tp.run_callbacks(:save) { false }
-        tp.run_callbacks(:create) { false }
+      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 = max_lat.to_f / 10000000
+        min_lat = min_lat.to_f / 10000000
+        max_lon = max_lon.to_f / 10000000
+        min_lon = min_lon.to_f / 10000000
+
+        self.latitude = f_lat
+        self.longitude = f_lon
+        image.attach(:io => gpx.picture(min_lat, min_lon, max_lat, max_lon, gpx.actual_points), :filename => "#{id}.gif", :content_type => "image/gif")
+        icon.attach(:io => gpx.icon(min_lat, min_lon, max_lat, max_lon), :filename => "#{id}_icon.gif", :content_type => "image/gif")
+        self.size = gpx.actual_points
+        self.inserted = true
+        save!
       end
 
-      Tracepoint.import!(tracepoints)
-    end
+      logger.info "done trace #{id}"
 
-    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 = max_lat.to_f / 10000000
-      min_lat = min_lat.to_f / 10000000
-      max_lon = max_lon.to_f / 10000000
-      min_lon = min_lon.to_f / 10000000
-
-      self.latitude = f_lat
-      self.longitude = f_lon
-      self.large_picture = gpx.picture(min_lat, min_lon, max_lat, max_lon, gpx.actual_points)
-      self.icon_picture = gpx.icon(min_lat, min_lon, max_lat, max_lon)
-      self.size = gpx.actual_points
-      self.inserted = true
-      save!
+      gpx
     end
+  end
 
-    logger.info "done trace #{id}"
+  private
 
-    gpx
+  def content_type(file)
+    case Open3.capture2("/usr/bin/file", "-Lbz", file).first.chomp
+    when /.*\btar archive\b.*\bgzip\b/ then "application/x-tar+gzip"
+    when /.*\btar archive\b.*\bbzip2\b/ then "application/x-tar+x-bzip2"
+    when /.*\btar archive\b/ then "application/x-tar"
+    when /.*\bZip archive\b/ then "application/zip"
+    when /.*\bXML\b.*\bgzip\b/ then "application/gzip"
+    when /.*\bXML\b.*\bbzip2\b/ then "application/x-bzip2"
+    else "application/gpx+xml"
+    end
   end
 
-  private
+  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)
index 929df7b8a15ee5bcc3e829a586927b401d122d8a..ffee16114b480275517fb1942a697a9825853f15 100644 (file)
@@ -134,3 +134,6 @@ smtp_user_name: null
 smtp_password: null
 # Storage services
 avatar_storage: "local"
+trace_file_storage: "local"
+trace_image_storage: "local"
+trace_icon_storage: "local"
index 77afe95ee3a94b2c7c0bf326c5d51b6af1cee8f7..3d940aec9a4e1886150c5a85e69b34c655f4fe5e 100644 (file)
@@ -21,3 +21,6 @@ wikipedia_auth_secret: "dummy"
 server_url: "test.host"
 # Storage services for testing
 avatar_storage: "test"
+trace_file_storage: "test"
+trace_image_storage: "test"
+trace_icon_storage: "test"
index 71b2823b85c16a38689987de8fd01a2c97533b1f..3dc448e4632cd85c9221d701f1c8386eca2b8151 100644 (file)
@@ -121,7 +121,7 @@ module GPX
 
       output = StringIO.new
       image.export(output)
-      output.read
+      output
     end
 
     def icon(min_lat, min_lon, max_lat, max_lon)
@@ -161,7 +161,7 @@ module GPX
         end
       end
 
-      image.gif
+      StringIO.new(image.gif)
     end
   end
 
index 52df899ba0778e8f2b600ddf14d6272827aa66da..9719c7c921020b93f3f930d8c2564bd78cbd57f7 100644 (file)
@@ -119,11 +119,15 @@ module Api
       # Now with some other user, which should work since the trace is public
       auth_header = basic_authorization_header create(:user).display_name, "test"
       get api_trace_data_path(public_trace_file), :headers => auth_header
+      follow_redirect!
+      follow_redirect!
       check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
 
       # And finally we should be able to do it with the owner of the trace
       auth_header = basic_authorization_header public_trace_file.user.display_name, "test"
       get api_trace_data_path(public_trace_file), :headers => auth_header
+      follow_redirect!
+      follow_redirect!
       check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
     end
 
@@ -136,7 +140,9 @@ module Api
 
       # First get the data as is
       get api_trace_data_path(identifiable_trace_file), :headers => auth_header
-      check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/x-gzip", "gpx.gz"
+      follow_redirect!
+      follow_redirect!
+      check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/gzip", "gpx.gz"
 
       # Now ask explicitly for XML format
       get api_trace_data_path(identifiable_trace_file, :format => "xml"), :headers => auth_header
@@ -163,6 +169,8 @@ module Api
       # And finally we should be able to do it with the owner of the trace
       auth_header = basic_authorization_header anon_trace_file.user.display_name, "test"
       get api_trace_data_path(anon_trace_file), :headers => auth_header
+      follow_redirect!
+      follow_redirect!
       check_trace_data anon_trace_file, "db4cb5ed2d7d2b627b3b504296c4f701"
     end
 
@@ -211,7 +219,7 @@ module Api
       assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag)
       assert_equal "trackable", trace.visibility
       assert_not trace.inserted
-      assert_equal File.new(fixture).read, File.new(trace.trace_name).read
+      assert_equal File.new(fixture).read, trace.file.blob.download
       trace.destroy
       assert_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v
 
@@ -229,7 +237,7 @@ module Api
       assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag)
       assert_equal "public", trace.visibility
       assert_not trace.inserted
-      assert_equal File.new(fixture).read, File.new(trace.trace_name).read
+      assert_equal File.new(fixture).read, trace.file.blob.download
       trace.destroy
       assert_equal "public", user.preferences.where(:k => "gps.trace.visibility").first.v
 
@@ -248,7 +256,7 @@ module Api
       assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag)
       assert_equal "private", trace.visibility
       assert_not trace.inserted
-      assert_equal File.new(fixture).read, File.new(trace.trace_name).read
+      assert_equal File.new(fixture).read, trace.file.blob.download
       trace.destroy
       assert_equal "private", second_user.preferences.where(:k => "gps.trace.visibility").first.v
     end
index 1c3dc2d31def9fc85db02a1d437d5593ea1143b4..48b5c457f7fe98b2f024d09ba9db0894897a3a7b 100644 (file)
@@ -369,16 +369,22 @@ class TracesControllerTest < ActionDispatch::IntegrationTest
 
     # First with no auth, which should work since the trace is public
     get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
+    follow_redirect!
+    follow_redirect!
     check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
 
     # Now with some other user, which should work since the trace is public
     session_for(create(:user))
     get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
+    follow_redirect!
+    follow_redirect!
     check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
 
     # And finally we should be able to do it with the owner of the trace
     session_for(public_trace_file.user)
     get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
+    follow_redirect!
+    follow_redirect!
     check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
   end
 
@@ -388,7 +394,9 @@ class TracesControllerTest < ActionDispatch::IntegrationTest
 
     # First get the data as is
     get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file)
-    check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/x-gzip", "gpx.gz"
+    follow_redirect!
+    follow_redirect!
+    check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/gzip", "gpx.gz"
 
     # Now ask explicitly for XML format
     get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file.id, :format => "xml")
@@ -415,6 +423,8 @@ class TracesControllerTest < ActionDispatch::IntegrationTest
     # And finally we should be able to do it with the owner of the trace
     session_for(anon_trace_file.user)
     get trace_data_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
+    follow_redirect!
+    follow_redirect!
     check_trace_data anon_trace_file, "db4cb5ed2d7d2b627b3b504296c4f701"
   end
 
@@ -598,7 +608,7 @@ class TracesControllerTest < ActionDispatch::IntegrationTest
     assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag)
     assert_equal "trackable", trace.visibility
     assert_not trace.inserted
-    assert_equal File.new(fixture).read, File.new(trace.trace_name).read
+    assert_equal File.new(fixture).read, trace.file.blob.download
     trace.destroy
     assert_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v
   end
@@ -789,19 +799,22 @@ class TracesControllerTest < ActionDispatch::IntegrationTest
   end
 
   def check_trace_data(trace, digest, content_type = "application/gpx+xml", extension = "gpx")
-    assert_response :success
     assert_equal digest, Digest::MD5.hexdigest(response.body)
     assert_equal content_type, response.media_type
     assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"; filename*=UTF-8''#{trace.id}.#{extension}", @response.header["Content-Disposition"]
   end
 
   def check_trace_picture(trace)
+    follow_redirect!
+    follow_redirect!
     assert_response :success
     assert_equal "image/gif", response.media_type
     assert_equal trace.large_picture, response.body
   end
 
   def check_trace_icon(trace)
+    follow_redirect!
+    follow_redirect!
     assert_response :success
     assert_equal "image/gif", response.media_type
     assert_equal trace.icon_picture, response.body
index 961d52988fc0595c841e9464e9f4028b23447ef6..687339e7f49a5ae1ce9212ba626b94ea51b78979 100644 (file)
@@ -17,14 +17,14 @@ FactoryBot.define do
       fixture { nil }
     end
 
-    after(:create) do |trace, evaluator|
+    after(:build) do |user, evaluator|
       if evaluator.fixture
-        FileUtils.copy(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}.gpx"),
-                       File.join(Settings.gpx_trace_dir, "#{trace.id}.gpx"))
-        FileUtils.copy(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}.gif"),
-                       File.join(Settings.gpx_image_dir, "#{trace.id}.gif"))
-        FileUtils.copy(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}_icon.gif"),
-                       File.join(Settings.gpx_image_dir, "#{trace.id}_icon.gif"))
+        user.file.attach(Rack::Test::UploadedFile.new(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}.gpx")))
+
+        if evaluator.inserted
+          user.image.attach(Rack::Test::UploadedFile.new(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}.gif")))
+          user.icon.attach(Rack::Test::UploadedFile.new(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}_icon.gif")))
+        end
       end
     end
   end
index 9682d6b288a0a3958f5bfa15e0daab3c68dd12c7..1322964c2734da4e5b907945c14a093970cc5497 100644 (file)
@@ -136,11 +136,11 @@ class TraceTest < ActiveSupport::TestCase
     check_mime_type("a", "application/gpx+xml")
     check_mime_type("b", "application/gpx+xml")
     check_mime_type("c", "application/x-bzip2")
-    check_mime_type("d", "application/x-gzip")
-    check_mime_type("f", "application/x-zip")
+    check_mime_type("d", "application/gzip")
+    check_mime_type("f", "application/zip")
     check_mime_type("g", "application/x-tar")
-    check_mime_type("h", "application/x-gzip")
-    check_mime_type("i", "application/x-bzip2")
+    check_mime_type("h", "application/x-tar+gzip")
+    check_mime_type("i", "application/x-tar+x-bzip2")
   end
 
   def test_extension_name
@@ -168,24 +168,16 @@ class TraceTest < ActiveSupport::TestCase
 
   def test_large_picture
     picture = File.read(Rails.root.join("test/gpx/fixtures/a.gif"), :mode => "rb")
+    trace = create(:trace, :fixture => "a")
 
-    trace = Trace.create
-    trace.large_picture = picture
-    assert_equal "7c841749e084ee4a5d13f12cd3bef456", md5sum(File.new(trace.large_picture_name))
     assert_equal picture, trace.large_picture
-
-    trace.destroy
   end
 
   def test_icon_picture
     picture = File.read(Rails.root.join("test/gpx/fixtures/a_icon.gif"), :mode => "rb")
+    trace = create(:trace, :fixture => "a")
 
-    trace = Trace.create
-    trace.icon_picture = picture
-    assert_equal "b47baf22ed0e85d77e808694fad0ee27", md5sum(File.new(trace.icon_picture_name))
     assert_equal picture, trace.icon_picture
-
-    trace.destroy
   end
 
   def test_import_removes_previous_tracepoints
@@ -215,29 +207,27 @@ class TraceTest < ActiveSupport::TestCase
   end
 
   def test_import_creates_icon
-    trace = create(:trace, :fixture => "a")
-    icon_path = File.join(Settings.gpx_image_dir, "#{trace.id}_icon.gif")
-    FileUtils.rm(icon_path)
-    assert_not File.exist?(icon_path)
+    trace = create(:trace, :inserted => false, :fixture => "a")
+
+    assert_not trace.icon.attached?
 
     trace.import
 
-    assert_path_exists(icon_path)
+    assert trace.icon.attached?
   end
 
   def test_import_creates_large_picture
-    trace = create(:trace, :fixture => "a")
-    large_picture_path = File.join(Settings.gpx_image_dir, "#{trace.id}.gif")
-    FileUtils.rm(large_picture_path)
-    assert_not File.exist?(large_picture_path)
+    trace = create(:trace, :inserted => false, :fixture => "a")
+
+    assert_not trace.image.attached?
 
     trace.import
 
-    assert_path_exists(large_picture_path)
+    assert trace.image.attached?
   end
 
   def test_import_handles_bz2
-    trace = create(:trace, :fixture => "c")
+    trace = create(:trace, :inserted => false, :fixture => "c")
 
     trace.import
 
@@ -245,7 +235,7 @@ class TraceTest < ActiveSupport::TestCase
   end
 
   def test_import_handles_plain
-    trace = create(:trace, :fixture => "a")
+    trace = create(:trace, :inserted => false, :fixture => "a")
 
     trace.import
 
@@ -253,7 +243,7 @@ class TraceTest < ActiveSupport::TestCase
   end
 
   def test_import_handles_plain_with_bom
-    trace = create(:trace, :fixture => "b")
+    trace = create(:trace, :inserted => false, :fixture => "b")
 
     trace.import
 
@@ -261,7 +251,7 @@ class TraceTest < ActiveSupport::TestCase
   end
 
   def test_import_handles_gz
-    trace = create(:trace, :fixture => "d")
+    trace = create(:trace, :inserted => false, :fixture => "d")
 
     trace.import
 
@@ -269,7 +259,7 @@ class TraceTest < ActiveSupport::TestCase
   end
 
   def test_import_handles_zip
-    trace = create(:trace, :fixture => "f")
+    trace = create(:trace, :inserted => false, :fixture => "f")
 
     trace.import
 
@@ -277,7 +267,7 @@ class TraceTest < ActiveSupport::TestCase
   end
 
   def test_import_handles_tar
-    trace = create(:trace, :fixture => "g")
+    trace = create(:trace, :inserted => false, :fixture => "g")
 
     trace.import
 
@@ -285,7 +275,7 @@ class TraceTest < ActiveSupport::TestCase
   end
 
   def test_import_handles_tar_gz
-    trace = create(:trace, :fixture => "h")
+    trace = create(:trace, :inserted => false, :fixture => "h")
 
     trace.import
 
@@ -293,7 +283,7 @@ class TraceTest < ActiveSupport::TestCase
   end
 
   def test_import_handles_tar_bz2
-    trace = create(:trace, :fixture => "i")
+    trace = create(:trace, :inserted => false, :fixture => "i")
 
     trace.import