使用Paperclip(使用s3存储)和Apartment gem时遇到非常有线的问题。
Apartment gem正在与Postgres DB一起用于多租户。 (即每个租户的单独模式)
对于存储,我想为每个租户创建一个单独的文件夹。
class Media < ApplicationRecord
belongs_to :user
has_attached_file :file,
:storage => :s3,
:s3_credentials => {
:access_key_id => "ACCESSKEY",
:secret_access_key => "SECRETE KEY"
},
:path => "#{Apartment::Tenant.current}/:class/:attachment/:id_partition/:style/:filename"
end
以上是我的媒体文件夹,属于用户。
class User < ApplicationRecord
has_attached_file :avatar,
:storage => :s3,
:s3_credentials => {
:access_key_id => "ACCESSKEY",
:secret_access_key => "SECRETE KEY"
},
:path => "#{Apartment::Tenant.current}/:class/:attachment/:id_partition/:style/:filename"
end
Apartment.rb文件如下所示
require 'apartment/elevators/subdomain'
require 'rescued_apartment_middleware'
Apartment.configure do |config|
config.excluded_models = %w{ Account }
config.tenant_names = lambda { Account.pluck :subdomain }
config.use_schemas = true
end
Rails.application.config.middleware.insert_before Warden::Manager, RescuedApartmentElevator
Apartment::Elevators::Subdomain.excluded_subdomains = ['www','admin']
rescued_apartment_elevator.rb文件如下所示
class RescuedApartmentElevator < Apartment::Elevators::Subdomain
def call(env)
begin
super
rescue Apartment::TenantNotFound
env[:apartment_tenant_not_found] = true # to be later referenced in your ApplicationController
@app.call(env) # the middleware call method should return this, but it was probably short-circuited by the raise
end
end
end
在application_controller.rb中,我处理了类似下面的代码
class ApplicationController < ActionController::Base
before_action :load_schema, :authenticate_user!, :set_mailer_host
before_action :configure_permitted_parameters, if: :devise_controller?
private
def load_schema
Apartment::Tenant.switch!
return if request.subdomain == "www"
if request.subdomain == ""
redirect_to root_url(subdomain: 'www')
else
if current_account
Apartment::Tenant.switch!(current_account.subdomain)
else
if request.env[:apartment_tenant_not_found]
redirect_to root_url(subdomain: 'www'), notice: 'Account you are looking for do not exists'
end
end
end
end
end
我启动服务器,转到其中一个租户,例如http://apple.lvh.me:3000(苹果是租客名称)
1。如果我去编辑用户个人资料并上传用户个人资料的文件, Apartment :: Tenant.current在模型中返回“public”,因此 该文件正在上传到公共文件夹而不是“苹果” 文件夹中。
我在下面使用devise gem(最新版本)是我的user_controller.rb的样子
class UsersController < ApplicationController
before_action : set_user, only: [:edit,:update]
def update
if @user.update(user_params)
if @user.pending_reconfirmation?
redirect_to edit_user_path(current_user), notice: "Your profile is successfully updated! But if you changed the email address, then please confirm it before!"
else
redirect_to edit_user_path(current_user), notice: "Your profile is successfully updated!"
end
else
render "edit"
end
end
end
问题2 **当我去媒体并添加一些媒体时,他们会正确地转到s3桶上的“apple”文件夹。我会签出,转到不同的tanent,http://google.lvh.me:3000/(谷歌是租户名称)。如果我去媒体列表,URL将继续指向Apartment :: Tenant.current - &gt;只有苹果。这会导致Google租户的错误网址和图片无法显示。
如果我关闭并重新启动服务器,则rails将开始返回google for Apartment :: Tenant.current方法,因此URL正确指向正确的文件夹。 **
夏季,下面是我的问题。
答案 0 :(得分:1)
发布到StackOverflow后,我能够找到解决方案。将其发布在此处以防万一其他人将来发现此事。
我的错误是尝试直接使用#{Apartment :: Tenant.current}进入路径。这是错的。回形针支持插值,我应该使用它来生成动态路径。
以下是所需的更改。
has_attached_file :file,
:storage => :s3,
:s3_credentials => {
:access_key_id => "AccessKey",
:secret_access_key => "SecreteKey"
},
:path => ":tenant/:class/:attachment/:id_partition/:style/:filename"
请注意:路径中引入了租户。
将以下行添加到paperclip.rb
中Paperclip.interpolates :tenant do |attachment, style|
Apartment::Tenant.current
end
就是这样。希望它可以帮助别人!