Class: URITemplate::RFC6570

Inherits:
Object
  • Object
show all
Extended by:
Forwardable, ClassMethods
Includes:
URITemplate
Defined in:
lib/uri_template/rfc6570.rb,
lib/uri_template/rfc6570/expression.rb,
lib/uri_template/rfc6570/regex_builder.rb

Overview

Note:

Most specs and examples refer to this class directly, because they are acutally refering to this specific implementation. If you just want uri templates, you should rather use the methods on URITemplate to create templates since they will select an implementation.

A uri template which should comply with the rfc 6570 ( tools.ietf.org/html/rfc6570 ).

Defined Under Namespace

Modules: ClassMethods Classes: Invalid, InvalidValue, RegexBuilder

Constant Summary

TYPE =
:rfc6570
NO_PROCESSING =

Specifies that no processing should be done upon extraction.

See Also:

[]
CONVERT_VALUES =

Specifies that the extracted values should be processed.

See Also:

[:convert_values]
CONVERT_RESULT =

Specifies that the extracted variable list should be processed.

See Also:

[:convert_result]
DEFAULT_PROCESSING =

Default processing. Means: convert values and the list itself.

See Also:

CONVERT_VALUES + CONVERT_RESULT

Constants included from URITemplate

HOST_REGEX, SCHEME_REGEX, URI_SPLIT, VERSIONS

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Methods included from ClassMethods

try_convert, valid?

Methods included from URITemplate

apply, coerce, coerce_first_arg, #concat, convert, #eq, #host?, new, #path_concat, #pattern, #relative?, resolve_class, #scheme?, #static_characters, try_convert, #variables

Constructor Details

- (RFC6570) initialize(pattern_or_tokens, options = {})

A new instance of RFC6570

Parameters:

  • pattern_or_tokens (String, Array)

    either a pattern as String or an Array of tokens

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

    some options

  • :lazy (Hash)

    a customizable set of options



265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/uri_template/rfc6570.rb', line 265

def initialize(pattern_or_tokens,options={})
  @options = options.dup.freeze
  if pattern_or_tokens.kind_of? String
    @pattern = pattern_or_tokens.dup
    @pattern.freeze
    unless @options[:lazy]
      self.tokens
    end
  elsif pattern_or_tokens.kind_of? Array
    @tokens = pattern_or_tokens.dup
    @tokens.freeze
  else
    raise ArgumentError, "Expected to receive a pattern string, but got #{pattern_or_tokens.inspect}"
  end
end

Instance Attribute Details

- (Object) options (readonly)

Returns the value of attribute options



260
261
262
# File 'lib/uri_template/rfc6570.rb', line 260

def options
  @options
end

Instance Method Details

- (Object) ===(uri)

Alias for to_r.=== . Tests whether this template matches a given uri.

Returns:

  • TrueClass, FalseClass



384
# File 'lib/uri_template/rfc6570.rb', line 384

def_delegators :to_r, :===

- (Object) expand(variables = {})

Note:

All keys of the supplied hash should be strings as anything else won't be recognised.

Note:

There are neither default values for variables nor will anything be raised if a variable is missing. Please read the spec if you want to know how undefined variables are handled.

Expands the template with the given variables. The expansion should be compatible to uritemplate spec rfc 6570 ( tools.ietf.org/html/rfc6570 ).

Examples:

URITemplate::RFC6570.new('{foo}').expand('foo'=>'bar') #=> 'bar'
URITemplate::RFC6570.new('{?args*}').expand('args'=>{'key'=>'value'}) #=> '?key=value'
URITemplate::RFC6570.new('{undef}').expand() #=> ''

Parameters:

  • variables (Hash)

Returns:

  • String



# File 'lib/uri_template/rfc6570.rb', line 281

- (Object) extract(uri_or_match, post_processing = DEFAULT_PROCESSING)

Note:

Don't expect that an extraction can fully recover the expanded variables. Extract rather generates a variable list which should expand to the uri from which it were extracted. In general the following equation should hold true:

a_tpl.expand( a_tpl.extract( an_uri ) ) == an_uri
Note:

The current implementation drops duplicated variables instead of checking them.

