Class: SchemaDotOrg::SchemaType

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::API, ActiveModel::Attributes, ActiveModel::Validations, ActiveModel::Validations::Callbacks, StripAttributes
Defined in:
app/models/schema_dot_org/schema_type.rb

Overview

Helper class scoped to SchemaDotOrg.

Constant Summary collapse

ROOT_ATTR =

Root attr.

{ '@context' => 'https://schema.org' }.freeze
UNQUALIFIED_CLASS_NAME_REGEX =

Regex pattern matching unqualified class name.

/([^:]+)$/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) ⇒ SchemaType

Virtus silently ignored unknown keys; ActiveModel::AttributeAssignment raises
UnknownAttributeError. Restore the permissive Virtus behaviour so that callers
constructing schema objects (e.g. seo_helper constants) can pass extra keywords
for attributes that are not yet declared without breaking at load time.



32
33
34
35
# File 'app/models/schema_dot_org/schema_type.rb', line 32

def initialize(attrs = {})
  known = self.class.attribute_types.keys
  super(attrs.slice(*known.map(&:to_sym), *known.map(&:to_s)))
end

Instance Attribute Details

#id_iriObject

Optional IRI for linking entities across documents/blocks



38
39
40
# File 'app/models/schema_dot_org/schema_type.rb', line 38

def id_iri
  @id_iri
end

Class Method Details

.attribute(name, type = ActiveModel::Type::Value.new) ⇒ Object



19
20
21
22
23
24
25
# File 'app/models/schema_dot_org/schema_type.rb', line 19

def attribute(name, type = ActiveModel::Type::Value.new, **)
  # Coerce Virtus-style plain-class types (e.g. String, Integer) and
  # Virtus array-of-type syntax (e.g. [ListItem]) to untyped Value so
  # existing subclass declarations continue to work without modification.
  type = ActiveModel::Type::Value.new if (type.is_a?(Class) && !(type < ActiveModel::Type::Value)) || type.is_a?(Array)
  super
end

Instance Method Details

#_to_json_structObject

Default behavior uses attributes defined in the class stripping empties



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'app/models/schema_dot_org/schema_type.rb', line 79

def _to_json_struct
  s = {}
  if valid?
    # Iterate through our attributes, members that are themselves schemaDotOrg type will be rendeed with their json struct attribute
    attributes.each do |k, v|
      next if v.nil? || (v.respond_to?(:empty?) && v.empty?)

      s[k] = if v.respond_to?(:to_json_struct)
               v.to_json_struct
             elsif v.is_a?(Array)
               v.map { |e| e.respond_to?(:to_json_struct) ? e.to_json_struct : e.to_s }.presence
             elsif v.respond_to?(:iso8601)
               v.iso8601
             else
               v
             end
    end
  else
    message = "Unable to generate json+ld struct for #{self.class.name}, #{errors_to_s}"
    Rails.logger.error message
    ErrorReporting.warning(message, schema_type: self.class.name, errors: errors_to_s)
  end
  s
end

#to_json(pretty: false, as_root: false) ⇒ Object



60
61
62
63
64
65
66
67
68
# File 'app/models/schema_dot_org/schema_type.rb', line 60

def to_json(pretty: false, as_root: false)
  structure = as_root ? ROOT_ATTR.merge(to_json_struct) : to_json_struct

  if pretty
    JSON.pretty_generate(structure)
  else
    structure.to_json
  end
end

#to_json_ld(pretty: false) ⇒ Object



56
57
58
# File 'app/models/schema_dot_org/schema_type.rb', line 56

def to_json_ld(pretty: false)
  "<script type=\"application/ld+json\">\n#{to_json(pretty: pretty, as_root: true)}\n</script>"
end

#to_json_structObject

Use the class name to create the "@type" attribute.

Returns:

  • a hash structure representing json.



72
73
74
75
76
# File 'app/models/schema_dot_org/schema_type.rb', line 72

def to_json_struct
  base = { '@type' => un_namespaced_classname }
  base['@id'] = id_iri if respond_to?(:id_iri) && id_iri.present?
  base.merge(_to_json_struct.compact)
end

#to_sObject



45
46
47
48
49
50
51
52
53
54
# File 'app/models/schema_dot_org/schema_type.rb', line 45

def to_s
  json_string = to_json_ld(pretty: !rails_production? && !ENV['SCHEMA_DOT_ORG_MINIFIED_JSON'])

  # Mark as safe if we're in Rails
  if json_string.respond_to?(:html_safe)
    json_string.html_safe
  else
    json_string
  end
end

#un_namespaced_classnameObject

Returns the classname without the module namespace.

Returns:

  • the classname without the module namespace.



105
106
107
108
109
110
# File 'app/models/schema_dot_org/schema_type.rb', line 105

def un_namespaced_classname
  self.class.name =~ UNQUALIFIED_CLASS_NAME_REGEX
  s = Regexp.last_match(1)
  # Translation map
  { 'FaqPage' => 'FAQPage', 'QaPage' => 'QAPage' }[s] || s
end