2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Rails】Active Storage + S3 + Active JobでGoogle Cloud Visionセーフサーチ

Last updated at Posted at 2019-05-30

個人開発のWebアプリ「まちかどルート」v6.0rc6への実装メモです。

Amazon S3に画像をダイレクトアップロード

Railsガイドをもとに実装しました。

セーフサーチを実装

前回の記事のとおりです。

【Rails】Active Storage環境下でGoogle Cloud Visionのセーフサーチを実装

S3アップロード画像のパブリックURLを取得

こちらの記事を参考にしました。

Rails ActiveStorage で PUBLIC な URL を表示する

セーフサーチを非同期処理化

※controllerのコードは省略します

model

post.rb
    has_one_attached :image
    after_commit :annotate_self, on: [:create, :update]

    def annotate_self
        if image.attached?
            ImageAnnotateJob.set(wait: 10.second).perform_later(self)
        end
    end

postの新規投稿もしくは編集のときに画像imageが添付されていたらImageAnnotateJobというActive Jobのキューを走らせます。10秒後に走らすようセットした理由は、Amazon S3へのアップロード完了までのタイムラグが発生するかなと思ったからです。

job

image_annotate_job.rb
class ImageAnnotateJob < ApplicationJob
  queue_as :second

  def perform(target)
 
    tempfile = target.image.attachment.service.send(:object_for, target.image.key).public_url

    require "google/cloud/vision"
    image_annotator = Google::Cloud::Vision::ImageAnnotator.new
    response = image_annotator.safe_search_detection image: tempfile
    # 注1
    response.responses.each do |res|
    safe_search = res.safe_search_annotation.to_h
      if safe_search.values.include?(:VERY_LIKELY) || safe_search.values.include?(:LIKELY)
        target.destroy
        return
      end
    end

  end

end

いったんtempfileにS3アップロード画像のパブリックURLを格納。それをGoogle Cloud Visionのセーフサーチにかけます。このコードはすべてActive Jobによってバックグラウンド(非同期)処理されます。もし不適切な画像と判断されれば投稿そのものを削除する流れです。

注1: 2022/05/19
初出の書き方だとAPIの仕様が変わったため正常動作しなくなったのでifendの部分をこのように書き換えたら動くようになりました。to_hメソッドを使っているのがポイントです。

Sidekiq

config\sidekiq.yml
:concurrency: 5
:queues:
  - [default, 7]
  - [second, 5]

じぶんはActive JobのライブラリとしてSidekiqを使用しています。上記image_annotate_job.rbqueue_as :secondによってキューが処理される優先順位を設定しました。

あとがき

駆け足ですが以上です。Google Cloud Visionのセーフサーチは高精度ですがレスポンスに1~2秒ほど要するため、そのぶん前回の記事のような同期処理だと投稿完了までにユーザーを待たせてしまううえ、サーバーサイドに負荷がかかります。今回の記事はそれらの課題を解決するものとなります。

また、苦労したのがS3アップロード画像のパブリックURLを取得する部分でした。url_forrails_blob_urlといったActive Storageのメソッドを使うと時限的なものorリダイレクトされるURLしか取得できずセーフサーチにかけても「そんな画像はありませんよ」と言われてしまいます。

というわけで試行錯誤を経たおかげでよりレスポンス性とセキュリティ性を兼ね備えた画像投稿機能を実装できました。

補足: Rails 6.0ではこちらもご覧ください
https://qiita.com/west2538/items/f932978e79220b880693

gemのv1.0.0に対応した記事を書きました
https://qiita.com/west2538/items/89bdbc4a935d12a65202

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?