Class: MetaTags::MetaTagsCollection

Inherits:
Object
  • Object
show all
Defined in:
lib/meta_tags/meta_tags_collection.rb,
sig/lib/meta_tags/meta_tags_collection.rbs

Overview

This class represents a collection of meta tags. Basically a wrapper around HashWithIndifferentAccess, with some additional helper methods.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeMetaTagsCollection

Initializes a new instance of MetaTagsCollection.



10
11
12
# File 'lib/meta_tags/meta_tags_collection.rb', line 10

def initialize
  @meta_tags = ActiveSupport::HashWithIndifferentAccess.new
end

Instance Attribute Details

#meta_tagsHash[String | Symbol, untyped] (readonly)

Returns the value of attribute meta_tags.

Returns:

  • (Hash[String | Symbol, untyped])


7
8
9
# File 'lib/meta_tags/meta_tags_collection.rb', line 7

def meta_tags
  @meta_tags
end

Instance Method Details

#[](name) ⇒ Object

Returns meta tag value by name.

Parameters:

  • name (String, Symbol)

    meta tag name.

Returns:

  • meta tag value.



18
19
20
# File 'lib/meta_tags/meta_tags_collection.rb', line 18

def [](name)
  @meta_tags[name]
end

#[]=(name, value) ⇒ Object

Sets meta tag value by name.

Parameters:

  • name (String, Symbol)

    meta tag name.

  • value

    meta tag value.

Returns:

  • meta tag value.



27
28
29
# File 'lib/meta_tags/meta_tags_collection.rb', line 27

def []=(name, value)
  @meta_tags[name] = value
end

#apply_robots_value(result, name, value, processed) ⇒ void

This method returns an undefined value.

Records a robots directive unless it has already been set for the same key.

Parameters:

  • result (Hash{String => Array<String>})

    robots directives grouped by tag name.

  • name (String)

    robots tag name.

  • value (String)

    robots directive value.

  • processed (Set<String>)

    names already recorded in this pass.



292
293
294
295
296
297
298
# File 'lib/meta_tags/meta_tags_collection.rb', line 292

def apply_robots_value(result, name, value, processed)
  name = name.to_s
  return if processed.include?(name)

  result[name] << value
  processed << name
end

#calculate_robots_attributes(result, attributes) ⇒ void

This method returns an undefined value.

Appends resolved robots directives while preserving first-write priority.

Parameters:

  • result (Hash{String => Array<String>})

    robots directives grouped by tag name.

  • attributes (Symbol, Array<Symbol>)

    robots attributes to resolve.



271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/meta_tags/meta_tags_collection.rb', line 271

def calculate_robots_attributes(result, attributes)
  processed = Set.new
  Array(attributes).each do |attribute|
    # @type var attribute: String | Symbol
    names, value = extract_robots_attribute(attribute)
    next unless value

    robot_names = names.is_a?(String) ? [names] : names
    robot_names.each do |name|
      apply_robots_value(result, name, value, processed)
    end
  end
end

#delete(*names) ⇒ void

This method returns an undefined value.

Deletes specified meta tags.

Parameters:

  • names (Array<String, Symbol>)

    list of meta tags to delete.



90
91
92
# File 'lib/meta_tags/meta_tags_collection.rb', line 90

def delete(*names)
  names.each { |name| @meta_tags.delete(name) }
end

#extract(name) ⇒ Object

Deletes and returns a meta tag value by name.

Parameters:

  • name (String, Symbol)

    meta tag name.

Returns:

  • (Object)

    meta tag value.



83
84
85
# File 'lib/meta_tags/meta_tags_collection.rb', line 83

def extract(name)
  @meta_tags.delete(name)
end

#extract_full_titleString

Extracts full page title and deletes all related meta tags.

Returns:

  • (String)

    page title.



97
98
99
100
101
102
103
104
# File 'lib/meta_tags/meta_tags_collection.rb', line 97

def extract_full_title
  site_title = extract(:site) || ""
  title = extract_title
  separator = extract_separator
  reverse = extract(:reverse) == true

  TextNormalizer.normalize_title(site_title, title, separator, reverse)
end

#extract_robotsHash{String => String}

