Graphql-ruby: Active Storage support

Created on 15 Aug 2018  路  10Comments  路  Source: rmosolgo/graphql-ruby

"exception": "#<RuntimeError: No connection implementation to wrap ActiveStorage::Attached::Many (#<ActiveStorage::Attached::Many:0x00007fceb5e6d5f8>)>"

I am running 1.7.14, so maybe 1.8 supports this already.

Most helpful comment

As far I can see, ActiveStorage::Attached::Many can simply be treated as ActiveRecord::Relation, and all you need to do is just register ActiveStorage::Attached::Many to GraphQL::Relay::RelationConnection as the custom connection implementation.

GraphQL::Relay::BaseConnection.register_connection_implementation(
  ActiveStorage::Attached::Many,
  GraphQL::Relay::RelationConnection
)

class User < ApplicationRecord
  has_many_attached :images
end

class ActiveStorageAttachment < GraphQL::Schema::Object
  field :id, ID, null: false
end

class UserType < GraphQL::Schema::Object
  field :images, ActiveStorageAttachment.connection_type, null: false
end

I haven't fully tested this but being using this method for some time now. I can create a PR if needed

To solve the N+1 issue, just use the batch gem.

All 10 comments

No, not supported by graphql-ruby yet! Actually, I haven't even _looked_ at ActiveStorage yet 馃檲

For other people seeing this, I am converting it to an array type as a temporary work around.

It would be very nice to have active storage support!

@kevincolemaninc can you elaborate a bit? Maybe a snippet of your type definition?

@t2

you can call .to_a on your active_storage models which converts it to an array which graphql can process. Unfortunately, its not treated like a connection so you will need to do your own pagination.

I did something like this to get the image url, is this ok?

module Types
  class PostType < Types::BaseObject
    field :id, ID, null: false
    field :title, String, null: false
    field :content, String, null: false
    field :image_url, String, null: true

    def image_url
      attachment = Post.find(id)&.image_attachment
      return if attachment.nil?

      Rails.application.routes.url_helpers.rails_blob_url(attachment, only_path: true)
    end
  end
end

@Sanchezdav

This would cause an N+2 for each type. Rails will do:

  • SELECT "active_storage_attachments".*
  • SELECT "active_storage_blobs".*

If speed isn't important or you're not loading very many post types, your solution might be tolerable.

As far I can see, ActiveStorage::Attached::Many can simply be treated as ActiveRecord::Relation, and all you need to do is just register ActiveStorage::Attached::Many to GraphQL::Relay::RelationConnection as the custom connection implementation.

GraphQL::Relay::BaseConnection.register_connection_implementation(
  ActiveStorage::Attached::Many,
  GraphQL::Relay::RelationConnection
)

class User < ApplicationRecord
  has_many_attached :images
end

class ActiveStorageAttachment < GraphQL::Schema::Object
  field :id, ID, null: false
end

class UserType < GraphQL::Schema::Object
  field :images, ActiveStorageAttachment.connection_type, null: false
end

I haven't fully tested this but being using this method for some time now. I can create a PR if needed

To solve the N+1 issue, just use the batch gem.

Thanks for sharing your solution! If someone wants to contribute first-class support for ActiveStorage, I'm happy to review a PR for it.

``

I did something like this to get the image url, is this ok?

module Types
  class PostType < Types::BaseObject
    field :id, ID, null: false
    field :title, String, null: false
    field :content, String, null: false
    field :image_url, String, null: true

    def image_url
      attachment = Post.find(id)&.image_attachment
      return if attachment.nil?

      Rails.application.routes.url_helpers.rails_blob_url(attachment, only_path: true)
    end
  end
end

This Looks like a quick solution although use 'object' to access the current object rather than query on id
and for solving N+1 problem use batch gem

Was this page helpful?
0 / 5 - 0 ratings