lib/mustermann/expander.rb in mustermann-0.2.0 vs lib/mustermann/expander.rb in mustermann-0.3.0

- old
+ new

@@ -91,11 +91,11 @@ # @example casting all ActiveRecord objects to param # expander.cast(ActiveRecord::Base, &:to_param) # # @param [Array<Symbol, Regexp, #===>] type_matchers # To identify key/value pairs to match against. - # Regexps and Symbols match againg key, everything else matches against value. + # Regexps and Symbols match against key, everything else matches against value. # # @yield every key/value pair # @yieldparam key [Symbol] omitted if block takes less than 2 # @yieldparam value [Object] omitted if block takes no arguments # @yieldreturn [Hash{Symbol: Object}] will replace key/value pair with returned hash @@ -136,24 +136,53 @@ # # @return [String] expanded string # @raise [NotImplementedError] raised if expand is not supported. # @raise [Mustermann::ExpandError] raised if a value is missing or unknown def expand(behavior = nil, **values) - values = caster.cast(values) + behavior, values = nil, behavior if behavior.is_a? Hash + values = map_values(values) case behavior || additional_values when :raise then @api_expander.expand(values) when :ignore then with_rest(values) { |uri, rest| uri } when :append then with_rest(values) { |uri, rest| append(uri, rest) } else raise ArgumentError, "unknown behavior %p" % behavior end end + # @see Object#== + def ==(other) + return false unless other.class == self.class + other.patterns == patterns and other.additional_values == additional_values + end + + # @see Object#eql? + def eql?(other) + return false unless other.class == self.class + other.patterns.eql? patterns and other.additional_values.eql? additional_values + end + + # @see Object#hash + def hash + patterns.hash + additional_values.hash + end + + def expandable?(values) + return false unless values + expandable, _ = split_values(map_values(values)) + @api_expander.expandable? expandable + end + def with_rest(values) + expandable, non_expandable = split_values(values) + yield expand(:raise, slice(values, expandable)), slice(values, non_expandable) + end + + def split_values(values) expandable = @api_expander.expandable_keys(values.keys) non_expandable = values.keys - expandable - yield expand(:raise, slice(values, expandable)), slice(values, non_expandable) + [expandable, non_expandable] end def slice(hash, keys) Hash[keys.map { |k| [k, hash[k]] }] end @@ -162,8 +191,14 @@ return uri unless values and values.any? entries = values.map { |pair| pair.map { |e| @api_expander.escape(e, also_escape: /[\/\?#\&\=%]/) }.join(?=) } "#{ uri }#{ uri[??]??&:?? }#{ entries.join(?&) }" end - private :with_rest, :slice, :append, :caster + def map_values(values) + values = values.dup + @api_expander.keys.each { |key| values[key] ||= values.delete(key.to_s) if values.include? key.to_s } + caster.cast(values) + end + + private :with_rest, :slice, :append, :caster, :map_values, :split_values end end