Extracts robots settings as a Hash mapping tag names to rendered values.

Returns:

  • (Hash{String => String})

    robots attributes.



147
148
149
150
151
152
153
154
155
# File 'lib/meta_tags/meta_tags_collection.rb', line 147

def extract_robots
  result = robots
  delete(:noindex, :index, :follow, :nofollow, :noarchive)
  [:robots, :googlebot, :bingbot].each do |bot|
    extract(bot) if meta_tags[bot].is_a?(Hash)
  end

  result
end

#extract_robots_attribute(name) ⇒ Array<Object>

Extracts a robots attribute name/value pair (noindex, nofollow, etc.).

Parameters:

  • name (String, Symbol)

    noindex attribute name.

Returns:

  • (Array<Object>)

    normalized robots tag name(s) and directive value.



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/meta_tags/meta_tags_collection.rb', line 241

def extract_robots_attribute(name)
  noindex = meta_tags[name]
  # @type var noindex_name: String | Array[String]
  noindex_name = if noindex.is_a?(Array)
    noindex.reject { |target| target.is_a?(String) && target.blank? }.map(&:to_s)
  elsif noindex.is_a?(String)
    noindex.presence || []
  else
    "robots"
  end
  noindex_value = if robots_attribute_present?(noindex) && noindex_name.present?
    name.to_s
  end

  [noindex_name, noindex_value]
end

#extract_separatorString

Extracts title separator as a string.

Returns:

  • (String)

    page title separator.



130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/meta_tags/meta_tags_collection.rb', line 130

def extract_separator
  if meta_tags[:separator] == false
    # Special case: if separator is hidden, do not display suffix/prefix
    prefix = separator = suffix = ""
  else
    prefix = extract_separator_section(:prefix, " ")
    separator = extract_separator_section(:separator, "|")
    suffix = extract_separator_section(:suffix, " ")
  end
  delete(:separator, :prefix, :suffix)

  TextNormalizer.safe_join([prefix, separator, suffix], "")
end

#extract_separator_section(name, default) ⇒ String

Extracts separator segment without deleting it from meta tags list. If the value is false, an empty string will be returned.

Parameters:

  • name (Symbol, String)

    separator segment name.

  • default (String)

    default value.

Returns:

  • (String)

    separator segment value.



233
234
235
# File 'lib/meta_tags/meta_tags_collection.rb', line 233

def extract_separator_section(name, default)
  (meta_tags[name] == false) ? "" : (meta_tags[name] || default)
end

#extract_titleArray<String>

Extracts page title as an array of segments without site title and separators.

Returns:

  • (Array<String>)

    segments of page title.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/meta_tags/meta_tags_collection.rb', line 109

def extract_title
  lowercase = extract(:lowercase) == true
  title = extract(:title).presence
  return [] unless title

  title = Array(title)
  if lowercase
    return title.map do |segment|
      string = String.try_convert(segment)
      raise ArgumentError, "Expected a string or an object that implements #to_str" unless string

      string.downcase
    end
  end

  title
end

#full_title(defaults = {}) ⇒ String

Constructs the full title as if it would be rendered in title meta tag.

Parameters:

  • defaults (Hash) (defaults to: {})

    list of default meta tag attributes.

Returns:

  • (String)

    page title.



63
64
65
# File 'lib/meta_tags/meta_tags_collection.rb', line 63

def full_title(defaults = {})
  with_defaults(defaults) { extract_full_title }
end

#noindex?Boolean

Returns whether robots settings produce a noindex directive.

Returns:

  • (Boolean)

    true when a noindex directive will be rendered.



160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/meta_tags/meta_tags_collection.rb', line 160

def noindex?
  contents = robots.values
  property_tags = MetaTags.config.property_tags.map(&:to_s)
  [:robots, :googlebot, :bingbot].each do |bot|
    values = meta_tags[bot]
    next if values.is_a?(Hash) || property_tags.include?(bot.to_s)

    contents.concat(Array(values))
  end

  contents.any? do |content|
    content.to_s.split(",").any? { |directive| directive.strip.casecmp?("noindex") }
  end
end

