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

Constant Summary collapse

ROOT_ATTR =
{ '@context' => 'https://schema.org' }.freeze
UNQUALIFIED_CLASS_NAME_REGEX =
/([^:]+)$/

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.



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

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



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

def id_iri
  @id_iri
end

Class Method Details

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



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

def attribute(name, type = ActiveModel::Type::Value.new, **options)
  # 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.
  if (type.is_a?(Class) && !(type < ActiveModel::Type::Value)) || type.is_a?(Array)
    type = ActiveModel::Type::Value.new
  end
  super(name, type, **options)
end

Instance Method Details

#_to_json_structObject

Default behavior uses attributes defined in the class stripping empties



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

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



57
58
59
60
61
62
63
64
65
# File 'app/models/schema_dot_org/schema_type.rb', line 57

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



53
54
55
# File 'app/models/schema_dot_org/schema_type.rb', line 53

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.



69
70
71
72
73
# File 'app/models/schema_dot_org/schema_type.rb', line 69

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



42
43
44
45
46
47
48
49
50
51
# File 'app/models/schema_dot_org/schema_type.rb', line 42

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.



102
103
104
105
106
107
# File 'app/models/schema_dot_org/schema_type.rb', line 102

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