Class: YANAPI::Query
- Inherits:
-
Object
- Object
- YANAPI::Query
- Defined in:
- lib/yanapi/query.rb
Direct Known Subclasses
Constant Summary collapse
- HOST =
'http://answers.yahooapis.com'- SERVICE =
'AnswersService'- SERVICE_VERSION =
'V1'- VALID_PARAMS =
[:appid, :output, :callback]
- MULTIVALUED_PARAMS =
[:region, :category_id, :category_name]
- REQUIRED_PARAMS =
[:appid]
- VALID_OUTPUT_FORMATS =
[nil, 'xml', 'php', 'rss', 'json']
Instance Method Summary collapse
-
#build_url(params) ⇒ Object
protected
It returns an URI::HTTP object containing the complete url for the request.
-
#check_params(params) ⇒ Object
protected
It checks params and returns a validated params hash.
-
#expand_params(params) ⇒ Object
protected
It expands multiple values to key-val pairs and returns a params array.
-
#get ⇒ Object
This is the main method.
-
#get_response(url) ⇒ Object
protected
It sends a HTTP request, rescues any external errors issuing an YANAPI::ExternalError, checks the HTTP code and fails if it is not 200.
-
#initialize(params) ⇒ Query
constructor
It accepts a two dimensional hash: => ‘questionSearch’, :query_params => {:appid => ‘YahooDemo’, :query => ‘Haus’}.
-
#prove_xml(xml_as_str) ⇒ Object
protected
It parses the input, checks for xml validity and proves if it is empty.
Constructor Details
#initialize(params) ⇒ Query
It accepts a two dimensional hash:
{:method => 'questionSearch', :query_params =>
{:appid => 'YahooDemo', :query => 'Haus'}}
24 25 26 27 28 29 |
# File 'lib/yanapi/query.rb', line 24 def initialize(params) @method = params[:method] @params = check_params(params[:query_params]) @url = build_url(@params) @output = @params[:output] || 'xml' end |
Instance Method Details
#build_url(params) ⇒ Object (protected)
It returns an URI::HTTP object containing the complete url for the request. Use <CGI>, not <URI>, the latter is somehow buggy.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/yanapi/query.rb', line 95 def build_url(params) = (params) # It is an array now! escaped_params = .map do |k, v| k = CGI.escape(k.to_s) v = CGI.escape(v.to_s) "#{k}=#{v}" end query = escaped_params.join('&') base_url = [HOST, SERVICE, SERVICE_VERSION, @method].join('/') url = base_url + '?' + query URI.parse(url) end |
#check_params(params) ⇒ Object (protected)
It checks params and returns a validated params hash.
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 |
# File 'lib/yanapi/query.rb', line 54 def check_params(params) # It requires <:appid> to be present. unless params.has_key?(:appid) fail UserError, 'APPID is missing!' end # It accepts only valid output formats. unless VALID_OUTPUT_FORMATS.include?(params[:output]) fail UserError, "The output type <#{params[:output]}> is not supported!" end # It rejects <:callback> for all output formats but <json>. if params[:output] != 'json' && params[:callback] fail UserError, "Output type #{params[:output]} is incompatible with <:callback>!" end # It accepts only unique values for every parameter other than: # * :category_id; # * :category_name; # * :region. # They can be strings, arrays or numbers: # :category_id => [123, 456, 789]. params.each_pair do |k, v| unless (v.kind_of?(String) || v.kind_of?(Fixnum) || v.kind_of?(Array)) fail(UserError, "The value type <#{v.class}> for the key <:#{k}> is wrong!") end if v.kind_of?(Array) unless MULTIVALUED_PARAMS.include?(k) fail UserError, "The value of <:#{k}> must, but is not unique!" end end end params end |
#expand_params(params) ⇒ Object (protected)
It expands multiple values to key-val pairs and returns a params array.
112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/yanapi/query.rb', line 112 def (params) = [] params.each_pair do |k, v| if v.instance_of?(Array) v.each { |val| << [k, val] } else << [k, v] end end .sort_by { |k, v| [k.to_s, v.to_s] } end |
#get ⇒ Object
This is the main method. It gets the body of the HTTP response and invokes the respective check. It returns the response or <nil> if the response is emtpy.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/yanapi/query.rb', line 34 def get http_response = get_response(@url) case @output when 'xml' prove_xml(http_response) when 'json' fail NotImplementedError, 'We do not handle JSON yet!' when 'php' fail NotImplementedError, 'We do not handle PHP yet!' when 'rss' fail NotImplementedError, 'We do not handle RSS yet!' end end |
#get_response(url) ⇒ Object (protected)
It sends a HTTP request, rescues any external errors issuing an YANAPI::ExternalError, checks the HTTP code and fails if it is not 200. Otherwise it returns the body of the HTTP response.
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/yanapi/query.rb', line 129 def get_response(url) begin http_response = Net::HTTP.get_response(url) rescue Net::HTTPError, SocketError, Timeout::Error, IOError => e fail ExternalError, e end case http_response when Net::HTTPSuccess http_response.body when Net::HTTPBadRequest, Net::HTTPForbidden, Net::HTTPServiceUnavailable # These errors are documented by Yahoo!. fail(ExternalError, http_response.header) else fail(ExternalError, "Unexpected HTTP response: #{http_response.header}.") end end |
#prove_xml(xml_as_str) ⇒ Object (protected)
It parses the input, checks for xml validity and proves if it is empty. It returns then <xml> as string or <nil> if the answer is emtpy.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/yanapi/query.rb', line 152 def prove_xml(xml_as_str) begin # Set the value to STRICT (0), otherwise no errors will be raised! xml = Nokogiri::XML::Document.parse(xml_as_str, nil, nil, 0) rescue Nokogiri::XML::SyntaxError fail(ContentError, 'Erroneous XML response!') end error = xml.at_xpath('/xmlns:Error', xml.root.namespaces) if error = 'The following errors were detected:' error.xpath('//xmlns:Message', xml.root.namespaces).each do |msg| << "\n" + msg.content end fail(ContentError, ) end question = xml.at_xpath('//xmlns:Question', xml.root.namespaces) question ? xml_as_str : nil end |