Created
January 7, 2022 11:50
-
-
Save sulmanweb/64c878292de356c62481ea3a81ed3ff5 to your computer and use it in GitHub Desktop.
ActiveStorage, Ruby on Rails 7, GraphQL and RSpec
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/graphql/mutations/create_document.rb | |
module Mutations | |
class CreateDocument < Mutations::BaseMutation | |
description "Create a document" | |
argument :doc, ApolloUploadServer::Upload, required: true, description: "The document to upload" | |
field :document, Types::Objects::DocumentType, null: false | |
field :code, Types::Enums::CodeEnum, null: false | |
def resolve(doc:) | |
authenticate_user | |
# First you need to create blob file in case of active storage. https://stackoverflow.com/q/70550808/4011757 | |
attachment = ActiveStorage::Blob::create_and_upload!(io: doc, filename: doc.original_filename, content_type: doc.content_type) | |
document = context[:current_user].documents.build(doc: attachment) | |
if document.save | |
{document: document, code: "SUCCESS"} | |
else | |
raise GraphQL::ExecutionError.new(document.errors.full_messages.join(", "), extensions: {code: "UNPROCESSABLE_ENTITY", errors: document.errors}) | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# spec/graphql/mutations/create_document_spec.rb | |
require 'rails_helper' | |
module Mutations | |
RSpec.describe CreateDocument, type: :request do | |
describe '.resolve' do | |
let(:session) {FactoryBot.create(:session)} | |
it 'create a document for the user' do | |
session.user.confirm | |
headers = sign_in_test_headers session | |
params = FactoryBot.attributes_for(:document, :with_image, user_id: session.user_id) | |
query = <<-GRAPHQL | |
mutation ($input: CreateDocumentInput!) { | |
createDocument(input: $input) { | |
document { | |
id | |
url | |
} | |
} | |
} | |
GRAPHQL | |
variables = {input: {doc: ::ApolloUploadServer::Wrappers::UploadedFile.new(ActionDispatch::Http::UploadedFile.new(filename: "image.png", type: "image/png", tempfile: File.new("spec/support/fixtures/image.png")))}} | |
response = ApiSchema.execute(query, variables: variables, context: {current_user: session.user}) | |
expect(response.to_h["data"]["createDocument"]["document"]["url"]).not_to be_nil | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/models/document.rb | |
class Document < ApplicationRecord | |
## RELATIONSHIPS | |
has_one_attached :doc | |
belongs_to :documentable, polymorphic: true, optional: true | |
belongs_to :user, optional: true | |
## VALIDATIONS | |
validate :doc_presence, on: :create | |
def doc_presence | |
pattern = %r{^(image|application|text)/(.)+$} | |
unless doc.attached? && pattern.match?(doc.attachment.blob.content_type) | |
errors.add(:doc, I18n.t("errors.models.document.file_presence")) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# spec/models/document_spec.rb | |
require 'rails_helper' | |
RSpec.describe Document, type: :model do | |
it 'has a valid factory' do | |
document = FactoryBot.build(:document) | |
expect(document.valid?).to be_falsey | |
document = FactoryBot.build(:document, :with_image) | |
expect(document.valid?).to be_truthy | |
expect(document.doc.attached?).to be_truthy | |
document.save! | |
expect(document.doc.attached?).to be_truthy | |
document = FactoryBot.build(:document, :with_video) | |
expect(document.valid?).to be_truthy | |
expect(document.doc.attached?).to be_truthy | |
document.save! | |
expect(document.doc.attached?).to be_truthy | |
document = FactoryBot.build(:document, :with_pdf) | |
expect(document.valid?).to be_truthy | |
document = FactoryBot.build(:document, :with_csv) | |
expect(document.valid?).to be_truthy | |
end | |
it 'must have user' do | |
document = FactoryBot.build(:document, user: nil) | |
expect(document.valid?).to be_falsey | |
end | |
it 'must contain file' do | |
document = FactoryBot.build(:document, doc: nil) | |
expect(document.valid?).to be_falsey | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/graphql/types/objects/document_type.rb | |
module Types | |
module Objects | |
class DocumentType < Types::BaseObject | |
field :id, Integer, null: false | |
field :documentable_type, String, null: true | |
field :documentable_id, Integer, null: true | |
field :content_type, String, null: true | |
field :url, String, null: false | |
field :created_at, GraphQL::Types::ISO8601DateTime, null: false | |
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false | |
def url | |
(Rails.env.development? || Rails.env.test?) ? Rails.application.routes.url_helpers.rails_blob_path(object.doc) : object.doc.service_url | |
end | |
def content_type | |
object.doc.present? ? object.doc.blob.content_type : nil | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# spec/factories/documents.rb | |
FactoryBot.define do | |
factory :document do | |
association :user | |
trait :with_image do | |
after :build do |document| | |
file_name = 'image.png' | |
file_path = Rails.root.join('spec', 'support', 'fixtures', file_name) | |
document.doc.attach(io: File.open(file_path), filename: file_name, content_type: 'image/png') | |
end | |
end | |
trait :with_video do | |
after :build do |document| | |
file_name = 'video.mp4' | |
file_path = Rails.root.join('spec', 'support', 'fixtures', file_name) | |
document.doc.attach(io: File.open(file_path), filename: file_name, content_type: 'video/mp4') | |
end | |
end | |
trait :with_pdf do | |
after :build do |document| | |
file_name = 'pdf.pdf' | |
file_path = Rails.root.join('spec', 'support', 'fixtures', file_name) | |
document.doc.attach(io: File.open(file_path), filename: file_name, content_type: 'application/pdf') | |
end | |
end | |
trait :with_csv do | |
after :build do |document| | |
file_name = 'import_csv.csv' | |
file_path = Rails.root.join('spec', 'support', 'fixtures', file_name) | |
document.doc.attach(io: File.open(file_path), filename: file_name, content_type: 'text/csv') | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment