Active Storageで画像をパブリックにする方法
こんにちは!!
GWに有休を使って長期休みにしておらず、普通に働いています...(休みたかった
今回はActive Storageで画像をパブリックにする方法とどのように実装されているかについて記事にしました。
前提としては以下です。
- Ruby : 3.4.X
- Rails : 8.0.X
- ストレージはAWSのS3
- CDNで画像をキャッシュしたいため、画像をパブリックにしつつ生成されるURLを固定にしたい
- すでにプライベートな画像をActive Storageを用いて保存している
Acitve Storageで画像をパブリックにする方法
まずはRailsガイドにもある通りサービスを設定します。
+ public:
+ service: S3
+ region: <%= ENV['AWS_REGION'] %>
+ bucket: <%= ENV['PUBLIC_BUCKET_NAME'] %>
+ public: true
+
private:
service: S3
region: <%= ENV['AWS_REGION'] %>
bucket: <%= ENV['PRIVATE_BUCKET_NAME'] %>
public: true
のサービスを分けることで利用するバケットを変え、プライベート用のS3のバケットとパブリック用のS3のバケットを分けます。
そしてActiveRecordのmodelで↑で追加したサービスを指定します。
class Hoge
- has_one_attached :image
+ has_one_attached :image, service: :public
end
ちなみにパブリックにする画像は明示的に指定する状態が望ましいと思う場合はconfigファイルに private
を指定しておくといいかもです!!
( has_one_attached
でserviceを指定しなければ private
が選択される
+ config.active_storage.service = :private
これでパブリックにできるため、URLが固定になります!!
実装見ていく
前提としてAWS S3を使っています。
以下のclassを用います。
initialize
を見ると以下のような記述があります。
public?
は継承元で定義されており、yamlで指定しているものが入ってそうです。
では戻って @upload_options[:acl]
に public-read
がついているとどうなるのか見ましょう。
ActiveStorage:Blobのインスタンスに upload
関数があります。
AcitveStorage::Blobのインスタンスに生えている service
は先ほど見たS3Serviceです。
そのS3Serviceの upload
関数は以下です。
**upload_option
を渡していますね。
object_for
で返ってくるのはaws-sdk-rubyで宣言されているインスタンスです。
Aws::S3::Objectには put
関数が生えています。
pub_object
関数は以下です。
requestを送る際にoptionsを渡していることがわかります。
コメントアウトでも acl: "public-read"
の説明があります。
AWSのドキュメントにも public-read
の説明があり、readのみ全公開されていることが分かります。
AWS S3にはアクセスの制御の仕方が複数あり、Active Storageはその中でもACLを使っていそうです。
S3のACLを使うならバケットポリシーなどで制限をかけたくなります。(ACLで検索すると非推奨という記事が散見される)
ここからは憶測ですが、Active StorageはS3のオブジェクトごとにアクセスをコントロールしたいためACLを使っているのかなと思います。
まとめ
Active Storageでパブリックアクセスを許可する方法とその実装を追ってみました。
AWS S3にはさまざまなアクセス制御の方法があり、Active Storageはその中でもACLを使って制御していることが分かりました。
以上です、よきRailsライフを..!!
Discussion