Search code examples
ruby-on-railsamazon-web-servicesamazon-s3ruby-on-rails-5rails-activestorage

I am missing the AWS URL for a Ruby on Rails model when I include it in the GET request of an associated model


I am fairly new to coding and I am trying to set up a Rails 5 backend for a new application. I have created a many-to-many relationship between two models, Projects and Skills, that both use S3 storage from Amazon Web Services to attach an image.

I can make a GET request for each model and see working image URLs in the json response, but when I try to include, say, Skills inside the GET request for a Project, I receive the Skill without the image URL.

Here is some sample json I get from calling the Skill "HTML":

created_at: "2019-12-06T04:27:52.537Z"
id: 4
image: (working URL for skill image)
name: "HTML"
updated_at: "2019-12-06T04:27:52.540Z"

And here is json for a Project with the Skill "HTML" nested inside it:

created_at: "2019-12-07T15:11:32.592Z"
id: 53
image: (working URL for project image)
skills: Array(1)
  0:
    created_at: "2019-12-06T04:27:52.537Z"
    id: 4
    name: "HTML"
    updated_at: "2019-12-06T04:27:52.540Z"
    __proto__: Object
    length: 1
  __proto__: Array(0)
title: "Card Game"
updated_at: "2019-12-07T19:35:08.751Z"

As you can see, the Skill "HTML" is suddenly missing the corresponding image URL when it is nested.

Here is my basic setup for the Projects Controller:

class ProjectsController < ApplicationController

  def index
    @projects = Project.all
    render json: @projects, include: :categories
  end

And here is my Skills Serializer:

class SkillSerializer < ActiveModel::Serializer
  attributes :id, :name, :created_at, :updated_at, :image

  def image
    object.image.service_url if object.image.attached?
  end
end

Does anyone know how to include a web-storage URL that belongs to a model when it is included inside another model association?


Solution

  • Changed the Projects Controller to the following:

    class ProjectsController < ApplicationController
      include Rails.application.routes.url_helpers
    
      def index
        @projects = Project.all
        projects_with_images = @projects.map do |project|
          new_project = project.attributes.symbolize_keys
          new_project[:image] = rails_blob_path(project.image, only_path: true)
    
          skills = project.skills
          skills_with_images = skills.map do |skill|
            new_skill = skill.attributes.symbolize_keys
            new_skill[:image] = rails_blob_path(skill.image, only_path: true)
            new_skill
          end
    
          new_project[:skills] = skills_with_images
          new_project
        end
    
        render json: {projects: projects_with_images}
      end
    

    May not be the most efficient, but it seems to be working!

    Here's a boiled down version from my show route for making sure a model has it's image url attached:

    def show
        @project = Project.find(params[:id]) 
        project_with_image = @project.attributes.symbolize_keys
        project_with_image[:image] = rails_blob_path(@project.image, only_path: true)
    
      render json: project_with_image