Active::Storageの画像をJavaScript/Ajaxで表示する方法

  • このエントリーをはてなブックマークに追加

こんにちはRyujiです。

Active::Storageめっちゃ便利ですよね!圧倒的に少ないコードで画像表示を実装することができました。

ただし、新機能なだけに文献が少ない!今回は詰まった非同期での画像表示について書きます。

今回やりたいこと

Rails 5.2でajaxで送られてきたリクエストに対して、Active::storageの画像付きデータをjbuilderで返送して、クライアントで表示したい。

Active::Storageとは?

そもそもActive::Storageって何ですか?って人

Active::StorageはRails 5.2から使用できるようになった、画像アップロードできる機能です。railsに標準付属である上に、非常に簡単に実装できます。

他の実装方法としては、carrierwaveなどが挙げられます。

Active::Storageの基本的な使い方

基本的にRails guideがとてもわかりやすいです。

https://railsguides.jp/active_storage_overview.html

諸々設定した後、アソシエーションのようにattachして、

class Item < ApplicationRecord
  has_many_attached :images  # 複数画像の場合
end
def create
  @item = Item.new(item_params)
end

private
def item_params
  params.permit(:name, :price, images: [])  # 複数画像の場合
end

Viewで呼び出すだけ!

= image_tag @item.images[0]

jbuilderでActive::Storageの画像を渡す

今回は非同期で表示したいので、先ほどの

= image_tag @item.images[0]

みたいな書き方は使えません。

その為、以下のような実装方法になるかと思います。

ajaxで通信します。

$.ajax({
  method: "GET",
  url: "./test",
  dataType: "json",
}).done(function(data){
  data["items"].forEach(function(item){
    $(".main_block__item").append(item.image)
  });
})

コントローラの設定はこんな感じ

def test
  @items = Item.all
  respond_to do |format|
    format.json {}
  end 
end

そしてjbuilderの設定

json.set! :items do
  json.array! @items do |item|
    json.id item.id
    json.name item.name
    json.price item.price
    json.image item.images[0]
  end
end

とりあえず画像一枚jbuilderで送信します。

これじゃダメなんです!!

実は item.images[0] で出力されるurlと、

通常のrubyで出力する方法= image_tag @item.images[0]で出力されるurlは

異なります。

Active::Storageとimage_tagがうまいこと裏でやってくれているんですよね。

= image_tag @item.images[0]で出力されるurl

<img src="http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBldz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--8379cabd9a6ac222ffa18e561d4eb900110fe265/-E3-82-B9-E3-82-AF-E3-83-AA-E3-83-BC-E3-83-B3-E3-82-B7-E3-83-A7-E3-83-83-E3-83-88-202019-07-12-2011.39.07.png">

こんなのを動的に作り出さなければなりません。

url_forを使用して画像を表示する

いや動的に複雑なurlを同じように生成するのって困難ですよね!

そんなあなたに救世主がいました。url_forです。

使い方は簡単です。

jbuilderを書き直します。

json.set! :items do
  json.array! @items do |item|
    json.id item.id
    json.name item.name
    json.price item.price
    json.image url_for(item.images[0])
  end
end

url_forは実は、Rails Guideの5.添付ファイルへのリンクに説明されていました。

(Rails Guide読んでも、最初はこんな使い方できるって気づかなかったよ、、、)

url_forを使うと5分間有効な永続リンクが作成されるんですよね。それでjavascriptでも操作して表示することが可能になります。

副産物として、一回表示した画像は早く表示できるようになりました!

まとめ

非同期で画像表示するときはurl_forを使いましょう。

他の方法があるなら教えて欲しいです!

Active::Storageは超便利・超簡単ですけど、割と新機能だから文献が少ないのが難しいところでした。

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

スポンサードリンク

コメントを残す

*