lib/materialist/materializer/internals/materializer.rb in materialist-3.3.0 vs lib/materialist/materializer/internals/materializer.rb in materialist-3.4.0

- old
+ new

@@ -1,20 +1,31 @@ require 'routemaster/api_client' require_relative '../../workers/event' +require_relative './resources' module Materialist module Materializer module Internals class Materializer - def initialize(url, klass) + def initialize(url, klass, resource_payload: nil, api_client: nil) @url = url @instance = klass.new @options = klass.__materialist_options + @api_client = api_client || Routemaster::APIClient.new(response_class: HateoasResource) + if resource_payload + @resource = PayloadResource.new(resource_payload, client: @api_client) + end end + def perform(action) + action.to_sym == :delete ? destroy : upsert + end + + private + def upsert(retry_on_race_condition: true) - return unless root_resource + return unless resource if materialize_self? upsert_record.tap do |entity| send_messages(after_upsert, entity) unless after_upsert.nil? end @@ -40,41 +51,34 @@ send_messages(after_destroy, entity) unless after_destroy.nil? end if entity end end - private + attr_reader :url, :instance, :options, :api_client - attr_reader :url, :instance, :options - def materialize_self? options.include? :model_class end def upsert_record model_class.find_or_initialize_by(source_lookup(url)).tap do |entity| send_messages(before_upsert, entity) unless before_upsert.nil? - entity.update_attributes! attributes + entity.update_attributes!(attributes) end end def materialize_links (options[:links_to_materialize] || []) .each { |key, opts| materialize_link(key, opts) } end def materialize_link(key, opts) - return unless root_resource.body._links.include?(key) + return unless link = resource.dig(:_links, key) + return unless materializer_class = MaterializerFactory.class_from_topic(opts.fetch(:topic)) - # this can't happen asynchronously - # because the handler options are unavailable in this context - # :( - ::Materialist::Workers::Event.new.perform({ - 'topic' => opts[:topic], - 'url' => root_resource.body._links[key].href, - 'type' => 'noop' - }) + # TODO: perhaps consider doing this asynchronously some how? + materializer_class.perform(link[:href], :noop) end def mappings options.fetch :mapping end @@ -110,24 +114,20 @@ def source_lookup(url) @_source_lookup ||= { source_key => url_parser.call(url) } end def attributes - mappings.map{ |m| m.map(root_resource) }.compact.reduce(&:merge) || {} + mappings.map{ |m| m.map(resource) }.compact.reduce(&:merge) || {} end - def root_resource - @_root_resource ||= begin - api_client.get(url, options: { enable_caching: false }) - rescue Routemaster::Errors::ResourceNotFound - nil - end + def resource + @resource ||= fetch_resource end - def api_client - @_api_client ||= Routemaster::APIClient.new( - response_class: Routemaster::Responses::HateoasResponse - ) + def fetch_resource + api_client.get(url, options: { enable_caching: false }) + rescue Routemaster::Errors::ResourceNotFound + nil end def send_messages(messages, arguments) messages.each { |message| instance.send(message, arguments) } end