#normalize_open_graph(meta_tags) ⇒ ActiveSupport::HashWithIndifferentAccess

Converts input hash to HashWithIndifferentAccess and renames :open_graph to :og. When both aliases contain hashes, they are deep-merged with :og taking precedence.

Parameters:

  • meta_tags (Hash)

    list of meta tags.

Returns:



214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/meta_tags/meta_tags_collection.rb', line 214

def normalize_open_graph(meta_tags)
  meta_tags = meta_tags.with_indifferent_access
  if meta_tags.key?(:open_graph)
    open_graph = meta_tags.delete(:open_graph)
    if meta_tags.key?(:og)
      meta_tags[:og] = open_graph.dup.deep_merge!(meta_tags[:og]) if open_graph.is_a?(Hash) && meta_tags[:og].is_a?(Hash)
    else
      meta_tags[:og] = open_graph
    end
  end
  meta_tags
end

#page_title(defaults = {}) ⇒ String

Constructs the title without site title (for normalized parameters). When title is empty, use the site title instead.

Parameters:

  • defaults (Hash) (defaults to: {})

    list of default meta tag attributes.

Returns:

  • (String)

    page title.



72
73
74
75
76
77
# File 'lib/meta_tags/meta_tags_collection.rb', line 72

def page_title(defaults = {})
  with_defaults(defaults) do
    site = extract(:site)
    extract_full_title.presence || site || ""
  end
end

#robotsHash{String => String}

Returns robots settings without modifying the collection.

Returns:

  • (Hash{String => String})

    robots attributes.



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/meta_tags/meta_tags_collection.rb', line 180

def robots
  # @type var result: Hash[String, Array[String]]
  result = Hash.new { |h, k| h[k] = [] }

  [
    # noindex has higher priority than index
    [:noindex, :index],
    # follow has higher priority than nofollow
    [:follow, :nofollow],
    :noarchive
  ].each do |attributes|
    calculate_robots_attributes(result, attributes)
  end

  [:robots, :googlebot, :bingbot].each do |bot|
    values = meta_tags[bot]
    if values.is_a?(Hash)
      values.each do |key, value|
        next if value == false

        directive = (value.nil? || value == true) ? key.to_s : "#{key}:#{value}"
        result[bot.to_s] << directive
      end
    end
  end

  result.transform_values { |v| v.join(", ") }
end

#robots_attribute_present?(value) ⇒ Boolean

Returns whether a robots attribute resolves to at least one target.

Parameters:

  • value (Object)

    robots attribute value.

Returns:

  • (Boolean)

    true when the attribute produces a directive.



262
263
264
# File 'lib/meta_tags/meta_tags_collection.rb', line 262

def robots_attribute_present?(value)
  !!value && (!value.is_a?(Array) || !value.empty?)
end

#update(object = {}) ⇒ Hash

Recursively merges a Hash of meta tag attributes into the current list.

Parameters:

  • object (Hash, #to_meta_tags) (defaults to: {})

    Hash of meta tags (or object responding to #to_meta_tags and returning a hash) to merge into the current list.

Returns:

  • (Hash)

    result of the merge.



36
37
38
39
40
41
42
43
44
45
# File 'lib/meta_tags/meta_tags_collection.rb', line 36

def update(object = {})
  meta_tags = if object.respond_to?(:to_meta_tags)
    # @type var object: _MetaTagish & Object
    object.to_meta_tags
  else
    # @type var object: Hash[String | Symbol, untyped]
    object
  end
  @meta_tags.deep_merge! normalize_open_graph(meta_tags)
end

#with_defaults(defaults = {}) { ... } ⇒ Object

Temporarily merges defaults with the current meta tags list and yields the block.

Parameters:

  • defaults (Hash) (defaults to: {})

    list of default meta tag attributes.

Yields:

Yield Returns:

Returns:

  • result of the block call.



51
52
53
54
55
56
57
# File 'lib/meta_tags/meta_tags_collection.rb', line 51

def with_defaults(defaults = {})
  old_meta_tags = @meta_tags
  @meta_tags = normalize_open_graph(defaults).deep_merge!(@meta_tags)
  yield
ensure
  @meta_tags = old_meta_tags
end