From d6c35b1213295db588c048c15a279a62088e67ba Mon Sep 17 00:00:00 2001 From: Julian Rubisch Date: Tue, 9 Feb 2021 13:18:11 +0100 Subject: [PATCH] Extract Resource Resolver #78 --- lib/futurism.rb | 1 + lib/futurism/channel.rb | 26 +----------- lib/futurism/resolver/resources.rb | 68 ++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 24 deletions(-) create mode 100644 lib/futurism/resolver/resources.rb diff --git a/lib/futurism.rb b/lib/futurism.rb index bccc78c..bbfa76c 100644 --- a/lib/futurism.rb +++ b/lib/futurism.rb @@ -3,6 +3,7 @@ require "cable_ready" require "futurism/engine" require "futurism/message_verifier" +require "futurism/resolver/resources" require "futurism/resolver/controller" require "futurism/resolver/controller/renderer" require "futurism/channel" diff --git a/lib/futurism/channel.rb b/lib/futurism/channel.rb index e2e1c66..5a1448f 100644 --- a/lib/futurism/channel.rb +++ b/lib/futurism/channel.rb @@ -1,7 +1,6 @@ module Futurism class Channel < ActionCable::Channel::Base include CableReady::Broadcaster - include Futurism::MessageVerifier def stream_name ids = connection.identifiers.map { |identifier| send(identifier).try(:id) || send(identifier) } @@ -18,19 +17,8 @@ def subscribed def receive(data) resources = data.fetch_values("signed_params", "sgids", "signed_controllers", "urls") { |_key| Array.new(data["signed_params"].length, nil) }.transpose - resources.each do |signed_params, sgid, signed_controller, url| - selector = "[data-signed-params='#{signed_params}']" - selector << "[data-sgid='#{sgid}']" if sgid.present? - - controller = Resolver::Controller.from(signed_string: signed_controller) - renderer = Resolver::Controller::Renderer.for(controller: controller, - connection: connection, - url: url, - params: @params) - - resource = lookup_resource(signed_params: signed_params, sgid: sgid) - html = renderer.render(resource) - + resolver = Resolver::Resources.new(resource_definitions: resources, connection: connection, params: @params) + resolver.resolve do |selector, html| cable_ready[stream_name].outer_html( selector: selector, html: html @@ -39,15 +27,5 @@ def receive(data) cable_ready.broadcast end - - private - - def lookup_resource(signed_params:, sgid:) - return GlobalID::Locator.locate_signed(sgid) if sgid.present? - - message_verifier - .verify(signed_params) - .deep_transform_values { |value| value.is_a?(String) && value.start_with?("gid://") ? GlobalID::Locator.locate(value) : value } - end end end diff --git a/lib/futurism/resolver/resources.rb b/lib/futurism/resolver/resources.rb new file mode 100644 index 0000000..44128d6 --- /dev/null +++ b/lib/futurism/resolver/resources.rb @@ -0,0 +1,68 @@ +module Futurism + module Resolver + class Resources + include Futurism::MessageVerifier + + # resource definitions are an array of [signed_params, sgid, signed_controller, url] + def initialize(resource_definitions:, connection:, params:) + @connection = connection + @params = params + @resources_with_sgids, @resources_without_sgids = resource_definitions + .partition { |signed_params, sgid, *| sgid.present? } + .map { |partition| partition.map { |definition| ResourceDefinition.new(definition) } } + end + + def resolve + resolved_models.zip(@resources_with_sgids).each do |model, resource_definition| + html = renderer_for(resource_definition: resource_definition).render(model) + + yield(resource_definition.selector, html) + end + + @resources_without_sgids.each do |resource_definition| + resource = lookup_resource(resource_definition) + html = renderer_for(resource_definition: resource_definition).render(resource) + + yield(resource_definition.selector, html) + end + end + + private + + class ResourceDefinition + attr_reader :signed_params, :sgid, :signed_controller, :url + + def initialize(resource_definition) + @signed_params, @sgid, @signed_controller, @url = resource_definition + end + + def selector + selector = "[data-signed-params='#{@signed_params}']" + selector << "[data-sgid='#{@sgid}']" if @sgid.present? + selector + end + + def controller + Resolver::Controller.from(signed_string: @signed_controller) + end + end + + def renderer_for(resource_definition:) + Resolver::Controller::Renderer.for(controller: resource_definition.controller, + connection: @connection, + url: resource_definition.url, + params: @params) + end + + def resolved_models + GlobalID::Locator.locate_many_signed @resources_with_sgids.map(&:sgid) + end + + def lookup_resource(resource_definition) + message_verifier + .verify(resource_definition.signed_params) + .deep_transform_values { |value| value.is_a?(String) && value.start_with?("gid://") ? GlobalID::Locator.locate(value) : value } + end + end + end +end