Alexander Kireyev
Alexander Kireyev

Reputation: 10825

How to get url of Active Storage image

I want to get list of records with attached images as a links or files by api.

I have a simple model:

class Category < ApplicationRecord
  has_one_attached :image
  validates :name, presence: true, uniqueness: true
end

And next action:

  def index
    @categories = Category.all.with_attached_image

    render json: @categories.to_json(include: { image_attachment: { include: :blob } })
  end

That's the only way I can get image object.

And I see next results:

{"id":4,"name":"Cat1","description":""},
{"id":1,"name":"Cat2","description":"","image_attachment":
  {"id":8,"name":"image","record_type":"Category","record_id":1,"blob_id":8,"created_at":"2018-06-09T13:45:40.512Z","blob":
  {"id":8,"key":"3upLhH4vGxZEhhf3TaAjDiCW","filename":"Screen Shot 2018-06-09 at 20.43.24.png","content_type":"image/png","metadata":
  {"identified":true,"width":424,"height":361,"analyzed":true},"byte_size":337347,"checksum":"Y58zbYUVOlZRadx81wxOJA==","created_at":"2018-06-09T13:45:40.482Z"}}},
...

I can see filename here. But files lives in different folders and it doesn't seems for me like a convenient way to get and link to the file.

I couldn't find any information about this.

Updated

Accordin to iGian solution my code become:

  def index
    @categories = Category.all.with_attached_image

    render json: @categories.map { |category|
      category.as_json.merge({ image: url_for(category.image) })
    }
  end

Upvotes: 37

Views: 64364

Answers (8)

Umar Farooq
Umar Farooq

Reputation: 489

We can just use

<%= image_tag url_for(user.avatar) %>

to display any image from Turbo Stream.

For example, showing real-time post notifications with Turbo Stream, we can use following code for post partial

<!-- app/views/notifications/_post.html.erb -->
<div class="flex items-start space-x-4 bg-white p-4 rounded-lg shadow-md">
  <% if notification.item.user.avatar.attached? %>
    <%= image_tag url_for(notification.item.user.avatar), class: 'w-10 h-10 rounded-full' %>
  <% end %>
  <div class="flex-grow">
    <p class="text-gray-700">
      <span class="font-semibold text-gray-900"><%= notification.item.user.username %></span>
      added a new post:
    </p>
    <p class="mt-1 text-gray-600">
      <%= link_to notification.item.content.truncate(100), notification.item, class: "underline text-blue-600 hover:text-blue-800 font-medium" %>
    </p>
    <p class="text-sm text-gray-400 mt-1">
      <%= time_ago_in_words(notification.item.created_at) %> ago
    </p>
  </div>
  <% if notification.item.image.attached? %>
    <div class="flex-shrink-0">
      <%= image_tag url_for(notification.item.image), class: 'w-20 h-20 object-cover rounded-lg' %>
    </div>
  <% end %>
</div>

Upvotes: 0

glinda93
glinda93

Reputation: 8459

Here is how I use active storage with AWS S3 bucket and attach image urls with domain to JSON response:

activerecord


class Imageable < ApplicationRecord
  has_many_attached :images

  def image_urls
    images.map(&:service_url)
  end

  def attributes
    super.merge({
                  image_urls: image_urls
                })
  end
end

application_controller.rb

class ApplicationController < ActionController::Base
  before_action :set_active_storage_current_host
  
  def set_active_storage_current_host
    ActiveStorage::Current.host = request.base_url
  end
end

imageables_controller.rb

class ImageablesController < ApplicationController
  include ImageablesHelper
  def update
    imageable = find_or_create
    imageable.update imageables_params
    imageable.images.purge
    imageable.images.attach imageable_params[:images]
    imageable.save!
    render json: imageable
  end
end

imageables_helper.rb

module ImageablesHelper
  def imageables_params
    params.require(:imageable).permit(:other_attributes, images: [])
  end
end

Upvotes: 1

Ananthu S Kumar
Ananthu S Kumar

Reputation: 171

If you want get this url in front end, try this :

<%= url_for(category.image) %>

and for displaying image :

<%= image_tag url_for(category.image) %>

Upvotes: 2

Eduardo Cruz
Eduardo Cruz

Reputation: 91

This works for me with multiple images

class PostSerializer < ActiveModel::Serializer
  include Rails.application.routes.url_helpers

  attributes :id, :content , :images

  def images
    images = object.images.map do |image|
      rails_blob_path(image , only_path: true) if object.images.attached?
    end
  end
end

Upvotes: 5

AnthonyM.
AnthonyM.

Reputation: 369

Also try @object.image.service_url. This will give you the url where the image is saved. I.E. url to amazon s3 storage.

Upvotes: 19

AnthonyM.
AnthonyM.

Reputation: 369

I got it to work with rails_blob_url(@object.image). Notice I am calling _url not _path with the helper.

Upvotes: 2

Ankit Varshney
Ankit Varshney

Reputation: 101

Please follow this for fetching images( in case if you are using has_many_attached)

Model.images.map{|img| ({ image: url_for(img) })}

Upvotes: 4

iGian
iGian

Reputation: 11183

For my User which has_one_attached :avatar I can get the url in my views with <%= image_tag url_for(user.avatar) %>. So, in controller I would use just url_for(user.avatar)

For Category which has_one_attached :image:

url_for(category.image)

Upvotes: 53

Related Questions