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) case format.to_s when 'json' begin JSON.decode(value) rescue JSON.backend::ParseError raise OEmbed::ParseError, $!.message end when 'xml' begin XML.decode(value) rescue XML.backend::ParseError raise OEmbed::ParseError, $!.message end 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"=>"Cool's\n the \"word\"!", } given_value = case backend_module.to_s when /OEmbed::Formatter::JSON::Backends::/ <<-JSON {"version":"1.0", "string":"test", "int":42,"html":"Cool's\\n the \\"word\\"\\u0021"} JSON when /OEmbed::Formatter::XML::Backends::/ <<-XML 1.0 test 42 <i>Cool's</i>\n the "word"! 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 end end