Skip to content

Commit

Permalink
Add support for reverse link set links in GraphQL
Browse files Browse the repository at this point in the history
This adds support for reverse links that are part of a link set.
  • Loading branch information
brucebolt committed Dec 30, 2024
1 parent 5de11fe commit ddb8e95
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 0 deletions.
29 changes: 29 additions & 0 deletions app/graphql/sources/reverse_linked_to_editions_source.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module Sources
class ReverseLinkedToEditionsSource < GraphQL::Dataloader::Source
# rubocop:disable Lint/MissingSuper
def initialize(parent_object:)
@object = parent_object
@content_store = parent_object.content_store.to_sym
end
# rubocop:enable Lint/MissingSuper

def fetch(link_types)
all_links = @object
.document
.reverse_links
.where(link_type: link_types)

link_types_map = link_types.index_with { [] }

all_links.each_with_object(link_types_map) { |link, hash|
hash[link.link_type].concat(editions_for_link(link))
}.values
end

private

def editions_for_link(link)
link.source_documents.map { |document| document.send(@content_store) }
end
end
end
9 changes: 9 additions & 0 deletions app/graphql/types/base_object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,14 @@ def self.links_field(field_name_and_link_type, graphql_field_type)
.load(field_name_and_link_type.to_s)
end
end

def self.reverse_links_field(field_name_and_link_type, belongs_to, graphql_field_type)
field(field_name_and_link_type.to_sym, graphql_field_type)

define_method(field_name_and_link_type.to_sym) do
dataloader.with(Sources::ReverseLinkedToEditionsSource, parent_object: object)
.load(belongs_to.to_s)
end
end
end
end
22 changes: 22 additions & 0 deletions app/graphql/types/edition_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,28 @@ class EditionLinks < Types::BaseObject
links_field :worldwide_organisation, [EditionType]
links_field :worldwide_organisations, [EditionType]

reverse_links_field :child_taxons, :parent_taxons, [EditionType]
reverse_links_field :children, :parent, [EditionType]
reverse_links_field :document_collections, :documents, [EditionType]
reverse_links_field :level_one_taxons, :root_taxon, [EditionType]
reverse_links_field :ministers, :ministerial, [EditionType]
reverse_links_field :part_of_step_navs, :pages_part_of_step_nav, [EditionType]
reverse_links_field :policies, :working_groups, [EditionType]
reverse_links_field :related_to_step_navs, :pages_related_to_step_nav, [EditionType]
reverse_links_field :secondary_to_step_navs, :secondary_to_step_navs, [EditionType]

field :role_appointments, [EditionType]

def role_appointments
if object.document_type == "role"
dataloader.with(Sources::ReverseLinkedToEditionsSource, parent_object: object)
.load("role")
else
dataloader.with(Sources::ReverseLinkedToEditionsSource, parent_object: object)
.load("person")
end
end

def available_translations
Presenters::Queries::AvailableTranslations.by_edition(object)
.translations.fetch(:available_translations, [])
Expand Down
20 changes: 20 additions & 0 deletions spec/graphql/sources/reverse_linked_to_editions_source_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
RSpec.describe Sources::ReverseLinkedToEditionsSource do
it "returns the specified reverse link set links" do
target_document = create(:edition)
source_document_1 = create(:edition)
source_document_2 = create(:edition)
source_document_3 = create(:edition)
link_set_1 = create(:link_set, content_id: source_document_1.content_id)
link_set_2 = create(:link_set, content_id: source_document_2.content_id)
link_set_3 = create(:link_set, content_id: source_document_3.content_id)
create(:link, link_set: link_set_1, target_content_id: target_document.content_id, link_type: "test_link")
create(:link, link_set: link_set_2, target_content_id: target_document.content_id, link_type: "another_link_type")
create(:link, link_set: link_set_3, target_content_id: target_document.content_id, link_type: "test_link")

GraphQL::Dataloader.with_dataloading do |dataloader|
request = dataloader.with(described_class, parent_object: target_document).request("test_link")

expect(request.load).to eq([source_document_1, source_document_3])
end
end
end

0 comments on commit ddb8e95

Please sign in to comment.