lib/micro_micro/collections/relationships_collection.rb in micromicro-2.0.1 vs lib/micro_micro/collections/relationships_collection.rb in micromicro-3.0.0
- old
+ new
@@ -1,33 +1,111 @@
# frozen_string_literal: true
module MicroMicro
module Collections
class RelationshipsCollection < BaseCollection
+ class RelationshipsCollectionSearch
+ def search(relationships, **args, &block)
+ relationships.select { |relationship| relationship_matches_conditions?(relationship, **args, &block) }
+ end
+
+ private
+
+ def relationship_matches_conditions?(relationship, **args)
+ return yield(relationship) if args.none?
+
+ args.all? { |key, value| (Array(relationship.public_send(key.to_sym)) & Array(value)).any? }
+ end
+ end
+
+ private_constant :RelationshipsCollectionSearch
+
+ # Return the first {MicroMicro::Relationship} from a search.
+ #
+ # @see #where
+ #
+ # @param (see #where)
+ # @yieldparam (see #where))
+ # @return [MicroMicro::Relationship, nil]
+ def find_by(**args, &block)
+ where(**args, &block).first
+ end
+
+ # Return a Hash of this collection's {MicroMicro::Relationship}s grouped
+ # by their +rel+ attribute value.
+ #
# @see https://microformats.org/wiki/microformats2-parsing#parse_a_hyperlink_element_for_rel_microformats
+ # microformats.org: microformats2 parsing specification § Parse a hyperlink element for rel microformats
#
# @return [Hash{Symbol => Array<String>}]
def group_by_rel
each_with_object(Hash.new { |hash, key| hash[key] = [] }) do |member, hash|
member.rels.each { |rel| hash[rel] << member.href }
end.symbolize_keys.transform_values(&:uniq)
end
+ # Return a Hash of this collection's {MicroMicro::Relationship}s grouped
+ # by their +href+ attribute value.
+ #
# @see https://microformats.org/wiki/microformats2-parsing#parse_a_hyperlink_element_for_rel_microformats
+ # microformats.org: microformats2 parsing specification § Parse a hyperlink element for rel microformats
#
# @return [Hash{Symbol => Hash{Symbol => Array, String}}]
def group_by_url
group_by(&:href).symbolize_keys.transform_values { |relationships| relationships.first.to_h.slice!(:href) }
end
+ # Retrieve an Array of this collection's unique {MicroMicro::Relationship}
+ # +rel+ attrivute values.
+ #
+ # @see MicroMicro::Relationship#rels
+ #
# @return [Array<String>]
def rels
@rels ||= flat_map(&:rels).uniq.sort
end
+ # Retrieve an Array of this collection's unique {MicroMicro::Relationship}
+ # +href+ attribute values.
+ #
+ # @see MicroMicro::Relationship#urls
+ #
# @return [Array<String>]
def urls
@urls ||= map(&:href).uniq.sort
+ end
+
+ # Search this collection for {MicroMicro::Relationship}s matching the
+ # given conditions.
+ #
+ # If a Hash is supplied, the returned collection will include
+ # {MicroMicro::Relationship}s matching _all_ conditions. Keys must be
+ # Symbols matching an instance method on {MicroMicro::Relationship} and
+ # values may be either a String or an Array of Strings.
+ #
+ # @example Search using a Hash with a String value
+ # MicroMicro.parse(markup, url).relationships.where(rels: 'webmention')
+ #
+ # @example Search using a Hash with an Array value
+ # MicroMicro.parse(markup, url).relationships.where(rels: ['me', 'webmention'])
+ #
+ # When passing a block, each {MicroMicro::Relationship} in this collection
+ # is yielded to the block and the returned collection will include
+ # {MicroMicro::Relationship}s that cause the block to return a value other
+ # than +false+ or +nil+.
+ #
+ # @example Search using a block
+ # MicroMicro.parse(markup, url).relationships.where do |relationship|
+ # relationship.href.match?(%r{https://webmention.io/.+})
+ # end
+ #
+ # @param args [Hash{Symbol => String, Array<String>}]
+ # @yieldparam relationship [MicroMicro::Relationship]
+ # @return [MicroMicro::Collections::RelationshipsCollection]
+ def where(**args, &block)
+ return self if args.none? && !block
+
+ self.class.new(RelationshipsCollectionSearch.new.search(self, **args, &block))
end
end
end
end