Class: Nanoc::Core::IdentifiableCollectionView

Inherits:
View
  • Object
show all
Includes:
Enumerable
Defined in:
lib/nanoc/core/views/identifiable_collection_view.rb

Constant Summary collapse

NOTHING =
Object.new

Instance Method Summary collapse

Methods inherited from View

#_context, #frozen?, #inspect

Methods included from ContractsSupport

enabled?, included, setup_once, warn_about_performance

Constructor Details

#initialize(objects, context) ⇒ IdentifiableCollectionView

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of IdentifiableCollectionView.



11
12
13
14
# File 'lib/nanoc/core/views/identifiable_collection_view.rb', line 11

def initialize(objects, context)
  super(context)
  @objects = objects
end

Instance Method Details

#[](string) ⇒ nil, #identifier #[](regex) ⇒ nil, #identifier

Overloads:

  • #[](string) ⇒ nil, #identifier

    Finds the object whose identifier matches the given string.

    If the glob syntax is enabled, the string can be a glob, in which case this method finds the first object that matches the given glob.

    Parameters:

    Returns:

    • (nil)

      if no object matches the string

    • (#identifier)

      if an object was found

  • #[](regex) ⇒ nil, #identifier

    Finds the object whose identifier matches the given regular expression.

    Parameters:

    • regex (Regex)

    Returns:

    • (nil)

      if no object matches the regex

    • (#identifier)

      if an object was found



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/nanoc/core/views/identifiable_collection_view.rb', line 127

def [](arg)
  # The argument to #[] fall in two categories: exact matches, and
  # patterns. An example of an exact match is '/about.md', while an
  # example of a pattern is '/about.*'.
  #
  # If a Nanoc::Core::Identifier is given, we know it will need to be an
  # exact match. If a String is given, it could be either. If a Regexp is
  # given, we know it’s a pattern match.
  #
  # If we have a pattern match, create a dependency on the item
  # collection, with a `raw_content` property that contains the pattern.
  # If we have an exact match, do nothing -- there is no reason to create
  # a dependency on the item itself, because accessing that item
  # (attributes, compiled content, …) will create the dependency later.

  object_from_exact_match = nil
  object_from_pattern_match = nil

  case arg
  when Nanoc::Core::Identifier
    # Can only be an exact match
    object_from_exact_match = @objects.object_with_identifier(arg)
  when String
    # Can be an exact match, or a pattern match
    tmp = @objects.object_with_identifier(arg)
    if tmp
      object_from_exact_match = tmp
    else
      object_from_pattern_match = @objects.object_matching_glob(arg)
    end
  when Regexp
    # Can only be a pattern match
    object_from_pattern_match = @objects.find do |i|
      i.identifier.to_s =~ arg
    end
  else
    raise ArgumentError,
          "Unexpected argument #{arg.class} to []: Can only pass " \
          'strings, identfiers, and regular expressions'
  end

  unless object_from_exact_match
    # We got this object from a pattern match. Create a dependency with
    # this pattern, because if the objects matching this pattern change,
    # then the result of #[] will change too.
    #
    # NOTE: object_from_exact_match can also be nil, but in that case
    # we still need to create a dependency.

    prop_attribute =
      case arg
      when Identifier
        [arg.to_s]
      when String, Regexp
        [arg]
      end

    @context.dependency_tracker.bounce(
      _unwrap,
      raw_content: prop_attribute,
    )
  end

  object = object_from_exact_match || object_from_pattern_match
  object && view_class.new(object, @context)
end

#_unwrapObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



17
18
19
# File 'lib/nanoc/core/views/identifiable_collection_view.rb', line 17

def _unwrap
  @objects
end

#each {|object| ... } ⇒ self

Calls the given block once for each object, passing that object as a parameter.

Yield Parameters:

  • object (#identifier)

Yield Returns:

  • (void)

Returns:

  • (self)


36
37
38
39
40
# File 'lib/nanoc/core/views/identifiable_collection_view.rb', line 36

def each
  @context.dependency_tracker.bounce(_unwrap, raw_content: true)
  @objects.each { |i| yield view_class.new(i, @context) }
  self
end

#find_all(arg = NOTHING) ⇒ Enumerable

Finds all objects whose identifier matches the given argument.

Parameters:

  • arg (String, Regex) (defaults to: NOTHING)

Returns:

  • (Enumerable)


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/nanoc/core/views/identifiable_collection_view.rb', line 53

def find_all(arg = NOTHING, &)
  if NOTHING.equal?(arg)
    @context.dependency_tracker.bounce(_unwrap, raw_content: true)
    return @objects.map { |i| view_class.new(i, @context) }.select(&)
  end

  prop_attribute =
    case arg
    when String, Nanoc::Core::Identifier
      [arg.to_s]
    when Regexp
      [arg]
    else
      true
    end

  @context.dependency_tracker.bounce(_unwrap, raw_content: prop_attribute)
  @objects.find_all(arg).map { |i| view_class.new(i, @context) }
end

#sizeInteger

Returns:

  • (Integer)


43
44
45
46
# File 'lib/nanoc/core/views/identifiable_collection_view.rb', line 43

def size
  @context.dependency_tracker.bounce(_unwrap, raw_content: true)
  @objects.size
end

#view_classObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method is abstract.

Raises:

  • (NotImplementedError)


24
25
26
# File 'lib/nanoc/core/views/identifiable_collection_view.rb', line 24

def view_class
  raise NotImplementedError
end

#where(**hash) ⇒ Enumerable

Finds all objects that have the given attribute key/value pair.

Examples:


@items.where(kind: 'article')
@items.where(kind: 'article', year: 2020)

Returns:

  • (Enumerable)


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/nanoc/core/views/identifiable_collection_view.rb', line 81

def where(**hash)
  unless Nanoc::Core::Feature.enabled?(Nanoc::Core::Feature::WHERE)
    raise(
      Nanoc::Core::TrivialError,
      '#where is experimental, and not yet available unless the ' \
      'corresponding feature flag is turned on. Set the ' \
      '`NANOC_FEATURES` environment variable to `where` to enable ' \
      'its usage. (Alternatively, set the environment variable to ' \
      '`all` to turn on all feature flags.)',
    )
  end

  @context.dependency_tracker.bounce(_unwrap, attributes: hash)

  # IDEA: Nanoc could remember (from the previous compilation) how many
  # times #where is called with a given attribute key, and memoize the
  # key-to-identifiers list.
  found_objects = @objects.select do |i|
    hash.all? { |k, v| i.attributes[k] == v }
  end

  found_objects.map { |i| view_class.new(i, @context) }
end