Module: Models::SchemaMarkup
- Extended by:
- ActiveSupport::Concern
- Included in:
- Article
- Defined in:
- app/concerns/models/schema_markup.rb
Overview
ActiveSupport::Concern mixin: schema markup.
Instance Method Summary collapse
-
#add_schema(schema) ⇒ void
Appends a schema.org hash to the schema markup list, defaulting
@context. -
#clear_schema_markup ⇒ void
Clears all schema markup entries.
-
#consolidated_faq_page_schema ⇒ Hash?
Build a single FAQPage schema merging: (1) FAQPage mainEntity from schema_markup, (2) FAQs from embedded blocks (by ID via FaqPresenter).
-
#content_has_embedded_faq_schema? ⇒ Boolean
Check if content has embedded FAQ oEmbed blocks for extractor/rules that need to skip or strip that block.
-
#embedded_faq_ids_from_content ⇒ Array<Integer>
Collect FAQ IDs from embedded oEmbed blocks (data-faq-ids), in document order.
-
#has_schema_type?(type) ⇒ Boolean
Checks whether the schema markup includes the given
@type. -
#render_schema_markup ⇒ ActiveSupport::SafeBuffer
Renders the schema markup as HTML-safe JSON-LD script tags.
-
#schema_count ⇒ Integer
Returns the number of schema markup entries.
-
#schema_types ⇒ Array<String>
Returns the distinct
@typevalues present in the schema markup. -
#schemas_by_type(type) ⇒ Array<Hash>
Returns all schema hashes matching the given
@type.
Instance Method Details
#add_schema(schema) ⇒ void
This method returns an undefined value.
Appends a schema.org hash to the schema markup list, defaulting @context.
Non-hash values are ignored.
16 17 18 19 20 21 22 23 24 |
# File 'app/concerns/models/schema_markup.rb', line 16 def add_schema(schema) return unless schema.is_a?(Hash) schema['@context'] = 'https://schema.org' unless schema['@context'] self.schema_markup ||= [] # rubocop:disable Style/RedundantSelf self.schema_markup << schema # rubocop:enable Style/RedundantSelf end |
#clear_schema_markup ⇒ void
This method returns an undefined value.
Clears all schema markup entries.
158 159 160 |
# File 'app/concerns/models/schema_markup.rb', line 158 def clear_schema_markup self.schema_markup = [] end |
#consolidated_faq_page_schema ⇒ Hash?
Build a single FAQPage schema merging: (1) FAQPage mainEntity from schema_markup, (2) FAQs from embedded blocks (by ID via FaqPresenter).
Deduplicates by question name. Returns a hash suitable for JSON-LD or nil if nothing to output.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'app/concerns/models/schema_markup.rb', line 99 def consolidated_faq_page_schema = extracted_faq_schemas = (schema_markup || []).select { |s| s['@type'] == 'FAQPage' } extracted_entities = extracted_faq_schemas.flat_map { |s| (s['mainEntity'] || s[:mainEntity] || []).map(&:with_indifferent_access) } = if .any? ordered_ids = .uniq faqs = ArticleFaq .where(id: ordered_ids) .published .order(Arel.sql("ARRAY_POSITION(ARRAY[#{ordered_ids.join(',')}]::integer[], id)")) if faqs.empty? [] else FaqPresenter.new(faqs).schema_dot_org_structure.mainEntity.map(&:to_json_struct) end else [] end all_entities = (extracted_entities + ) return nil if all_entities.empty? # Deduplicate by question name (first occurrence wins) seen = Set.new main_entity = all_entities.filter_map do |entity| name = entity['name'] || entity[:name] next if name.blank? || seen.include?(name) seen.add(name) entity end return nil if main_entity.empty? { '@context' => 'https://schema.org', '@type' => 'FAQPage', 'mainEntity' => main_entity } end |
#content_has_embedded_faq_schema? ⇒ Boolean
Check if content has embedded FAQ oEmbed blocks for extractor/rules that need to skip or strip that block
144 145 146 147 148 149 150 151 152 153 |
# File 'app/concerns/models/schema_markup.rb', line 144 def return false unless respond_to?(:localized_solution) rendered = localized_solution.to_s return true if rendered.match?(/wy-faq-embed|data-wy-oembed="faq"/i) return true if rendered.include?('application/ld+json') && rendered.include?('"FAQPage"') false end |
#embedded_faq_ids_from_content ⇒ Array<Integer>
Collect FAQ IDs from embedded oEmbed blocks (data-faq-ids), in document order.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'app/concerns/models/schema_markup.rb', line 76 def return [] unless respond_to?(:localized_solution) content = localized_solution.to_s return [] if content.blank? ids = [] doc = Nokogiri::HTML(content) doc.css('figure.wy-faq-embed, figure[data-wy-oembed="faq"]').each do |figure| figure['data-faq-ids'].to_s.split(',').each do |id_str| id = id_str.strip.to_i ids << id if id.positive? end end ids.uniq end |
#has_schema_type?(type) ⇒ Boolean
Checks whether the schema markup includes the given @type.
39 40 41 |
# File 'app/concerns/models/schema_markup.rb', line 39 def has_schema_type?(type) schema_types.include?(type) end |
#render_schema_markup ⇒ ActiveSupport::SafeBuffer
Renders the schema markup as HTML-safe JSON-LD script tags.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'app/concerns/models/schema_markup.rb', line 56 def render_schema_markup # Build one consolidated FAQPage (extracted schema_markup FAQ + embedded oEmbed FAQs), then other schemas consolidated_faq = consolidated_faq_page_schema other_schemas = (schema_markup || []).reject { |s| s['@type'] == 'FAQPage' } parts = [] parts << consolidated_faq if consolidated_faq.present? parts.concat(other_schemas) return '' if parts.empty? parts.map do |schema| hash = schema.is_a?(Hash) ? schema : schema.with_indifferent_access "<script type=\"application/ld+json\">#{hash.to_json}</script>" end.join("\n").html_safe end |
#schema_count ⇒ Integer
Returns the number of schema markup entries.
165 166 167 |
# File 'app/concerns/models/schema_markup.rb', line 165 def schema_count schema_markup&.length || 0 end |
#schema_types ⇒ Array<String>
Returns the distinct @type values present in the schema markup.
29 30 31 32 33 |
# File 'app/concerns/models/schema_markup.rb', line 29 def schema_types return [] if schema_markup.blank? schema_markup.pluck('@type').compact.uniq end |
#schemas_by_type(type) ⇒ Array<Hash>
Returns all schema hashes matching the given @type.
47 48 49 50 51 |
# File 'app/concerns/models/schema_markup.rb', line 47 def schemas_by_type(type) return [] if schema_markup.blank? schema_markup.select { |schema| schema['@type'] == type } end |