Extracts variables from a uri ( given as string ) or an instance of MatchData ( which was matched by the regexp of this template. The actual result depends on the value of post_processing. This argument specifies whether pair arrays should be converted to hashes.

Examples:

Default Processing

URITemplate::RFC6570.new('{var}').extract('value') #=> {'var'=>'value'}
URITemplate::RFC6570.new('{&args*}').extract('&a=1&b=2') #=> {'args'=>{'a'=>'1','b'=>'2'}}
URITemplate::RFC6570.new('{&arg,arg}').extract('&arg=1&arg=2') #=> {'arg'=>'2'}

No Processing

URITemplate::RFC6570.new('{var}').extract('value', URITemplate::RFC6570::NO_PROCESSING) #=> [['var','value']]
URITemplate::RFC6570.new('{&args*}').extract('&a=1&b=2', URITemplate::RFC6570::NO_PROCESSING) #=> [['args',[['a','1'],['b','2']]]]
URITemplate::RFC6570.new('{&arg,arg}').extract('&arg=1&arg=2', URITemplate::RFC6570::NO_PROCESSING) #=> [['arg','1'],['arg','2']]

Extraction cruces

two_lists = URITemplate::RFC6570.new('{listA*,listB*}')
uri = two_lists.expand('listA'=>[1,2],'listB'=>[3,4]) #=> "1,2,3,4"
variables = two_lists.extract( uri ) #=> {'listA'=>["1","2","3"],'listB'=>["4"]}
# However, like said in the note:
two_lists.expand( variables ) == uri #=> true

Parameters:

  • uri_or_match (String, MatchData)

    Uri_or_MatchData A uri or a matchdata from which the variables should be extracted.

  • post_processing (Array) (defaults to: DEFAULT_PROCESSING)

    Processing Specifies which processing should be done.

Raises:

  • Encoding::InvalidByteSequenceError when the given uri was not properly encoded.

  • Encoding::UndefinedConversionError when the given uri could not be converted to utf-8.

  • Encoding::CompatibilityError when the given uri could not be converted to utf-8.



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/uri_template/rfc6570.rb', line 349

def extract(uri_or_match, post_processing = DEFAULT_PROCESSING )
  if uri_or_match.kind_of? String
    m = self.to_r.match(uri_or_match)
  elsif uri_or_match.kind_of?(MatchData)
    if uri_or_match.respond_to?(:regexp) and uri_or_match.regexp != self.to_r
      raise ArgumentError, "Trying to extract variables from MatchData which was not generated by this template."
    end
    m = uri_or_match
  elsif uri_or_match.nil?
    return nil
  else
    raise ArgumentError, "Expected to receive a String or a MatchData, but got #{uri_or_match.inspect}."
  end
  if m.nil?
    return nil
  else
    result = extract_matchdata(m, post_processing)
    if block_given?
      return yield result
    end

    return result
  end
end

- (Object) extract_simple(uri_or_match)

Extracts variables without any proccessing. This is equivalent to #extract with options NO_PROCESSING.

See Also:



377
378
379
# File 'lib/uri_template/rfc6570.rb', line 377

def extract_simple(uri_or_match)
  extract( uri_or_match, NO_PROCESSING )
end

- (Object) level

Returns the level of this template according to the rfc 6570 ( tools.ietf.org/html/rfc6570#section-1.2 ). Higher level means higher complexity. Basically this is defined as:

  • Level 1: no operators, one variable per expansion, no variable modifiers

  • Level 2: '+' and '#' operators, one variable per expansion, no variable modifiers

  • Level 3: all operators, multiple variables per expansion, no variable modifiers

  • Level 4: all operators, multiple variables per expansion, all variable modifiers

Templates of lower levels might be convertible to other formats while templates of higher levels might be incompatible. Level 1 for example should be convertible to any other format since it just contains simple expansions.

Examples:

URITemplate::RFC6570.new('/foo/').level #=> 1
URITemplate::RFC6570.new('/foo{bar}').level #=> 1
URITemplate::RFC6570.new('/foo{#bar}').level #=> 2
URITemplate::RFC6570.new('/foo{.bar}').level #=> 3
URITemplate::RFC6570.new('/foo{bar,baz}').level #=> 3
URITemplate::RFC6570.new('/foo{bar:20}').level #=> 4
URITemplate::RFC6570.new('/foo{bar*}').level #=> 4


423
424
425
# File 'lib/uri_template/rfc6570.rb', line 423

def level
  tokens.map(&:level).max
end

- (Object) match(uri) { ... }

Alias for to_r.match . Matches this template against the given uri.

Yields:

  • MatchData

Returns:

  • MatchData, Object



390
# File 'lib/uri_template/rfc6570.rb', line 390

def_delegators :to_r, :match

- (Object) to_r

Compiles this template into a regular expression which can be used to test whether a given uri matches this template. This template is also used for #===.

Examples:

tpl = URITemplate::RFC6570.new('/foo/{bar}/')
regex = tpl.to_r
regex === '/foo/baz/' #=> true
regex === '/foz/baz/' #=> false

Returns:

  • Regexp



305
306
307
308
309
310
311
312
# File 'lib/uri_template/rfc6570.rb', line 305

def to_r
  @regexp ||= begin
    source = tokens.map(&:to_r_source)
    source.unshift('\A')
    source.push('\z')
    Regexp.new( source.join, Utils::KCODE_UTF8)
  end
end

- (Object) tokens

Returns an array containing a the template tokens.



428
429
430
# File 'lib/uri_template/rfc6570.rb', line 428

def tokens
  @tokens ||= tokenize!
end

- (Object) type

The type of this template.

Examples:

tpl1 = URITemplate::RFC6570.new('/foo')
tpl2 = URITemplate.new( tpl1.pattern, tpl1.type )
tpl1 == tpl2 #=> true

See Also:

  • URITemplate::RFC6570.{URITemplate{URITemplate#type}


400
401
402
# File 'lib/uri_template/rfc6570.rb', line 400

def type
  self.class::TYPE
end