lib/csl/node.rb in csl-1.0.0.pre2 vs lib/csl/node.rb in csl-1.0.0.pre3
- old
+ new
@@ -27,23 +27,29 @@
def default_attributes
@default_attributes ||= {}
end
def constantize(name)
- klass = types.detect { |t| t.matches?(name) }
+ pattern = /#{name.to_s.tr('-', '')}$/i
+ klass = types.detect { |t| t.matches?(pattern) }
- if klass || !superclass.respond_to?(:constantize)
+ case
+ when !klass.nil?
klass
+ when nesting[-2].respond_to?(:constantize)
+ nesting[-2].constantize(name)
else
- superclass.constantize(name)
+ nil
end
end
- # @return [Boolean] whether or not the node's name matches the passed-in name
- def matches?(nodename)
- name.split(/::/)[-1].gsub(/([[:lower:]])([[:upper:]])/, '\1-\2').downcase == nodename
+ # @return [Boolean] whether or not the node's name matches the
+ # passed-in name pattern
+ def match?(name_pattern)
+ name_pattern === name
end
+ alias matches? match?
# Returns a new node with the passed in name and attributes.
def create(name, attributes = {}, &block)
klass = constantize(name)
@@ -197,11 +203,81 @@
f << (options[:compact] ? to_xml : pretty_print)
end
self
end
-
+
+ # Tests whether or not the Name matches the passed-in node name and
+ # attribute conditions; if a Hash is passed as a single argument,
+ # it is taken as the conditions parameter (the name parameter is
+ # automatically matches in this case).
+ #
+ # Whether or not the arguments match the node is determined as
+ # follows:
+ #
+ # 1. The name must match {#nodename}
+ # 2. All attribute name/value pairs passed as conditions must match
+ # the corresponding attributes of the node
+ #
+ # Note that only attributes present in the passed-in conditions
+ # influence the match – if you want to match only nodes that contain
+ # no other attributes than specified by the conditions, {#exact_match?}
+ # should be used instead.
+ #
+ # @see #exact_match?
+ #
+ # @param name [String,Regexp] must match the nodename
+ # @param conditions [Hash] the conditions
+ #
+ # @return [Boolean] whether or not the query matches the node
+ def match?(name = nodename, conditions = {})
+ name, conditions = match_conditions_for(name, conditions)
+
+ return false unless name === nodename
+ return true if conditions.empty?
+
+ conditions.values.zip(
+ attributes.values_at(*conditions.keys)).all? do |condition, value|
+ condition === value
+ end
+ end
+ alias matches? match?
+
+ # Tests whether or not the Name matches the passed-in node name and
+ # attribute conditions exactly; if a Hash is passed as a single argument,
+ # it is taken as the conditions parameter (the name parameter is
+ # automatically matches in this case).
+ #
+ # Whether or not the arguments match the node is determined as
+ # follows:
+ #
+ # 1. The name must match {#nodename}
+ # 2. All attribute name/value pairs of the node must match the
+ # corresponding pairs in the passed-in Hash
+ #
+ # Note that all node attributes are used by this method – if you want
+ # to match only a subset of attributes {#match?} should be used instead.
+ #
+ # @see #match?
+ #
+ # @param name [String,Regexp] must match the nodename
+ # @param conditions [Hash] the conditions
+ #
+ # @return [Boolean] whether or not the query matches the node exactly
+ def exact_match?(name = nodename, conditions = {})
+ name, conditions = match_conditions_for(name, conditions)
+
+ return false unless name === nodename
+ return true if conditions.empty?
+
+ conditions.values_at(*attributes.keys).zip(
+ attributes.values_at(*attributes.keys)).all? do |condition, value|
+ condition === value
+ end
+ end
+ alias matches_exactly? exact_match?
+
def <=>(other)
[nodename, attributes, children] <=> [other.nodename, other.attributes, other.children]
rescue
nil
end
@@ -223,11 +299,11 @@
["<#{[nodename, *attribute_assignments].join(' ')}/>"]
end
end
def inspect
- "#<#{[self.class.name, *attribute_assignments].join(' ')} children=[#{children.length}]>"
+ "#<#{[self.class.name, *attribute_assignments].join(' ')} children=[#{children.count}]>"
end
alias to_s pretty_print
@@ -237,9 +313,20 @@
each_pair.map { |name, value|
value.nil? ? nil: [name, value.to_s.inspect].join('=')
}.compact
end
+ def match_conditions_for(name, conditions)
+ case name
+ when Hash
+ conditions, name = name, nodename
+ when Symbol
+ name = name.to_s
+ end
+
+ [name, conditions.symbolize_keys]
+ end
+
end
class TextNode < Node
\ No newline at end of file