activestorage_saas 7.0.4 → 7.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AGENTS.md +260 -0
- data/CHANGELOG.md +12 -0
- data/COVERAGE.md +64 -0
- data/Gemfile +6 -5
- data/README.md +206 -17
- data/lib/active_storage_saas/direct_uploads_controller_mixin.rb +1 -1
- data/lib/active_storage_saas/storage_service_configuration_model_mixin.rb +2 -1
- metadata +9 -21
- data/.rspec +0 -3
- data/.rubocop.yml +0 -17
- data/Gemfile.lock +0 -236
- data/Guardfile +0 -42
- data/Rakefile +0 -8
- data/activestorage_saas.gemspec +0 -30
- data/config/initializers/active_storage_saas.rb +0 -6
- data/sig/activestorage_saas.rbs +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 422aa00826004eda3168829ac76146aa61a20934de7e41cd05ec8f4eccd4c6eb
|
|
4
|
+
data.tar.gz: 8ff8749becec2ae3ed721ee1cfe1fe1e2dcaa3e1658c06364c4304d452f131b7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d4d504753d8951ad1d8e932d417590b3bf8d916f84ceb3ec09438203158a59192c8e183a943b8d9d3c07a98db38803f9d55579da9079b0861b9dd17cf832cb02
|
|
7
|
+
data.tar.gz: 66e2ce4a52e23ebf32dcddbb3046e8e51cd3c8b8580d1c94d4713605de2e9f9863d5150c445a801900c993f11bbb8868c0d398b70604ec6b6fd5467996e88118
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# ActiveStorageSaas - AI 助手指南
|
|
2
|
+
|
|
3
|
+
本文档用于指导 AI 助手理解 ActiveStorageSaas gem 的代码结构、依赖关系和升级流程。
|
|
4
|
+
|
|
5
|
+
## 项目概述
|
|
6
|
+
|
|
7
|
+
ActiveStorageSaas 是一个 Rails gem,为 ActiveStorage 提供多租户存储服务支持。它通过扩展 ActiveStorage 的核心类来实现动态存储服务加载。
|
|
8
|
+
|
|
9
|
+
## 核心架构
|
|
10
|
+
|
|
11
|
+
### 1. 主要组件
|
|
12
|
+
|
|
13
|
+
#### SaasService (`lib/active_storage/service/saas_service.rb`)
|
|
14
|
+
- **作用**:包装器服务,动态委托方法调用到实际的存储服务
|
|
15
|
+
- **关键特性**:
|
|
16
|
+
- 通过 `Service.public_instance_methods(false)` 动态定义所有 Service 方法
|
|
17
|
+
- 使用 `method_missing` 处理未定义的方法
|
|
18
|
+
- 通过 `service_resolver` 根据 blob 动态解析实际服务
|
|
19
|
+
- **依赖的 Rails API**:
|
|
20
|
+
- `ActiveStorage::Service` 基类
|
|
21
|
+
- `Service.public_instance_methods` 方法
|
|
22
|
+
- `url_for_direct_upload` 和 `headers_for_direct_upload` 方法(需要支持 `custom_metadata` 参数)
|
|
23
|
+
|
|
24
|
+
#### BlobModelMixin (`lib/active_storage_saas/blob_model_mixin.rb`)
|
|
25
|
+
- **作用**:扩展 `ActiveStorage::Blob`,重写 `service` 方法以支持动态服务解析
|
|
26
|
+
- **关键方法**:
|
|
27
|
+
- `service`:重写以支持动态服务解析
|
|
28
|
+
- `analyzer_class`:支持服务级别的 analyzers
|
|
29
|
+
- `validate_service_name_in_services`:验证服务名称
|
|
30
|
+
- **依赖的 Rails API**:
|
|
31
|
+
- `ActiveStorage::Blob#service` 方法
|
|
32
|
+
- `ActiveStorage::Blob#service_name` 属性
|
|
33
|
+
- `ActiveSupport.on_load(:active_storage_blob)` 钩子
|
|
34
|
+
- `redefine_method` (ActiveSupport 扩展)
|
|
35
|
+
|
|
36
|
+
#### DirectUploadsControllerMixin (`lib/active_storage_saas/direct_uploads_controller_mixin.rb`)
|
|
37
|
+
- **作用**:扩展 `ActiveStorage::DirectUploadsController`,支持动态服务名称
|
|
38
|
+
- **关键方法**:
|
|
39
|
+
- `create`:重写以使用 `create_before_direct_upload!` 并传递 `service_name`
|
|
40
|
+
- `blob_args`:合并额外的 blob 参数和服务名称
|
|
41
|
+
- **依赖的 Rails API**:
|
|
42
|
+
- `ActiveStorage::DirectUploadsController#create` 方法
|
|
43
|
+
- `ActiveStorage::Blob.create_before_direct_upload!` 方法
|
|
44
|
+
- `blob_args` 方法签名
|
|
45
|
+
|
|
46
|
+
#### StorageServiceConfigurationMixin (`lib/active_storage_saas/storage_service_configuration_model_mixin.rb`)
|
|
47
|
+
- **作用**:为存储服务配置模型提供方法
|
|
48
|
+
- **关键方法**:
|
|
49
|
+
- `to_service`:根据配置创建存储服务实例
|
|
50
|
+
- `to_service_name`:生成格式为 `ClassName:ID` 的服务名称
|
|
51
|
+
- `from_service_name`:从服务名称解析配置记录
|
|
52
|
+
- **依赖的 Rails API**:
|
|
53
|
+
- `ActiveStorage::Blob.services` 和 `services.fetch`
|
|
54
|
+
- `ActiveStorage::Blob.services.send(:configurations)`
|
|
55
|
+
|
|
56
|
+
#### Engine (`lib/active_storage_saas/engine.rb`)
|
|
57
|
+
- **作用**:Rails Engine,负责加载 mixins 和配置
|
|
58
|
+
- **关键初始化**:
|
|
59
|
+
- 使用 `ActiveSupport.on_load(:active_storage_blob)` 加载 BlobModelMixin
|
|
60
|
+
- 使用 `config.to_prepare` 加载 DirectUploadsControllerMixin
|
|
61
|
+
- 配置默认的服务解析器、转换器等
|
|
62
|
+
|
|
63
|
+
## 依赖的 Rails 版本和 API
|
|
64
|
+
|
|
65
|
+
### 当前版本
|
|
66
|
+
- **Rails**: 7.2.3
|
|
67
|
+
- **ActiveStorage**: 7.2.3
|
|
68
|
+
- **Ruby**: >= 2.6.0
|
|
69
|
+
|
|
70
|
+
### 关键依赖的 Rails API
|
|
71
|
+
|
|
72
|
+
在升级时需要检查以下 API 是否发生变化:
|
|
73
|
+
|
|
74
|
+
1. **ActiveStorage::Service**
|
|
75
|
+
- `public_instance_methods(false)` - 用于动态方法定义
|
|
76
|
+
- `url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:, custom_metadata: {})`
|
|
77
|
+
- `headers_for_direct_upload(key, filename:, content_type:, content_length:, checksum:, custom_metadata: {})`
|
|
78
|
+
- `name=` 和 `name` 方法
|
|
79
|
+
|
|
80
|
+
2. **ActiveStorage::Blob**
|
|
81
|
+
- `service` 方法(返回服务实例)
|
|
82
|
+
- `service_name` 属性
|
|
83
|
+
- `create_before_direct_upload!` 方法签名
|
|
84
|
+
- `services` 类属性(Registry 对象)
|
|
85
|
+
- `services.fetch(service_name)` 方法
|
|
86
|
+
- `services.send(:configurations)` 方法
|
|
87
|
+
|
|
88
|
+
3. **ActiveStorage::DirectUploadsController**
|
|
89
|
+
- `create` 方法
|
|
90
|
+
- `blob_args` 方法(返回 Hash)
|
|
91
|
+
- `direct_upload_json` 方法
|
|
92
|
+
|
|
93
|
+
4. **ActiveSupport**
|
|
94
|
+
- `on_load(:active_storage_blob)` 钩子
|
|
95
|
+
- `redefine_method` 方法(Module 扩展)
|
|
96
|
+
- `ruby2_keywords`(Ruby 2.x 兼容性,Ruby 3.x 会忽略)
|
|
97
|
+
|
|
98
|
+
## 升级检查清单
|
|
99
|
+
|
|
100
|
+
当需要升级 Rails 版本时,AI 助手应该执行以下检查:
|
|
101
|
+
|
|
102
|
+
### 1. 更新依赖版本
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
# activestorage_saas.gemspec
|
|
106
|
+
spec.version = "X.Y.Z" # 更新为新版本
|
|
107
|
+
spec.add_dependency "activestorage", 'X.Y.Z' # 更新为对应的 Rails 版本
|
|
108
|
+
|
|
109
|
+
# Gemfile
|
|
110
|
+
gem "rails", "X.Y.Z" # 更新为新版本
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 2. 检查 Service 类变更
|
|
114
|
+
|
|
115
|
+
**文件**: `/Users/xiaohui/Codes/rails/activestorage/lib/active_storage/service.rb`
|
|
116
|
+
|
|
117
|
+
检查点:
|
|
118
|
+
- `url_for_direct_upload` 方法签名是否变化(特别是 `custom_metadata` 参数)
|
|
119
|
+
- `headers_for_direct_upload` 方法签名是否变化
|
|
120
|
+
- `public_instance_methods(false)` 是否仍然可用
|
|
121
|
+
- 是否有新的公共方法需要委托
|
|
122
|
+
|
|
123
|
+
**影响文件**:
|
|
124
|
+
- `lib/active_storage/service/saas_service.rb`
|
|
125
|
+
|
|
126
|
+
### 3. 检查 Blob 类变更
|
|
127
|
+
|
|
128
|
+
**文件**: `/Users/xiaohui/Codes/rails/activestorage/app/models/active_storage/blob.rb`
|
|
129
|
+
|
|
130
|
+
检查点:
|
|
131
|
+
- `service` 方法实现是否变化
|
|
132
|
+
- `create_before_direct_upload!` 方法签名是否变化
|
|
133
|
+
- `services` 类属性的类型和接口是否变化
|
|
134
|
+
- `services.fetch` 和 `services.send(:configurations)` 是否仍然可用
|
|
135
|
+
- 验证逻辑是否变化(`validate do` 块)
|
|
136
|
+
|
|
137
|
+
**影响文件**:
|
|
138
|
+
- `lib/active_storage_saas/blob_model_mixin.rb`
|
|
139
|
+
|
|
140
|
+
### 4. 检查 DirectUploadsController 变更
|
|
141
|
+
|
|
142
|
+
**文件**: `/Users/xiaohui/Codes/rails/activestorage/app/controllers/active_storage/direct_uploads_controller.rb`
|
|
143
|
+
|
|
144
|
+
检查点:
|
|
145
|
+
- `create` 方法实现是否变化
|
|
146
|
+
- `blob_args` 方法返回格式是否变化
|
|
147
|
+
- `create_before_direct_upload!` 调用方式是否变化(是否使用 `**blob_args` 展开)
|
|
148
|
+
|
|
149
|
+
**影响文件**:
|
|
150
|
+
- `lib/active_storage_saas/direct_uploads_controller_mixin.rb`
|
|
151
|
+
|
|
152
|
+
### 5. 检查 ActiveSupport 钩子
|
|
153
|
+
|
|
154
|
+
**文件**: `/Users/xiaohui/Codes/rails/activestorage/lib/active_storage/engine.rb`
|
|
155
|
+
|
|
156
|
+
检查点:
|
|
157
|
+
- `ActiveSupport.on_load(:active_storage_blob)` 是否仍然可用
|
|
158
|
+
- 钩子触发时机是否变化
|
|
159
|
+
|
|
160
|
+
**影响文件**:
|
|
161
|
+
- `lib/active_storage_saas/engine.rb`
|
|
162
|
+
|
|
163
|
+
### 6. 检查 ActiveSupport 扩展
|
|
164
|
+
|
|
165
|
+
**文件**: `/Users/xiaohui/Codes/rails/activesupport/lib/active_support/core_ext/module/redefine_method.rb`
|
|
166
|
+
|
|
167
|
+
检查点:
|
|
168
|
+
- `redefine_method` 是否仍然可用
|
|
169
|
+
- 方法签名是否变化
|
|
170
|
+
|
|
171
|
+
**影响文件**:
|
|
172
|
+
- `lib/active_storage_saas/blob_model_mixin.rb`
|
|
173
|
+
- `lib/active_storage/service/saas_service.rb`
|
|
174
|
+
|
|
175
|
+
### 7. 检查方法委托机制
|
|
176
|
+
|
|
177
|
+
检查 `ruby2_keywords` 的使用:
|
|
178
|
+
- Ruby 3.x 会自动忽略 `ruby2_keywords`,但保留它不会造成问题
|
|
179
|
+
- 如果 Rails 移除了对 Ruby 2.x 的支持,可以考虑移除
|
|
180
|
+
|
|
181
|
+
**影响文件**:
|
|
182
|
+
- `lib/active_storage/service/saas_service.rb`
|
|
183
|
+
|
|
184
|
+
## 升级工作流程
|
|
185
|
+
|
|
186
|
+
### 步骤 1: 定位 Rails 源码
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# 假设 Rails 源码在 /Users/xiaohui/Codes/rails
|
|
190
|
+
cd /Users/xiaohui/Codes/rails
|
|
191
|
+
git checkout v7.2.3 # 切换到目标版本
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### 步骤 2: 对比关键文件
|
|
195
|
+
|
|
196
|
+
使用 `grep` 和 `read_file` 工具检查关键文件:
|
|
197
|
+
|
|
198
|
+
1. 读取 Rails 源码中的相关文件
|
|
199
|
+
2. 对比当前 gem 代码
|
|
200
|
+
3. 识别变更点
|
|
201
|
+
|
|
202
|
+
### 步骤 3: 更新代码
|
|
203
|
+
|
|
204
|
+
根据检查结果更新:
|
|
205
|
+
|
|
206
|
+
1. **SaasService**: 如果 Service 类有新方法,动态委托会自动处理;如果方法签名变化,需要更新
|
|
207
|
+
2. **BlobModelMixin**: 如果 `service` 方法实现变化,需要更新重写逻辑
|
|
208
|
+
3. **DirectUploadsControllerMixin**: 如果 `create` 或 `blob_args` 变化,需要更新
|
|
209
|
+
4. **Engine**: 如果钩子机制变化,需要更新初始化逻辑
|
|
210
|
+
|
|
211
|
+
### 步骤 4: 测试兼容性
|
|
212
|
+
|
|
213
|
+
运行测试套件:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
bundle exec rspec
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### 步骤 5: 更新文档
|
|
220
|
+
|
|
221
|
+
更新 `README.md` 和 `CHANGELOG.md` 中的版本信息。
|
|
222
|
+
|
|
223
|
+
## 常见问题
|
|
224
|
+
|
|
225
|
+
### Q: 如何知道 Rails 版本是否兼容?
|
|
226
|
+
|
|
227
|
+
A: 检查以下关键点:
|
|
228
|
+
1. `ActiveStorage::Service` 的公共方法列表
|
|
229
|
+
2. `ActiveStorage::Blob#service` 方法实现
|
|
230
|
+
3. `ActiveStorage::DirectUploadsController#create` 方法实现
|
|
231
|
+
4. ActiveSupport 钩子是否仍然可用
|
|
232
|
+
|
|
233
|
+
### Q: 如果 Rails 移除了某个方法怎么办?
|
|
234
|
+
|
|
235
|
+
A:
|
|
236
|
+
1. 检查是否有替代方法
|
|
237
|
+
2. 如果必须保留功能,考虑在 gem 中实现兼容层
|
|
238
|
+
3. 更新文档说明兼容性要求
|
|
239
|
+
|
|
240
|
+
### Q: 如何测试升级后的兼容性?
|
|
241
|
+
|
|
242
|
+
A:
|
|
243
|
+
1. 运行完整的测试套件
|
|
244
|
+
2. 在测试应用中创建 blob 并验证服务解析
|
|
245
|
+
3. 测试直接上传功能
|
|
246
|
+
4. 测试多租户场景
|
|
247
|
+
|
|
248
|
+
## 代码修改原则
|
|
249
|
+
|
|
250
|
+
1. **最小侵入**:尽量使用 mixin 和 prepend,避免直接修改 Rails 代码
|
|
251
|
+
2. **向后兼容**:保留对旧版本 Ruby/Rails 的支持(如果可能)
|
|
252
|
+
3. **委托优先**:通过方法委托实现功能,而不是复制代码
|
|
253
|
+
4. **测试覆盖**:确保所有关键功能都有测试覆盖
|
|
254
|
+
|
|
255
|
+
## 参考资源
|
|
256
|
+
|
|
257
|
+
- Rails ActiveStorage 文档: https://guides.rubyonrails.org/active_storage_overview.html
|
|
258
|
+
- Rails 源码: `/Users/xiaohui/Codes/rails`
|
|
259
|
+
- 当前 gem 版本: 7.2.3
|
|
260
|
+
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [7.2.3] - 2024-XX-XX
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- 升级支持 Rails 7.2.3
|
|
7
|
+
- 更新 `DirectUploadsControllerMixin` 使用 `create_before_direct_upload!` 方法,与 Rails 7.2.3 保持一致
|
|
8
|
+
- 更新依赖版本:activestorage 7.2.3
|
|
9
|
+
|
|
10
|
+
### Compatibility
|
|
11
|
+
- Rails: 7.2.3
|
|
12
|
+
- ActiveStorage: 7.2.3
|
|
13
|
+
- Ruby: >= 2.6.0
|
|
14
|
+
|
|
3
15
|
## [0.1.0] - 2022-08-09
|
|
4
16
|
|
|
5
17
|
- Initial release
|
data/COVERAGE.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# 代码覆盖率
|
|
2
|
+
|
|
3
|
+
本项目使用 [SimpleCov](https://github.com/simplecov-ruby/simplecov) 来跟踪代码覆盖率。
|
|
4
|
+
|
|
5
|
+
## 覆盖率要求
|
|
6
|
+
|
|
7
|
+
- **最小行覆盖率**: 90%
|
|
8
|
+
- **最小文件覆盖率**: 80%
|
|
9
|
+
|
|
10
|
+
## 运行覆盖率测试
|
|
11
|
+
|
|
12
|
+
### 使用环境变量
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
COVERAGE=true bundle exec rspec
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### 使用 Rake 任务
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# 运行测试并生成覆盖率报告
|
|
22
|
+
bundle exec rake spec:coverage
|
|
23
|
+
|
|
24
|
+
# 运行测试并验证覆盖率(如果低于 90% 会失败)
|
|
25
|
+
bundle exec rake spec:coverage:verify
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 使用脚本
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
./script/check_coverage
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 查看覆盖率报告
|
|
35
|
+
|
|
36
|
+
运行测试后,覆盖率报告会生成在 `coverage/index.html`。在浏览器中打开该文件即可查看详细的覆盖率报告。
|
|
37
|
+
|
|
38
|
+
## 覆盖率统计范围
|
|
39
|
+
|
|
40
|
+
覆盖率统计只包括 `lib/` 目录下的代码,排除:
|
|
41
|
+
- 测试文件 (`spec/`)
|
|
42
|
+
- 配置文件 (`config/`)
|
|
43
|
+
- 生成器代码 (`generators/`)
|
|
44
|
+
- 测试应用代码 (`spec/dummy/`)
|
|
45
|
+
- 其他非核心代码
|
|
46
|
+
|
|
47
|
+
## CI/CD 集成
|
|
48
|
+
|
|
49
|
+
项目已配置 GitHub Actions 工作流 (`.github/workflows/coverage.yml`),在每次推送或创建 Pull Request 时会:
|
|
50
|
+
1. 运行测试套件
|
|
51
|
+
2. 生成覆盖率报告
|
|
52
|
+
3. 验证覆盖率是否达到 90%
|
|
53
|
+
4. 上传覆盖率报告作为构建产物
|
|
54
|
+
|
|
55
|
+
## 提高覆盖率
|
|
56
|
+
|
|
57
|
+
如果覆盖率低于 90%,请:
|
|
58
|
+
1. 查看 `coverage/index.html` 了解哪些代码未被覆盖
|
|
59
|
+
2. 为未覆盖的代码添加测试用例
|
|
60
|
+
3. 特别关注边界情况和错误处理路径
|
|
61
|
+
|
|
62
|
+
## 当前覆盖率
|
|
63
|
+
|
|
64
|
+
运行 `COVERAGE=true bundle exec rspec` 后,会在终端显示当前覆盖率。
|
data/Gemfile
CHANGED
|
@@ -5,11 +5,12 @@ source "https://rubygems.org"
|
|
|
5
5
|
# Specify your gem's dependencies in activestorage_saas.gemspec
|
|
6
6
|
gemspec
|
|
7
7
|
|
|
8
|
-
gem "rails", "
|
|
8
|
+
gem "rails", "7.2.3"
|
|
9
9
|
gem "sqlite3"
|
|
10
10
|
gem "propshaft"
|
|
11
|
-
gem
|
|
11
|
+
gem 'rspec-rails', '~> 8.0', '>= 8.0.2'
|
|
12
|
+
gem 'aws-sdk-s3', '~> 1.206'
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
group :development, :test do
|
|
15
|
+
gem 'simplecov', '~> 0.22', require: false
|
|
16
|
+
end
|
data/README.md
CHANGED
|
@@ -1,33 +1,222 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ActiveStorageSaas
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
ActiveStorageSaas 是一个 Rails gem,为 ActiveStorage 提供多租户存储服务支持。它允许每个租户配置自己的存储服务,并支持动态加载不同的存储服务。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 功能特性
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- 🏢 **多租户支持**:每个租户可以配置独立的存储服务
|
|
8
|
+
- 🔄 **动态服务加载**:根据 blob 的 service_name 动态解析并加载对应的存储服务
|
|
9
|
+
- 🔌 **灵活配置**:支持通过数据库配置存储服务选项
|
|
10
|
+
- 📦 **完全兼容**:与 Rails ActiveStorage API 完全兼容,无需修改现有代码
|
|
11
|
+
- 🚀 **直接上传支持**:支持 ActiveStorage 的直接上传功能
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
## 安装
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
在 Gemfile 中添加:
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
```ruby
|
|
18
|
+
gem 'activestorage_saas', '~> 7.2.3'
|
|
19
|
+
```
|
|
14
20
|
|
|
15
|
-
|
|
21
|
+
然后运行:
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
```bash
|
|
24
|
+
bundle install
|
|
25
|
+
```
|
|
18
26
|
|
|
19
|
-
|
|
27
|
+
运行安装生成器:
|
|
20
28
|
|
|
21
|
-
|
|
29
|
+
```bash
|
|
30
|
+
rails generate active_storage_saas:install
|
|
31
|
+
```
|
|
22
32
|
|
|
23
|
-
|
|
33
|
+
这将创建必要的迁移文件。运行迁移:
|
|
24
34
|
|
|
25
|
-
|
|
35
|
+
```bash
|
|
36
|
+
rails db:migrate
|
|
37
|
+
```
|
|
26
38
|
|
|
27
|
-
##
|
|
39
|
+
## 配置
|
|
28
40
|
|
|
29
|
-
|
|
41
|
+
### 1. 数据库迁移
|
|
30
42
|
|
|
31
|
-
|
|
43
|
+
安装生成器会创建一个 `storage_service_configurations` 表,用于存储每个租户的存储服务配置。
|
|
32
44
|
|
|
33
|
-
|
|
45
|
+
### 2. 存储配置 (config/storage.yml)
|
|
46
|
+
|
|
47
|
+
在 `config/storage.yml` 中配置一个 `saas` 服务作为包装器:
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
saas:
|
|
51
|
+
service: Saas
|
|
52
|
+
default_service: local # 默认使用的存储服务
|
|
53
|
+
|
|
54
|
+
local:
|
|
55
|
+
service: Disk
|
|
56
|
+
root: <%= Rails.root.join("storage") %>
|
|
57
|
+
|
|
58
|
+
amazon:
|
|
59
|
+
service: S3
|
|
60
|
+
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
|
|
61
|
+
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
|
|
62
|
+
region: us-east-1
|
|
63
|
+
bucket: my-bucket
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 3. 应用配置 (config/application.rb 或 config/environments/*.rb)
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
Rails.application.configure do
|
|
70
|
+
# 可选:自定义服务解析器
|
|
71
|
+
# config.active_storage_saas.service_resolver = ->(blob) {
|
|
72
|
+
# StorageServiceConfiguration.from_service_name(blob.service_name)&.to_service
|
|
73
|
+
# }
|
|
74
|
+
|
|
75
|
+
# 可选:自定义服务名称转换器(用于直接上传)
|
|
76
|
+
# config.active_storage_saas.service_name_converter = ->(controller) {
|
|
77
|
+
# controller.send(:current_tenant).storage_service&.to_service_name
|
|
78
|
+
# }
|
|
79
|
+
|
|
80
|
+
# 可选:自定义服务名称验证器
|
|
81
|
+
# config.active_storage_saas.service_name_validator = ->(service_name) {
|
|
82
|
+
# StorageServiceConfiguration.valid_service_name?(service_name)
|
|
83
|
+
# }
|
|
84
|
+
|
|
85
|
+
# 可选:直接上传时额外的 blob 参数
|
|
86
|
+
# config.active_storage_saas.direct_upload_extra_blob_args = ->(controller) {
|
|
87
|
+
# { tenant: controller.send(:current_tenant) }
|
|
88
|
+
# }
|
|
89
|
+
end
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 使用方法
|
|
93
|
+
|
|
94
|
+
### 创建存储服务配置
|
|
95
|
+
|
|
96
|
+
```ruby
|
|
97
|
+
# 为租户创建存储服务配置
|
|
98
|
+
config = StorageServiceConfiguration.create!(
|
|
99
|
+
service_name: 'amazon', # 基础服务名称(在 storage.yml 中定义)
|
|
100
|
+
service_options: {
|
|
101
|
+
bucket: 'tenant-specific-bucket',
|
|
102
|
+
region: 'us-west-2'
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# 获取服务名称(格式:StorageServiceConfiguration:123)
|
|
107
|
+
service_name = config.to_service_name
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 使用存储服务
|
|
111
|
+
|
|
112
|
+
```ruby
|
|
113
|
+
# 创建 blob 时指定服务名称
|
|
114
|
+
blob = ActiveStorage::Blob.create!(
|
|
115
|
+
filename: 'example.jpg',
|
|
116
|
+
byte_size: 1024,
|
|
117
|
+
checksum: 'abc123',
|
|
118
|
+
content_type: 'image/jpeg',
|
|
119
|
+
service_name: config.to_service_name # 使用动态服务名称
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# blob.service 会自动解析为对应的存储服务实例
|
|
123
|
+
blob.service # => 返回配置的 S3 服务实例
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 在模型中关联文件
|
|
127
|
+
|
|
128
|
+
```ruby
|
|
129
|
+
class User < ApplicationRecord
|
|
130
|
+
has_one_attached :avatar
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# 上传文件时指定服务
|
|
134
|
+
user.avatar.attach(
|
|
135
|
+
io: file,
|
|
136
|
+
filename: 'avatar.jpg',
|
|
137
|
+
service_name: current_tenant.storage_config.to_service_name
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## 工作原理
|
|
142
|
+
|
|
143
|
+
### SaasService
|
|
144
|
+
|
|
145
|
+
`SaasService` 是一个包装器服务,它:
|
|
146
|
+
|
|
147
|
+
1. 接收一个 `blob` 对象
|
|
148
|
+
2. 根据 `blob.service_name` 动态解析对应的存储服务
|
|
149
|
+
3. 将所有方法调用委托给实际的存储服务
|
|
150
|
+
|
|
151
|
+
### 服务解析流程
|
|
152
|
+
|
|
153
|
+
1. 当访问 `blob.service` 时,会调用 `ActiveStorageSaas.service_resolver`
|
|
154
|
+
2. 解析器根据 `service_name` 查找对应的 `StorageServiceConfiguration`
|
|
155
|
+
3. 配置对象通过 `to_service` 方法创建实际的存储服务实例
|
|
156
|
+
4. 如果解析失败,回退到默认服务
|
|
157
|
+
|
|
158
|
+
### 服务名称格式
|
|
159
|
+
|
|
160
|
+
动态服务的名称格式为:`ClassName:ID`,例如:
|
|
161
|
+
- `StorageServiceConfiguration:1`
|
|
162
|
+
- `StorageServiceConfiguration:42`
|
|
163
|
+
|
|
164
|
+
这种格式允许从服务名称中提取配置记录的 ID。
|
|
165
|
+
|
|
166
|
+
## 高级用法
|
|
167
|
+
|
|
168
|
+
### 自定义服务解析器
|
|
169
|
+
|
|
170
|
+
```ruby
|
|
171
|
+
config.active_storage_saas.service_resolver = ->(blob) {
|
|
172
|
+
tenant = blob.record&.tenant
|
|
173
|
+
tenant&.storage_config&.to_service
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 多租户集成示例
|
|
178
|
+
|
|
179
|
+
```ruby
|
|
180
|
+
class Tenant < ApplicationRecord
|
|
181
|
+
has_one :storage_service_configuration, class_name: 'StorageServiceConfiguration'
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
class ApplicationController < ActionController::Base
|
|
185
|
+
def current_tenant
|
|
186
|
+
@current_tenant ||= Tenant.find(session[:tenant_id])
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# 在配置中
|
|
191
|
+
config.active_storage_saas.service_name_converter = ->(controller) {
|
|
192
|
+
controller.current_tenant.storage_service_configuration.to_service_name
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## 兼容性
|
|
197
|
+
|
|
198
|
+
- **Rails 版本**:7.2.3
|
|
199
|
+
- **Ruby 版本**:>= 2.6.0
|
|
200
|
+
- **ActiveStorage 版本**:7.2.3
|
|
201
|
+
|
|
202
|
+
## 开发
|
|
203
|
+
|
|
204
|
+
运行测试:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
bundle exec rspec
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
运行控制台:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
bin/console
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## 贡献
|
|
217
|
+
|
|
218
|
+
欢迎提交 Issue 和 Pull Request!
|
|
219
|
+
|
|
220
|
+
## 许可证
|
|
221
|
+
|
|
222
|
+
MIT License
|
|
@@ -30,7 +30,8 @@ module ActiveStorageSaas
|
|
|
30
30
|
def to_service
|
|
31
31
|
defined_service = ActiveStorage::Blob.services.fetch(service_name)
|
|
32
32
|
klass = defined_service.class
|
|
33
|
-
options = ActiveStorage::Blob.services.send(:configurations).fetch(service_name.to_sym)
|
|
33
|
+
options = ActiveStorage::Blob.services.send(:configurations).fetch(service_name.to_sym).deep_dup
|
|
34
|
+
options.delete(:service) if service_name == 'amazon'
|
|
34
35
|
options.deep_merge! service_options.deep_symbolize_keys
|
|
35
36
|
klass.new(**options).tap do |instance|
|
|
36
37
|
instance.instance_eval <<~RUBY
|
metadata
CHANGED
|
@@ -1,35 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activestorage_saas
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 7.
|
|
4
|
+
version: 7.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- xiaohui
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2025-12-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activestorage
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- -
|
|
17
|
+
- - '='
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 7.
|
|
20
|
-
- - "<="
|
|
21
|
-
- !ruby/object:Gem::Version
|
|
22
|
-
version: 7.0.4
|
|
19
|
+
version: 7.2.3
|
|
23
20
|
type: :runtime
|
|
24
21
|
prerelease: false
|
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
23
|
requirements:
|
|
27
|
-
- -
|
|
28
|
-
- !ruby/object:Gem::Version
|
|
29
|
-
version: 7.0.3.1
|
|
30
|
-
- - "<="
|
|
24
|
+
- - '='
|
|
31
25
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 7.
|
|
26
|
+
version: 7.2.3
|
|
33
27
|
description: Each tenant can set its own storage service, ActiveStorage service can
|
|
34
28
|
be dynamically loaded.
|
|
35
29
|
email:
|
|
@@ -38,17 +32,12 @@ executables: []
|
|
|
38
32
|
extensions: []
|
|
39
33
|
extra_rdoc_files: []
|
|
40
34
|
files:
|
|
41
|
-
-
|
|
42
|
-
- ".rubocop.yml"
|
|
35
|
+
- AGENTS.md
|
|
43
36
|
- CHANGELOG.md
|
|
37
|
+
- COVERAGE.md
|
|
44
38
|
- Gemfile
|
|
45
|
-
- Gemfile.lock
|
|
46
|
-
- Guardfile
|
|
47
39
|
- LICENSE.txt
|
|
48
40
|
- README.md
|
|
49
|
-
- Rakefile
|
|
50
|
-
- activestorage_saas.gemspec
|
|
51
|
-
- config/initializers/active_storage_saas.rb
|
|
52
41
|
- lib/active_storage/service/saas_service.rb
|
|
53
42
|
- lib/active_storage_saas.rb
|
|
54
43
|
- lib/active_storage_saas/blob_model_mixin.rb
|
|
@@ -60,7 +49,6 @@ files:
|
|
|
60
49
|
- lib/generators/active_storage_saas/install/USAGE
|
|
61
50
|
- lib/generators/active_storage_saas/install/install_generator.rb
|
|
62
51
|
- lib/generators/active_storage_saas/install/templates/config/initializers/active_storage_saas.rb
|
|
63
|
-
- sig/activestorage_saas.rbs
|
|
64
52
|
homepage: https://github.com/xiaohui-zhangxh/activestorage_saas
|
|
65
53
|
licenses:
|
|
66
54
|
- MIT
|
|
@@ -83,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
83
71
|
- !ruby/object:Gem::Version
|
|
84
72
|
version: '0'
|
|
85
73
|
requirements: []
|
|
86
|
-
rubygems_version: 3.
|
|
74
|
+
rubygems_version: 3.5.16
|
|
87
75
|
signing_key:
|
|
88
76
|
specification_version: 4
|
|
89
77
|
summary: Wraps multi-tenant storage services as ActiveStorage service
|
data/.rspec
DELETED
data/.rubocop.yml
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
AllCops:
|
|
2
|
-
TargetRubyVersion: 2.6
|
|
3
|
-
NewCops: enable
|
|
4
|
-
Style/StringLiterals:
|
|
5
|
-
Enabled: true
|
|
6
|
-
EnforcedStyle: single_quotes
|
|
7
|
-
|
|
8
|
-
Style/StringLiteralsInInterpolation:
|
|
9
|
-
Enabled: true
|
|
10
|
-
EnforcedStyle: double_quotes
|
|
11
|
-
|
|
12
|
-
Layout/LineLength:
|
|
13
|
-
Max: 120
|
|
14
|
-
|
|
15
|
-
Layout/IndentationConsistency:
|
|
16
|
-
Enabled: true
|
|
17
|
-
EnforcedStyle: indented_internal_methods
|
data/Gemfile.lock
DELETED
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
PATH
|
|
2
|
-
remote: .
|
|
3
|
-
specs:
|
|
4
|
-
activestorage_saas (7.0.4)
|
|
5
|
-
activestorage (>= 7.0.3.1, <= 7.0.4)
|
|
6
|
-
|
|
7
|
-
GEM
|
|
8
|
-
remote: https://rubygems.org/
|
|
9
|
-
specs:
|
|
10
|
-
actioncable (7.0.4)
|
|
11
|
-
actionpack (= 7.0.4)
|
|
12
|
-
activesupport (= 7.0.4)
|
|
13
|
-
nio4r (~> 2.0)
|
|
14
|
-
websocket-driver (>= 0.6.1)
|
|
15
|
-
actionmailbox (7.0.4)
|
|
16
|
-
actionpack (= 7.0.4)
|
|
17
|
-
activejob (= 7.0.4)
|
|
18
|
-
activerecord (= 7.0.4)
|
|
19
|
-
activestorage (= 7.0.4)
|
|
20
|
-
activesupport (= 7.0.4)
|
|
21
|
-
mail (>= 2.7.1)
|
|
22
|
-
net-imap
|
|
23
|
-
net-pop
|
|
24
|
-
net-smtp
|
|
25
|
-
actionmailer (7.0.4)
|
|
26
|
-
actionpack (= 7.0.4)
|
|
27
|
-
actionview (= 7.0.4)
|
|
28
|
-
activejob (= 7.0.4)
|
|
29
|
-
activesupport (= 7.0.4)
|
|
30
|
-
mail (~> 2.5, >= 2.5.4)
|
|
31
|
-
net-imap
|
|
32
|
-
net-pop
|
|
33
|
-
net-smtp
|
|
34
|
-
rails-dom-testing (~> 2.0)
|
|
35
|
-
actionpack (7.0.4)
|
|
36
|
-
actionview (= 7.0.4)
|
|
37
|
-
activesupport (= 7.0.4)
|
|
38
|
-
rack (~> 2.0, >= 2.2.0)
|
|
39
|
-
rack-test (>= 0.6.3)
|
|
40
|
-
rails-dom-testing (~> 2.0)
|
|
41
|
-
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
|
42
|
-
actiontext (7.0.4)
|
|
43
|
-
actionpack (= 7.0.4)
|
|
44
|
-
activerecord (= 7.0.4)
|
|
45
|
-
activestorage (= 7.0.4)
|
|
46
|
-
activesupport (= 7.0.4)
|
|
47
|
-
globalid (>= 0.6.0)
|
|
48
|
-
nokogiri (>= 1.8.5)
|
|
49
|
-
actionview (7.0.4)
|
|
50
|
-
activesupport (= 7.0.4)
|
|
51
|
-
builder (~> 3.1)
|
|
52
|
-
erubi (~> 1.4)
|
|
53
|
-
rails-dom-testing (~> 2.0)
|
|
54
|
-
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
|
55
|
-
activejob (7.0.4)
|
|
56
|
-
activesupport (= 7.0.4)
|
|
57
|
-
globalid (>= 0.3.6)
|
|
58
|
-
activemodel (7.0.4)
|
|
59
|
-
activesupport (= 7.0.4)
|
|
60
|
-
activerecord (7.0.4)
|
|
61
|
-
activemodel (= 7.0.4)
|
|
62
|
-
activesupport (= 7.0.4)
|
|
63
|
-
activestorage (7.0.4)
|
|
64
|
-
actionpack (= 7.0.4)
|
|
65
|
-
activejob (= 7.0.4)
|
|
66
|
-
activerecord (= 7.0.4)
|
|
67
|
-
activesupport (= 7.0.4)
|
|
68
|
-
marcel (~> 1.0)
|
|
69
|
-
mini_mime (>= 1.1.0)
|
|
70
|
-
activesupport (7.0.4)
|
|
71
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
72
|
-
i18n (>= 1.6, < 2)
|
|
73
|
-
minitest (>= 5.1)
|
|
74
|
-
tzinfo (~> 2.0)
|
|
75
|
-
aws-eventstream (1.2.0)
|
|
76
|
-
aws-partitions (1.664.0)
|
|
77
|
-
aws-sdk-core (3.168.1)
|
|
78
|
-
aws-eventstream (~> 1, >= 1.0.2)
|
|
79
|
-
aws-partitions (~> 1, >= 1.651.0)
|
|
80
|
-
aws-sigv4 (~> 1.5)
|
|
81
|
-
jmespath (~> 1, >= 1.6.1)
|
|
82
|
-
aws-sdk-kms (1.59.0)
|
|
83
|
-
aws-sdk-core (~> 3, >= 3.165.0)
|
|
84
|
-
aws-sigv4 (~> 1.1)
|
|
85
|
-
aws-sdk-s3 (1.117.1)
|
|
86
|
-
aws-sdk-core (~> 3, >= 3.165.0)
|
|
87
|
-
aws-sdk-kms (~> 1)
|
|
88
|
-
aws-sigv4 (~> 1.4)
|
|
89
|
-
aws-sigv4 (1.5.2)
|
|
90
|
-
aws-eventstream (~> 1, >= 1.0.2)
|
|
91
|
-
builder (3.2.4)
|
|
92
|
-
coderay (1.1.3)
|
|
93
|
-
concurrent-ruby (1.1.10)
|
|
94
|
-
crass (1.0.6)
|
|
95
|
-
diff-lcs (1.5.0)
|
|
96
|
-
erubi (1.11.0)
|
|
97
|
-
ffi (1.15.5)
|
|
98
|
-
formatador (1.1.0)
|
|
99
|
-
globalid (1.0.0)
|
|
100
|
-
activesupport (>= 5.0)
|
|
101
|
-
guard (2.18.0)
|
|
102
|
-
formatador (>= 0.2.4)
|
|
103
|
-
listen (>= 2.7, < 4.0)
|
|
104
|
-
lumberjack (>= 1.0.12, < 2.0)
|
|
105
|
-
nenv (~> 0.1)
|
|
106
|
-
notiffany (~> 0.0)
|
|
107
|
-
pry (>= 0.13.0)
|
|
108
|
-
shellany (~> 0.0)
|
|
109
|
-
thor (>= 0.18.1)
|
|
110
|
-
guard-compat (1.2.1)
|
|
111
|
-
guard-rspec (4.7.3)
|
|
112
|
-
guard (~> 2.1)
|
|
113
|
-
guard-compat (~> 1.1)
|
|
114
|
-
rspec (>= 2.99.0, < 4.0)
|
|
115
|
-
i18n (1.12.0)
|
|
116
|
-
concurrent-ruby (~> 1.0)
|
|
117
|
-
jmespath (1.6.1)
|
|
118
|
-
listen (3.7.1)
|
|
119
|
-
rb-fsevent (~> 0.10, >= 0.10.3)
|
|
120
|
-
rb-inotify (~> 0.9, >= 0.9.10)
|
|
121
|
-
loofah (2.19.0)
|
|
122
|
-
crass (~> 1.0.2)
|
|
123
|
-
nokogiri (>= 1.5.9)
|
|
124
|
-
lumberjack (1.2.8)
|
|
125
|
-
mail (2.7.1)
|
|
126
|
-
mini_mime (>= 0.1.1)
|
|
127
|
-
marcel (1.0.2)
|
|
128
|
-
method_source (1.0.0)
|
|
129
|
-
mini_mime (1.1.2)
|
|
130
|
-
mini_portile2 (2.8.0)
|
|
131
|
-
minitest (5.16.3)
|
|
132
|
-
nenv (0.3.0)
|
|
133
|
-
net-imap (0.3.1)
|
|
134
|
-
net-protocol
|
|
135
|
-
net-pop (0.1.2)
|
|
136
|
-
net-protocol
|
|
137
|
-
net-protocol (0.1.3)
|
|
138
|
-
timeout
|
|
139
|
-
net-smtp (0.3.3)
|
|
140
|
-
net-protocol
|
|
141
|
-
nio4r (2.5.8)
|
|
142
|
-
nokogiri (1.13.9)
|
|
143
|
-
mini_portile2 (~> 2.8.0)
|
|
144
|
-
racc (~> 1.4)
|
|
145
|
-
notiffany (0.1.3)
|
|
146
|
-
nenv (~> 0.1)
|
|
147
|
-
shellany (~> 0.0)
|
|
148
|
-
propshaft (0.6.4)
|
|
149
|
-
actionpack (>= 7.0.0)
|
|
150
|
-
activesupport (>= 7.0.0)
|
|
151
|
-
rack
|
|
152
|
-
railties (>= 7.0.0)
|
|
153
|
-
pry (0.14.1)
|
|
154
|
-
coderay (~> 1.1)
|
|
155
|
-
method_source (~> 1.0)
|
|
156
|
-
racc (1.6.0)
|
|
157
|
-
rack (2.2.4)
|
|
158
|
-
rack-test (2.0.2)
|
|
159
|
-
rack (>= 1.3)
|
|
160
|
-
rails (7.0.4)
|
|
161
|
-
actioncable (= 7.0.4)
|
|
162
|
-
actionmailbox (= 7.0.4)
|
|
163
|
-
actionmailer (= 7.0.4)
|
|
164
|
-
actionpack (= 7.0.4)
|
|
165
|
-
actiontext (= 7.0.4)
|
|
166
|
-
actionview (= 7.0.4)
|
|
167
|
-
activejob (= 7.0.4)
|
|
168
|
-
activemodel (= 7.0.4)
|
|
169
|
-
activerecord (= 7.0.4)
|
|
170
|
-
activestorage (= 7.0.4)
|
|
171
|
-
activesupport (= 7.0.4)
|
|
172
|
-
bundler (>= 1.15.0)
|
|
173
|
-
railties (= 7.0.4)
|
|
174
|
-
rails-dom-testing (2.0.3)
|
|
175
|
-
activesupport (>= 4.2.0)
|
|
176
|
-
nokogiri (>= 1.6)
|
|
177
|
-
rails-html-sanitizer (1.4.3)
|
|
178
|
-
loofah (~> 2.3)
|
|
179
|
-
railties (7.0.4)
|
|
180
|
-
actionpack (= 7.0.4)
|
|
181
|
-
activesupport (= 7.0.4)
|
|
182
|
-
method_source
|
|
183
|
-
rake (>= 12.2)
|
|
184
|
-
thor (~> 1.0)
|
|
185
|
-
zeitwerk (~> 2.5)
|
|
186
|
-
rake (13.0.6)
|
|
187
|
-
rb-fsevent (0.11.2)
|
|
188
|
-
rb-inotify (0.10.1)
|
|
189
|
-
ffi (~> 1.0)
|
|
190
|
-
rspec (3.12.0)
|
|
191
|
-
rspec-core (~> 3.12.0)
|
|
192
|
-
rspec-expectations (~> 3.12.0)
|
|
193
|
-
rspec-mocks (~> 3.12.0)
|
|
194
|
-
rspec-core (3.12.0)
|
|
195
|
-
rspec-support (~> 3.12.0)
|
|
196
|
-
rspec-expectations (3.12.0)
|
|
197
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
198
|
-
rspec-support (~> 3.12.0)
|
|
199
|
-
rspec-mocks (3.12.0)
|
|
200
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
201
|
-
rspec-support (~> 3.12.0)
|
|
202
|
-
rspec-rails (5.1.2)
|
|
203
|
-
actionpack (>= 5.2)
|
|
204
|
-
activesupport (>= 5.2)
|
|
205
|
-
railties (>= 5.2)
|
|
206
|
-
rspec-core (~> 3.10)
|
|
207
|
-
rspec-expectations (~> 3.10)
|
|
208
|
-
rspec-mocks (~> 3.10)
|
|
209
|
-
rspec-support (~> 3.10)
|
|
210
|
-
rspec-support (3.12.0)
|
|
211
|
-
shellany (0.0.1)
|
|
212
|
-
sqlite3 (1.5.4)
|
|
213
|
-
mini_portile2 (~> 2.8.0)
|
|
214
|
-
thor (1.2.1)
|
|
215
|
-
timeout (0.3.0)
|
|
216
|
-
tzinfo (2.0.5)
|
|
217
|
-
concurrent-ruby (~> 1.0)
|
|
218
|
-
websocket-driver (0.7.5)
|
|
219
|
-
websocket-extensions (>= 0.1.0)
|
|
220
|
-
websocket-extensions (0.1.5)
|
|
221
|
-
zeitwerk (2.6.6)
|
|
222
|
-
|
|
223
|
-
PLATFORMS
|
|
224
|
-
ruby
|
|
225
|
-
|
|
226
|
-
DEPENDENCIES
|
|
227
|
-
activestorage_saas!
|
|
228
|
-
aws-sdk-s3 (~> 1.114)
|
|
229
|
-
guard-rspec (~> 4.7)
|
|
230
|
-
propshaft
|
|
231
|
-
rails (~> 7.0)
|
|
232
|
-
rspec-rails (~> 5.1)
|
|
233
|
-
sqlite3
|
|
234
|
-
|
|
235
|
-
BUNDLED WITH
|
|
236
|
-
2.3.17
|
data/Guardfile
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# A sample Guardfile
|
|
2
|
-
# More info at https://github.com/guard/guard#readme
|
|
3
|
-
|
|
4
|
-
## Uncomment and set this to only include directories you want to watch
|
|
5
|
-
# directories %w(app lib config test spec features) \
|
|
6
|
-
# .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
|
7
|
-
|
|
8
|
-
## Note: if you are using the `directories` clause above and you are not
|
|
9
|
-
## watching the project directory ('.'), then you will want to move
|
|
10
|
-
## the Guardfile to a watched dir and symlink it back, e.g.
|
|
11
|
-
#
|
|
12
|
-
# $ mkdir config
|
|
13
|
-
# $ mv Guardfile config/
|
|
14
|
-
# $ ln -s config/Guardfile .
|
|
15
|
-
#
|
|
16
|
-
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
|
17
|
-
|
|
18
|
-
# Note: The cmd option is now required due to the increasing number of ways
|
|
19
|
-
# rspec may be run, below are examples of the most common uses.
|
|
20
|
-
# * bundler: 'bundle exec rspec'
|
|
21
|
-
# * bundler binstubs: 'bin/rspec'
|
|
22
|
-
# * spring: 'bin/rspec' (This will use spring if running and you have
|
|
23
|
-
# installed the spring binstubs per the docs)
|
|
24
|
-
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
|
25
|
-
# * 'just' rspec: 'rspec'
|
|
26
|
-
|
|
27
|
-
guard :rspec, cmd: "bundle exec rspec" do
|
|
28
|
-
require "guard/rspec/dsl"
|
|
29
|
-
dsl = Guard::RSpec::Dsl.new(self)
|
|
30
|
-
|
|
31
|
-
# Feel free to open issues for suggestions and improvements
|
|
32
|
-
|
|
33
|
-
# RSpec files
|
|
34
|
-
rspec = dsl.rspec
|
|
35
|
-
watch(rspec.spec_helper) { rspec.spec_dir }
|
|
36
|
-
watch(rspec.spec_support) { rspec.spec_dir }
|
|
37
|
-
watch(rspec.spec_files)
|
|
38
|
-
|
|
39
|
-
# Ruby files
|
|
40
|
-
ruby = dsl.ruby
|
|
41
|
-
dsl.watch_spec_files_for(ruby.lib_files)
|
|
42
|
-
end
|
data/Rakefile
DELETED
data/activestorage_saas.gemspec
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
Gem::Specification.new do |spec|
|
|
4
|
-
spec.name = "activestorage_saas"
|
|
5
|
-
spec.version = "7.0.4"
|
|
6
|
-
spec.authors = ["xiaohui"]
|
|
7
|
-
spec.email = ["xiaohui@tanmer.com"]
|
|
8
|
-
|
|
9
|
-
spec.summary = "Wraps multi-tenant storage services as ActiveStorage service"
|
|
10
|
-
spec.description = "Each tenant can set its own storage service, ActiveStorage service can be dynamically loaded."
|
|
11
|
-
spec.homepage = "https://github.com/xiaohui-zhangxh/activestorage_saas"
|
|
12
|
-
spec.license = "MIT"
|
|
13
|
-
spec.required_ruby_version = ">= 2.6.0"
|
|
14
|
-
|
|
15
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
|
16
|
-
spec.metadata["source_code_uri"] = spec.homepage
|
|
17
|
-
spec.metadata["changelog_uri"] = "#{spec.homepage}/CHANGELOG.md"
|
|
18
|
-
|
|
19
|
-
# Specify which files should be added to the gem when it is released.
|
|
20
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
21
|
-
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
22
|
-
`git ls-files -z`.split("\x0").reject do |f|
|
|
23
|
-
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
spec.require_paths = ["lib"]
|
|
28
|
-
|
|
29
|
-
spec.add_dependency "activestorage", '>=7.0.3.1', '<= 7.0.4'
|
|
30
|
-
end
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
Rails.application.configure do
|
|
2
|
-
# config.active_storage_saas.service_resolver = ->(blob) { StorageServiceConfiguration.from_service_name(blob.service_name)&.to_service }
|
|
3
|
-
# config.active_storage_saas.service_name_converter = ->(controller) { controller.send(:current_tenant).storage_service&.to_service_name }
|
|
4
|
-
# config.active_storage_saas.service_name_validator = ->(service_name) { StorageServiceConfiguration.valid_service_name?(service_name) }
|
|
5
|
-
# config.active_storage_saas.direct_upload_extra_blob_args = ->(controller) { { tenant: controller.send(:current_tenant) } }
|
|
6
|
-
end
|
data/sig/activestorage_saas.rbs
DELETED