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

Feature Request: Exclude ActiveStorage attachments from tenancy #611

Open
davidlowry opened this issue Aug 1, 2019 · 4 comments
Open

Feature Request: Exclude ActiveStorage attachments from tenancy #611

davidlowry opened this issue Aug 1, 2019 · 4 comments

Comments

@davidlowry
Copy link

Feature request, or How To??

Steps to reproduce

Have an excluded model, add ActiveStorage to that model. Here, Teams have "Logos" and "Branded Backgrounds" which are, ideally, global. My Teams also act as the Tenants here, but the fixture list can be global, and the issue may stand alone.

config.excluded_models = %w{ User Order Team Fixture }

I've tried to exclude some variation of ActiveStorage/ActiveStorage::Attached/ActiveStorage::Attached::One but get a undefined method establish_connection' for [x]` in response.

Desired behavior

A Tenanted model's attachments should be globally accessible

Actual behavior

While the Tenant model is visible, adding an attachment either in the public domain or in a tenant, it displays no attachments for each of the other tenants. If this was Paperclip or some such I don't imagine there'd be an issue, but using Rail's Own Brand storage solution I can't work out the solution.

System configuration

Ruby 2.6.3
Rails 5.2
Apartment 2.2
DB: Sqlite locally/Mysql in production test

  • Apartment config (in config/initializers/apartment.rb or so):

`Apartment.configure do |config|

config.excluded_models = %w{ User Order Team Fixture }

config.excluded_models << 'ActiveStorage::Attached::One'

config.tenant_names = lambda { Team.clients.pluck :tenant_identifier }

config.use_schemas = true
end`

@rubendinho
Copy link

rubendinho commented Sep 20, 2019

Also running into a similar problem:

The model has an attachment using ActiveStorage

class Client < ApplicationRecord
  has_one_attached :logo
end

The model is excluded like so:

Apartment.configure do |config|
...
  config.excluded_models = ['Client']
...
end

When switched onto a tenant DB, the logo is not available.
$ Apartment::Tenant.switch('foo') { Client.first.logo.attached? } # = false

When accessing from the public DB, the logo is attached.
$ Apartment::Tenant.switch { Client.first.logo.attached? } # = true

Is there a way to make ActiveStorage play nice with Apartment?

@rubendinho
Copy link

rubendinho commented Sep 20, 2019

Update: I was able to get things working by adding these two models to excluded_models:
config.excluded_models = ['Client', 'ActiveStorage::Attachment', 'ActiveStorage::Blob']

But this obviously means all ActiveStorage data is only on the "public" DB.

@cimm
Copy link

cimm commented Apr 22, 2020

I was wondering why purge_later didn’t work on my ActiveStorage objects! They are running outside of the Apartment::Tenant scope of course. Thanks!

@archonic
Copy link

archonic commented Jul 21, 2020

In my app, some attachments should be tenanted and other should be public. User avatars for example should be public but attachments on tenanted resources should be tenanted. There's an inherent incompatibility between schemas and polymorphism. It should still work if you use Apartment::Tenant.switch at the right times, but it doesn't.

If I call resource.reload in my avatar helper, that ensures that resource.avatar.attached? is correct and consistent, but it also introduces an N+1. I'm not sure why, but this isn't working:

def avatar_url(resource, width)
  Apartment::Tenant.switch("public") do
    if resource.avatar.attached?
      size_str = "#{width}x#{width}"
      full_url_for_avatar(
        resource.avatar.variant(resize: size_str)
      )
    else
      ""
    end
  end
end

While this is working:

def avatar_url(resource, width)
  Apartment::Tenant.switch("public") do
    # NOTE ActiveStorage + Apartment is buggy?
    if resource.avatar.attached? || resource.reload.avatar.attached?
      size_str = "#{width}x#{width}"
      full_url_for_avatar(
        resource.avatar.variant(resize: size_str)
      )
    else
      ""
    end
  end
end

This may have something to do with the way I'm including the attachment blob in the ActiveRecord::Relation but I don't see any issue with includes(user: { avatar_attachment: :blob }).

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

4 participants