File: formatter.rb

package info (click to toggle)
ruby-oembed 0.18.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 356 kB
  • sloc: ruby: 1,148; makefile: 3
file content (102 lines) | stat: -rw-r--r-- 3,288 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
require 'oembed/formatter/base'
require 'oembed/formatter/json'
require 'oembed/formatter/xml'

module OEmbed
  # Takes the raw response from an oEmbed server and turns it into a nice Hash of data.
  module Formatter
    
    class << self
      # Returns the default format for OEmbed::Provider requests as a String.
      def default
        # Listed in order of preference.
        %w{json xml}.detect { |type| supported?(type) rescue false }
      end
      
      # Given the name of a format we want to know about (e.g. 'json'), returns 
      # true if there is a valid backend. If there is no backend, raises
      # OEmbed::FormatNotSupported.
      def supported?(format)
        case format.to_s
        when 'json'
          JSON.supported?
        when 'xml'
          XML.supported?
        else
          raise OEmbed::FormatNotSupported, format
        end
      end

      # Convert the given value into a nice Hash of values. The format should
      # be the name of the response format (e.g. 'json'). The value should be
      # a String or IO containing the response from an oEmbed server.
      # 
      # For example:
      #   value = '{"version": "1.0", "type": "link", "title": "Some Cool News Article"}'
      #   OEmbed::Formatter.decode('json', value)
      #   #=> {"version": "1.0", "type": "link", "title": "Some Cool News Article"}
      def decode(format, value)
        supported?(format)
        
        begin
          case format.to_s
          when 'json'
            begin
              JSON.decode(value)
            rescue JSON.backend.parse_error
              raise OEmbed::ParseError, $!.message
            end
          when 'xml'
            begin
              XML.decode(value)
            rescue XML.backend.parse_error
              raise OEmbed::ParseError, $!.message
            end
          end
        rescue
          raise OEmbed::ParseError, "#{$!.class}: #{$!.message}"
        end
      end
      
      # Test the given backend to make sure it parses known values correctly.
      # The backend_module should be either a JSON or XML backend.
      def test_backend(backend_module)
        expected = {
          "version"=>1.0,
          "string"=>"test",
          "int"=>42,
          "html"=>"<i>Cool's</i>\n the \"word\"!",
        }
        
        given_value = case backend_module.to_s
        when /OEmbed::Formatter::JSON::Backends::/
          <<-JSON
{"version":"1.0", "string":"test", "int":42,"html":"<i>Cool's</i>\\n the \\"word\\"\\u0021"}
          JSON
        when /OEmbed::Formatter::XML::Backends::/
          <<-XML
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<oembed>
  <version>1.0</version>
  <string>test</string>
  <int>42</int>
  <html>&lt;i&gt;Cool's&lt;/i&gt;\n the &quot;word&quot;&#x21;</html>
</oembed>
          XML
        else
          nil
        end
        
        actual = backend_module.decode(given_value)
        
        # For the test to be true the actual output Hash should have the
        # exact same list of keys _and_ the values should be the same
        # if we ignoring typecasting.
        actual.keys.sort == expected.keys.sort &&
          !actual.detect { |key, value| value.to_s != expected[key].to_s }
      end
      
    end # self
    
  end
end