Skip to content

Loading…

Csv support #269

Merged
merged 5 commits into from

2 participants

@davidgg

Hi!

I think it will be nice to add CSV support. CSV is in the standard library and some analytic services returns the info as csv, that allows easy manipulation.

@davidgg

Sorry for the fixes, im a noob in cucumber.

@jnunemaker jnunemaker merged commit dadb283 into jnunemaker:master

1 check passed

Details default The Travis CI build passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 8, 2014
  1. @davidgg

    added CSV support

    davidgg committed
  2. @davidgg

    added CSV support

    davidgg committed
  3. @davidgg

    fix for travis lexic

    davidgg committed
  4. @davidgg

    fix for travis lexic

    davidgg committed
  5. @davidgg
This page is out of date. Refresh to see the latest.
View
5 bin/httparty
@@ -18,7 +18,7 @@ OptionParser.new do |o|
o.on("-f",
"--format [FORMAT]",
"Output format to use instead of pretty-print ruby: " +
- "plain, json or xml") do |f|
+ "plain, csv, json or xml") do |f|
opts[:output_format] = f.downcase.to_sym
end
@@ -107,6 +107,9 @@ else
require 'rexml/document'
REXML::Document.new(response.body).write(STDOUT, 2)
puts
+ when :csv
+ require 'csv'
+ puts CSV.parse(response.body).map{|row| row.to_s }
else
puts response
end
View
15 features/handles_multiple_formats.feature
@@ -14,6 +14,21 @@ Feature: Handles Multiple Formats
Then it should return a String
And the return value should match '<h1>Some HTML</h1>'
+ Scenario: A CSV service
+ Given a remote service that returns:
+ """
+ "Last Name","Name"
+ "jennings","waylon"
+ "cash","johnny"
+ """
+ And that service is accessed at the path '/service.csv'
+ And the response from the service has a Content-Type of 'application/csv'
+ When I call HTTParty#get with '/service.csv'
+ Then it should return an Array equaling:
+ | Last Name | Name |
+ | jennings | waylon |
+ | cash | johnny |
+
Scenario: A JSON service
Given a remote service that returns '{ "jennings": "waylon", "cash": "johnny" }'
And that service is accessed at the path '/service.json'
View
5 features/steps/httparty_response_steps.rb
@@ -29,6 +29,11 @@ def constantize(camel_cased_word)
end
end
+Then /it should return an Array equaling:/ do |array|
+ @response_from_httparty.should be_an_instance_of(Array)
+ @response_from_httparty.should eql array.raw
+end
+
Then /it should return a response with a (\d+) response code/ do |code|
@response_from_httparty.code.should eql(code.to_i)
end
View
5 features/steps/remote_service_steps.rb
@@ -3,6 +3,11 @@
Given "the response from the service has a body of '#{response_body}'"
end
+Given /^a remote service that returns:$/ do |response_body|
+ @handler = BasicMongrelHandler.new
+ @handler.response_body = response_body
+end
+
Given /a remote service that returns a (\d+) status code/ do |code|
@handler = BasicMongrelHandler.new
@handler.response_code = code
View
1 lib/httparty.rb
@@ -5,6 +5,7 @@
require 'zlib'
require 'multi_xml'
require 'json'
+require 'csv'
require 'httparty/module_inheritable_attributes'
require 'httparty/cookie_hash'
View
11 lib/httparty/parser.rb
@@ -1,5 +1,5 @@
module HTTParty
- # The default parser used by HTTParty, supports xml, json, html, and
+ # The default parser used by HTTParty, supports xml, json, html, csv and
# plain text.
#
# == Custom Parsers
@@ -45,7 +45,10 @@ class Parser
'application/javascript' => :plain,
'text/javascript' => :plain,
'text/html' => :html,
- 'text/plain' => :plain
+ 'text/plain' => :plain,
+ 'text/csv' => :csv,
+ 'application/csv' => :csv,
+ 'text/comma-separated-values' => :csv
}
# The response body of the request
@@ -113,6 +116,10 @@ def json
JSON.load(body, nil)
end
+ def csv
+ CSV.parse(body)
+ end
+
def html
body
end
View
2 spec/fixtures/twitter.csv
@@ -0,0 +1,2 @@
+"name","url","id","description","protected","screen_name","followers_count","profile_image_url","location"
+"Magic 8 Bot",,"17656026","ask me a question","false","magic8bot","90","http://s3.amazonaws.com/twitter_production/profile_images/65565851/8ball_large_normal.jpg",
View
5 spec/httparty/parser_spec.rb
@@ -156,5 +156,10 @@ def self.name; 'AtomParser'; end
it "parses plain text by simply returning the body" do
subject.send(:plain).should == 'body'
end
+
+ it "parses csv with CSV" do
+ CSV.should_receive(:parse).with('body')
+ subject.send(:csv)
+ end
end
end
View
24 spec/httparty/request_spec.rb
@@ -202,6 +202,24 @@
end
end
+ it 'should handle text/csv' do
+ ["text/csv", "text/csv; charset=iso8859-1"].each do |ct|
+ @request.send(:format_from_mimetype, ct).should == :csv
+ end
+ end
+
+ it 'should handle application/csv' do
+ ["application/csv", "application/csv; charset=iso8859-1"].each do |ct|
+ @request.send(:format_from_mimetype, ct).should == :csv
+ end
+ end
+
+ it 'should handle text/comma-separated-values' do
+ ["text/comma-separated-values", "text/comma-separated-values; charset=iso8859-1"].each do |ct|
+ @request.send(:format_from_mimetype, ct).should == :csv
+ end
+ end
+
it 'should handle text/javascript' do
["text/javascript", "text/javascript; charset=iso8859-1"].each do |ct|
@request.send(:format_from_mimetype, ct).should == :plain
@@ -231,6 +249,12 @@
@request.send(:parse_response, xml).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
end
+ it 'should handle csv automatically' do
+ csv=[%q["id","Name"],%q["1234","Foo Bar!"]].join("\n")
+ @request.options[:format] = :csv
+ @request.send(:parse_response, csv).should == [["id","Name"],["1234","Foo Bar!"]]
+ end
+
it 'should handle json automatically' do
json = %q[{"books": {"book": {"name": "Foo Bar!", "id": "1234"}}}]
@request.options[:format] = :json
View
15 spec/httparty_spec.rb
@@ -391,6 +391,11 @@ class MyParser < HTTParty::Parser
@klass.default_options[:format].should == :xml
end
+ it "should allow csv" do
+ @klass.format :csv
+ @klass.default_options[:format].should == :csv
+ end
+
it "should allow json" do
@klass.format :json
@klass.default_options[:format].should == :json
@@ -410,7 +415,7 @@ class MyParser < HTTParty::Parser
it 'should only print each format once with an exception' do
lambda do
@klass.format :foobar
- end.should raise_error(HTTParty::UnsupportedFormat, "':foobar' Must be one of: html, json, plain, xml")
+ end.should raise_error(HTTParty::UnsupportedFormat, "':foobar' Must be one of: csv, html, json, plain, xml")
end
it 'sets the default parser' do
@@ -703,6 +708,14 @@ def self.inherited(subclass)
}
end
+ it "should be able parse response type csv automatically" do
+ stub_http_response_with('twitter.csv')
+ profile = HTTParty.get('http://twitter.com/statuses/profile.csv')
+ profile.size.should == 2
+ profile[0].should == ["name","url","id","description","protected","screen_name","followers_count","profile_image_url","location"]
+ profile[1].should == ["Magic 8 Bot",nil,"17656026","ask me a question","false","magic8bot","90","http://s3.amazonaws.com/twitter_production/profile_images/65565851/8ball_large_normal.jpg",nil]
+ end
+
it "should not get undefined method add_node for nil class for the following xml" do
stub_http_response_with('undefined_method_add_node_for_nil.xml')
result = HTTParty.get('http://foobar.com')
Something went wrong with that request. Please try again.