Reputation: 2246
Would want to add the url for the attached file, while responding to get request for a nested resource (say Document) for parent resource (say Person).
# people_controller.rb
def show
render json: @person, include: [{document: {include: :files}}]
end
# returns
# {"id":1,"full_name":"James Bond","document":{"id":12,"files":[{"id":12,"name":"files","record_type":"Document","record_id":689,"blob_id":18,}]}
# MODELS
# person.rb
class Person < ApplicationRecord
has_one :document, class_name: "Document", foreign_key: :document_id
end
# document.rb
class Document < ApplicationRecord
has_many_attached :files
end
Issue being, I want to show the file or provide a link to the file in a React frontend setup, which doesn't have helper methods like url_for. As pointed out here.
Any help, would be greatly appreciated.
Upvotes: 5
Views: 5320
Reputation: 52478
All credit to @JuanCarlosGamaRoa for this, which worked for me.
I had a app where each 'product' has one 'main_image' attachment.
# app/models/product.rb
def main_image_url
if self.main_image.attached?
Rails.application.routes.url_helpers.rails_blob_path(self.main_image, only_path: true)
else
nil
end
end
# app/views/products/_product.json.jbuilder
json.extract! product, :id, :price, :created_at, :updated_at, :main_image_url
json.url product_url(product, format: :json)
Upvotes: 0
Reputation: 21
class Meal < ApplicationRecord
has_many_attached :photos
end
class MealsController < ApplicationController
def index
render json: current_user.meals.map { |meal| meal_json(meal) }
end
def show
render json: meal_json(current_user.meals.find!(params[:id]))
end
private
def meal_json(meal)
meal.as_json.merge(photos: meal.photos.map { |photo| url_for(photo) })
end
end
Upvotes: 1
Reputation: 61
What I have done is create this method in the model
def logo_url
if self.logo.attached?
Rails.application.routes.url_helpers.rails_blob_path(self.logo, only_path: true)
else
nil
end
end
To add logo_url to your response json you can add methods
.
render json: @person, methods: :logo_url
that is explained in the official guides =)
Upvotes: 6
Reputation: 2246
After digging in the source code of Active Storage, I found out model methods which exposed method called: service_url, which returns a short lived link to the attachment files.
Then this answer helped include the method inside the controller response json.
so, in order to achieve my required output I had to do
render json: @person, include: [{document: {include: {files: {include: {attachments: {include: {blob: {methods: :service_url}}}}} }}]
Upvotes: 5