lib/wcc/contentful/model_methods.rb in wcc-contentful-0.4.0.pre.rc vs lib/wcc/contentful/model_methods.rb in wcc-contentful-1.0.0.pre.rc1
- old
+ new
@@ -3,10 +3,19 @@
# This module is included by all {WCC::Contentful::Model models} and defines instance
# methods that are not dynamically generated.
#
# @api Model
module WCC::Contentful::ModelMethods
+ include WCC::Contentful::Instrumentation
+
+ # The set of options keys that are specific to the Model layer and shouldn't
+ # be passed down to the Store layer.
+ MODEL_LAYER_CONTEXT_KEYS = %i[
+ preview
+ backlinks
+ ].freeze
+
# Resolves all links in an entry to the specified depth.
#
# Each link in the entry is recursively retrieved from the store until the given
# depth is satisfied. Depth resolution is unlimited, circular references will
# be resolved to the same object.
@@ -20,34 +29,40 @@
# @param [Hash] options The remaining optional parameters, defined below
# @option options [Symbol] circular_reference Determines how circular references are
# handled. `:raise` causes a {WCC::Contentful::CircularReferenceError} to be raised,
# `:ignore` will cause the field to remain unresolved, and any other value (or nil)
# will cause the field to point to the previously resolved ruby object for that ID.
- def resolve(depth: 1, fields: nil, context: {}, **options)
+ def resolve(depth: 1, fields: nil, context: sys.context.to_h, **options)
raise ArgumentError, "Depth must be > 0 (was #{depth})" unless depth && depth > 0
return self if resolved?(depth: depth, fields: fields)
fields = fields.map { |f| f.to_s.camelize(:lower) } if fields.present?
fields ||= self.class::FIELDS
typedef = self.class.content_type_definition
links = fields.select { |f| %i[Asset Link].include?(typedef.fields[f].type) }
- raw_links =
- links.any? do |field_name|
- raw_value = raw.dig('fields', field_name, sys.locale)
- if raw_value&.is_a? Array
- raw_value.any? { |v| v&.dig('sys', 'type') == 'Link' }
- elsif raw_value
- raw_value.dig('sys', 'type') == 'Link'
+ raw_link_ids =
+ links.map { |field_name| raw.dig('fields', field_name, sys.locale) }
+ .flat_map do |raw_value|
+ _try_map(raw_value) { |v| v.dig('sys', 'id') if v.dig('sys', 'type') == 'Link' }
end
- end
- if raw_links
- # use include param to do resolution
- raw = self.class.store.find_by(content_type: self.class.content_type,
- filter: { 'sys.id' => id },
- options: { include: [depth, 10].min })
+ raw_link_ids = raw_link_ids.compact
+ backlinked_ids = (context[:backlinks]&.map { |m| m.id } || [])
+
+ has_unresolved_raw_links = (raw_link_ids - backlinked_ids).any?
+ if has_unresolved_raw_links
+ raw =
+ _instrument 'resolve', id: id, depth: depth, backlinks: backlinked_ids do
+ # use include param to do resolution
+ self.class.store(context[:preview])
+ .find_by(content_type: self.class.content_type,
+ filter: { 'sys.id' => id },
+ options: context.except(*MODEL_LAYER_CONTEXT_KEYS).merge!({
+ include: [depth, 10].min
+ }))
+ end
unless raw
raise WCC::Contentful::ResolveError, "Cannot find #{self.class.content_type} with ID #{id}"
end
@raw = raw.freeze
@@ -116,10 +131,16 @@
}
end
delegate :to_json, to: :to_h
+ protected
+
+ def _instrumentation_event_prefix
+ '.model.contentful.wcc'
+ end
+
private
def _resolve_field(field_name, depth = 1, context = {}, options = {})
return if depth <= 0
@@ -145,20 +166,24 @@
# Use the already resolved circular reference, or resolve a link, or
# instantiate from already resolved raw entry data.
m = already_resolved ||
if raw.dig('sys', 'type') == 'Link'
- WCC::Contentful::Model.find(id, new_context)
+ _instrument 'resolve',
+ id: self.id, depth: depth, backlinks: context[:backlinks]&.map(&:id) do
+ WCC::Contentful::Model.find(id, options: new_context)
+ end
else
WCC::Contentful::Model.new_from_raw(raw, new_context)
end
m.resolve(depth: depth - 1, context: new_context, **options) if m && depth > 1
m
}
begin
val = _try_map(val) { |v| load.call(v) }
+ val = val.compact if val.is_a? Array
instance_variable_set(var_name + '_resolved', val)
rescue WCC::Contentful::CircularReferenceError
raise unless options[:circular_reference] == :ignore
end