[go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ActiveStorage - attached file quietly discarded if record is later locked in the same transaction #53737

Open
seandilda opened this issue Nov 25, 2024 · 0 comments

Comments

@seandilda
Copy link

Steps to reproduce

  1. Open a transaction (using #transaction or #with_lock)
  2. Attach a file
  3. Call #with_lock while in the same transaction
  4. Close the transaction
  5. Try to download the attachment
# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  gem "rails", '~> 7.2'
  # If you want to test against edge Rails replace the previous line with this:
  # gem "rails", github: "rails/rails", branch: "main"
  gem 'securerandom'

  gem "sqlite3"
end

require "active_record/railtie"
require "active_storage/engine"
require "minitest/autorun"

ENV["DATABASE_URL"] = "sqlite3::memory:"

class TestApp < Rails::Application
  config.load_defaults Rails::VERSION::STRING.to_f

  config.root = __dir__
  config.hosts << "example.org"
  config.eager_load = false
  config.session_store :cookie_store, key: "cookie_store_key"
  config.secret_key_base = "secret_key_base"

  config.logger = Logger.new($stdout)
  Rails.logger  = config.logger

  config.active_storage.service = :local
  config.active_storage.service_configurations = {
    local: {
      root: Dir.tmpdir,
      service: "Disk"
    }
  }
end
Rails.application.initialize!

require ActiveStorage::Engine.root.join("db/migrate/20170806125915_create_active_storage_tables.rb").to_s

ActiveRecord::Schema.define do
  CreateActiveStorageTables.new.change

  create_table :users, force: true
end

class User < ActiveRecord::Base
  has_one_attached :profile
end

class BugTest < ActiveSupport::TestCase
  def test_upload_and_download
    user = User.create!
    user.transaction do
      user.profile.attach(content_type: "text/plain",
                          filename: "dummy.txt",
                          io: ::StringIO.new("dummy"))
      user.with_lock {}
    end

    assert_equal "dummy", user.profile.download
  end
end

Expected behavior

File should be properly saved in the backend or an error raised if that is not possible.

Actual behavior

The attachment appears to work. However, when you later call #download on it, you receive an ActiveStorage::FileNotFoundError error.

If you are updating an existing attachment, the old saved file will still be deleted, but the new data will be lost.

System configuration

Rails version: 7.2.1.1

Ruby version: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [x86_64-linux]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant