ftp_service 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -16,6 +16,8 @@ tmtags
16
16
  ## PROJECT::GENERAL
17
17
  coverage
18
18
  rdoc
19
+ doc
19
20
  pkg
21
+ .yardoc
20
22
 
21
23
  ## PROJECT::SPECIFIC
@@ -0,0 +1,10 @@
1
+ # v0.2.0 (2010-03-08)
2
+
3
+ * Add `FtpService#write_request` and `FtpService#read_response` methods,
4
+ making this thing actually usable.
5
+
6
+ * Switch to Markdown + Yardoc for rdocs.
7
+
8
+ # v0.1.1 (2010-03-08)
9
+
10
+ * First version. Opens a connection but that's it. Useful, huh?
data/README.markdown ADDED
@@ -0,0 +1,37 @@
1
+ # FTP Service
2
+
3
+ An FTP Service is like a web service except stupid. You send your
4
+ request by uploading an xml file and get your response by downloading
5
+ another xml file. Have you ever had to deal with something like that? I
6
+ have.
7
+
8
+ RDocs on [rdoc.info](http://rdoc.info/projects/blaix/ftp_service).
9
+
10
+ Source code on [github](http://github.com/blaix/ftp_service).
11
+
12
+ ## Installation
13
+
14
+ gem install ftp_service
15
+
16
+ ## Usage
17
+
18
+ require 'ftp_service'
19
+
20
+ FtpService.open('host', 'user', 'pass') do |service|
21
+ path = '/the/remote/path'
22
+ service.write_request("#{path}/request.xml", '<foo>bar</foo>')
23
+ response = service.read_response("#{path}/response.xml")
24
+ end
25
+
26
+ * `read_response` will block while it polls the server waiting for a
27
+ response.
28
+ * Temp files are created for the local request and response files and
29
+ deleted when no longer needed.
30
+
31
+ For more details, see the
32
+ [RDocs](http://rdoc.info/projects/blaix/ftp_service) (sike they are
33
+ really yardocs!).
34
+
35
+ ## Copyright
36
+
37
+ Copyright (c) 2010 Justin Blake. See LICENSE for details.
data/Rakefile CHANGED
@@ -12,6 +12,7 @@ begin
12
12
  gem.authors = ["Justin Blake"]
13
13
  gem.add_development_dependency "rspec", ">= 1.2.9"
14
14
  gem.add_development_dependency "mocha", ">= 0.9.8"
15
+ gem.add_development_dependency "yard", ">= 0"
15
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
17
  end
17
18
  Jeweler::GemcutterTasks.new
@@ -25,6 +26,14 @@ Spec::Rake::SpecTask.new(:spec) do |spec|
25
26
  spec.spec_files = FileList['spec/**/*_spec.rb']
26
27
  end
27
28
 
29
+ namespace :spec do
30
+ Spec::Rake::SpecTask.new(:doc) do |spec|
31
+ spec.libs << 'lib' << 'spec'
32
+ spec.spec_files = FileList['spec/**/*_spec.rb']
33
+ spec.spec_opts << '--format specdoc'
34
+ end
35
+ end
36
+
28
37
  Spec::Rake::SpecTask.new(:rcov) do |spec|
29
38
  spec.libs << 'lib' << 'spec'
30
39
  spec.pattern = 'spec/**/*_spec.rb'
@@ -35,12 +44,13 @@ task :spec => :check_dependencies
35
44
 
36
45
  task :default => :spec
37
46
 
38
- require 'rake/rdoctask'
39
- Rake::RDocTask.new do |rdoc|
40
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
-
42
- rdoc.rdoc_dir = 'rdoc'
43
- rdoc.title = "ftp_service #{version}"
44
- rdoc.rdoc_files.include('README*')
45
- rdoc.rdoc_files.include('lib/**/*.rb')
47
+ begin
48
+ require 'yard'
49
+ YARD::Rake::YardocTask.new do |y|
50
+ y.files << '-' << 'CHANGELOG.*'
51
+ end
52
+ rescue LoadError
53
+ task :yardoc do
54
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
55
+ end
46
56
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
data/ftp_service.gemspec CHANGED
@@ -5,29 +5,31 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ftp_service}
8
- s.version = "0.1.1"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Justin Blake"]
12
- s.date = %q{2010-03-05}
12
+ s.date = %q{2010-03-08}
13
13
  s.description = %q{An FTP Service is like a web service except stupid. You send your request by uploading an xml file and get your response by downloading another xml file.}
14
14
  s.email = %q{justin@megablaix.com}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.rdoc"
17
+ "README.markdown"
18
18
  ]
19
19
  s.files = [
20
- ".document",
21
- ".gitignore",
20
+ ".gitignore",
21
+ "CHANGELOG.markdown",
22
22
  "LICENSE",
23
- "README.rdoc",
23
+ "README.markdown",
24
24
  "Rakefile",
25
25
  "VERSION",
26
26
  "ftp_service.gemspec",
27
27
  "lib/ftp_service.rb",
28
+ "lib/tempfile_helper.rb",
28
29
  "spec/ftp_service_spec.rb",
29
30
  "spec/spec.opts",
30
- "spec/spec_helper.rb"
31
+ "spec/spec_helper.rb",
32
+ "spec/tempfile_helper_spec.rb"
31
33
  ]
32
34
  s.homepage = %q{http://github.com/blaix/ftp_service}
33
35
  s.rdoc_options = ["--charset=UTF-8"]
@@ -36,7 +38,8 @@ Gem::Specification.new do |s|
36
38
  s.summary = %q{A class for dealing with the worst possible type of "web" service.}
37
39
  s.test_files = [
38
40
  "spec/ftp_service_spec.rb",
39
- "spec/spec_helper.rb"
41
+ "spec/spec_helper.rb",
42
+ "spec/tempfile_helper_spec.rb"
40
43
  ]
41
44
 
42
45
  if s.respond_to? :specification_version then
@@ -46,13 +49,16 @@ Gem::Specification.new do |s|
46
49
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
50
  s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
48
51
  s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
52
+ s.add_development_dependency(%q<yard>, [">= 0"])
49
53
  else
50
54
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
51
55
  s.add_dependency(%q<mocha>, [">= 0.9.8"])
56
+ s.add_dependency(%q<yard>, [">= 0"])
52
57
  end
53
58
  else
54
59
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
55
60
  s.add_dependency(%q<mocha>, [">= 0.9.8"])
61
+ s.add_dependency(%q<yard>, [">= 0"])
56
62
  end
57
63
  end
58
64
 
data/lib/ftp_service.rb CHANGED
@@ -1,17 +1,31 @@
1
1
  require 'net/ftp'
2
+ require 'tempfile_helper'
2
3
 
3
4
  # Class for dealing with a service that acts like a web service, except
4
5
  # over FTP. Meaning an xml request is uploaded as a file, and the
5
6
  # response xml is downloaded as another file.
7
+ #
8
+ # Typical usage:
9
+ #
10
+ # FtpService.open('host', 'user', 'pass') do |service|
11
+ # path = '/the/remote/path'
12
+ # service.write_request("#{path}/request.xml", '<foo>bar</foo>')
13
+ # response = service.read_response("#{path}/response.xml")
14
+ # end
15
+ #
16
+ # or (the sucky way):
17
+ #
18
+ # path = '/the/remote/path'
19
+ # service = FtpService.new('host', 'user', 'pass')
20
+ # service.write_request("#{path}/request.xml", '<foo>bar</foo>')
21
+ # response = service.read_response("#{path}/response.xml")
22
+ # service.close
6
23
  class FtpService
7
24
 
8
25
  # Open a connection to the FTP server and return an FtpService object.
9
- # The object must be closed explicitely.
10
- #
11
- # ftp_service = FtpService.open(host, user, pass)
12
- # ftp_service.write_request(path, request)
13
- # response = ftp_service.read_response(path)
14
- # ftp_service.close
26
+ # The object must be closed explicitely. See FtpServier#open for a
27
+ # better way to do this that will automatically close the connection,
28
+ # even if an exception is raised.
15
29
  def initialize(host, user, pass)
16
30
  @ftp = Net::FTP.open(host, user, pass)
17
31
  end
@@ -19,11 +33,6 @@ class FtpService
19
33
  # Open a connection and pass an FtpService instance to the block. The
20
34
  # instance will be closed when the block finishes, or when an
21
35
  # exception is raised.
22
- #
23
- # FtpService.open(host, user, pass) do |ftp_service|
24
- # ftp_service.write_request(path, request)
25
- # response = ftp_service.read_response(path)
26
- # end
27
36
  def self.open(host, user, pass)
28
37
  instance = new(host, user, pass)
29
38
  begin
@@ -33,6 +42,21 @@ class FtpService
33
42
  end
34
43
  end
35
44
 
45
+ # Write `request` to a local temp file and upload it to `remote_path`
46
+ # on the FTP server.
47
+ def write_request(request, remote_path)
48
+ tmp = TempfileHelper.write(request, 'request')
49
+ @ftp.puttextfile(tmp.path, remote_path)
50
+ end
51
+
52
+ # Download the file at `remote_path` from the FTP server to a local
53
+ # temp file and return its contents.
54
+ def read_response(remote_path)
55
+ TempfileHelper.read('response') do |tmp|
56
+ @ftp.gettextfile(remote_path, tmp.path)
57
+ end
58
+ end
59
+
36
60
  # Close the connection to the FTP server.
37
61
  def close
38
62
  @ftp.close
@@ -0,0 +1,20 @@
1
+ require 'tempfile'
2
+
3
+ module TempfileHelper
4
+ extend self
5
+
6
+ def read(name = nil)
7
+ tempfile = nil
8
+ name ||= Time.now.to_f
9
+ Tempfile.open(name) { |tempfile| yield(tempfile) }
10
+ File.read(tempfile.path)
11
+ end
12
+
13
+ def write(content, name = nil)
14
+ name ||= Time.now.to_f.to_s
15
+ file = Tempfile.new(name)
16
+ file.write(content)
17
+ file.close
18
+ file
19
+ end
20
+ end
@@ -7,35 +7,35 @@ describe "FtpService" do
7
7
  end
8
8
 
9
9
  describe '.new(host, user, pass)' do
10
- it 'should connect to the requested ftp server' do
10
+ it 'connects to the requested ftp server' do
11
11
  Net::FTP.expects(:open).with('host', 'user', 'pass').returns(@ftp)
12
12
  FtpService.new('host', 'user', 'pass')
13
13
  end
14
14
 
15
- it 'should yield an instance of the ftp service' do
15
+ it 'returns an instance of the ftp service' do
16
16
  service = FtpService.new('host', 'user', 'pass')
17
17
  service.should be_a(FtpService)
18
18
  end
19
19
  end
20
20
 
21
21
  describe '.open(host, user, pass)' do
22
- it 'should connect to the requested ftp server' do
22
+ it 'connects to the requested ftp server' do
23
23
  Net::FTP.expects(:open).with('host', 'user', 'pass').returns(@ftp)
24
24
  FtpService.open('host', 'user', 'pass') {}
25
25
  end
26
26
 
27
- it 'should yield an instance of the ftp service' do
27
+ it 'yields an instance of the ftp service' do
28
28
  service = nil
29
29
  FtpService.open('host', 'user', 'pass') { |service| }
30
30
  service.should be_a(FtpService)
31
31
  end
32
32
 
33
- it 'should automatically close the connection' do
33
+ it 'automatically closes the connection' do
34
34
  @ftp.expects(:close)
35
35
  FtpService.open('host', 'user', 'pass') {}
36
36
  end
37
37
 
38
- it 'should close the connection even if an exception is raised' do
38
+ it 'closes the connection even if an exception is raised' do
39
39
  @ftp.expects(:close)
40
40
  lambda {
41
41
  FtpService.open('host', 'user', 'pass') { raise "boom" }
@@ -43,8 +43,43 @@ describe "FtpService" do
43
43
  end
44
44
  end
45
45
 
46
+ describe '#write_request(path, request)' do
47
+ before do
48
+ @tempfile = stub('tempfile', :path => '/local/path')
49
+ @service = FtpService.new('host', 'user', 'pass')
50
+ end
51
+
52
+ it "saves the request to a temp file" do
53
+ TempfileHelper.expects(:write).with('request', optionally(anything)).returns(@tempfile)
54
+ @service.write_request('request', '/remote/path')
55
+ end
56
+
57
+ it "uploads the request to `path` on the FTP server" do
58
+ TempfileHelper.stubs(:write).returns(@tempfile)
59
+ @ftp.expects(:puttextfile).with('/local/path', '/remote/path')
60
+ @service.write_request('request', '/remote/path')
61
+ end
62
+ end
63
+
64
+ describe '#read_response(path)' do
65
+ before do
66
+ tempfile = stub('tempfile', :path => '/local/path')
67
+ TempfileHelper.stubs(:read).returns('response').yields(tempfile)
68
+ @service = FtpService.new('host', 'user', 'pass')
69
+ end
70
+
71
+ it "downloads the response at `path` from the FTP server" do
72
+ @ftp.expects(:gettextfile).with('/remote/path', '/local/path')
73
+ @service.read_response('/remote/path')
74
+ end
75
+
76
+ it "returns the contents of the downloaded response" do
77
+ @service.read_response('/remote/path').should == "response"
78
+ end
79
+ end
80
+
46
81
  describe '#close' do
47
- it 'should close the connection to the ftp server' do
82
+ it 'closes the connection to the ftp server' do
48
83
  @ftp.expects(:close)
49
84
  FtpService.new('host', 'user', 'pass').close
50
85
  end
@@ -0,0 +1,62 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'tempfile_helper'
3
+
4
+ describe "TempfileHelper" do
5
+ describe '.read([name]) { |tempfile| }' do
6
+ before do
7
+ @tempfile = nil
8
+ TempfileHelper.read { |@tempfile| }
9
+ end
10
+
11
+ it "yields a Tempfile object" do
12
+ @tempfile.should be_a(Tempfile)
13
+ end
14
+
15
+ it "closes the tempfile object after the block executes" do
16
+ @tempfile.should be_closed
17
+ end
18
+
19
+ it "closes the tempfile object even if an exception is raised" do
20
+ tempfile = nil
21
+ lambda {
22
+ TempfileHelper.read { |tempfile| raise "boom" }
23
+ }.should raise_error
24
+ tempfile.should be_closed
25
+ end
26
+
27
+ it "accepts an optional name for the tempfile" do
28
+ tempfile = nil
29
+ TempfileHelper.read('the_name') { |tempfile| }
30
+ tempfile.path.should include('the_name')
31
+ end
32
+
33
+ it "returns contents of the tempfile after the block is executed" do
34
+ TempfileHelper.read do |tempfile|
35
+ tempfile.write('the contents')
36
+ end.should == 'the contents'
37
+ end
38
+ end
39
+
40
+ describe '.write_temp_file(content[, name])' do
41
+ before do
42
+ @tempfile = TempfileHelper.write('the content')
43
+ end
44
+
45
+ it "returns a tempfile object" do
46
+ @tempfile.should be_a(Tempfile)
47
+ end
48
+
49
+ it "writes the passed content to the temp file" do
50
+ File.read(@tempfile.path).should == 'the content'
51
+ end
52
+
53
+ it "closes the tempfile object" do
54
+ @tempfile.should be_closed
55
+ end
56
+
57
+ it "accepts an optional name for the temp file" do
58
+ tempfile = TempfileHelper.write('the content', 'the_name')
59
+ tempfile.path.should include('the_name')
60
+ end
61
+ end
62
+ end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
- - 1
9
- version: 0.1.1
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Justin Blake
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-05 00:00:00 -05:00
17
+ date: 2010-03-08 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -45,6 +45,18 @@ dependencies:
45
45
  version: 0.9.8
46
46
  type: :development
47
47
  version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: yard
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ type: :development
59
+ version_requirements: *id003
48
60
  description: An FTP Service is like a web service except stupid. You send your request by uploading an xml file and get your response by downloading another xml file.
49
61
  email: justin@megablaix.com
50
62
  executables: []
@@ -53,19 +65,21 @@ extensions: []
53
65
 
54
66
  extra_rdoc_files:
55
67
  - LICENSE
56
- - README.rdoc
68
+ - README.markdown
57
69
  files:
58
- - .document
59
70
  - .gitignore
71
+ - CHANGELOG.markdown
60
72
  - LICENSE
61
- - README.rdoc
73
+ - README.markdown
62
74
  - Rakefile
63
75
  - VERSION
64
76
  - ftp_service.gemspec
65
77
  - lib/ftp_service.rb
78
+ - lib/tempfile_helper.rb
66
79
  - spec/ftp_service_spec.rb
67
80
  - spec/spec.opts
68
81
  - spec/spec_helper.rb
82
+ - spec/tempfile_helper_spec.rb
69
83
  has_rdoc: true
70
84
  homepage: http://github.com/blaix/ftp_service
71
85
  licenses: []
@@ -99,3 +113,4 @@ summary: A class for dealing with the worst possible type of "web" service.
99
113
  test_files:
100
114
  - spec/ftp_service_spec.rb
101
115
  - spec/spec_helper.rb
116
+ - spec/tempfile_helper_spec.rb
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
data/README.rdoc DELETED
@@ -1,40 +0,0 @@
1
- = FTP Service
2
-
3
- An FTP Service is like a web service except stupid. You send your
4
- request by uploading an xml file and get your response by downloading
5
- another xml file. Have you ever had to deal with something like that? I
6
- have.
7
-
8
- == Installation
9
-
10
- gem install ftp_service
11
-
12
- == Usage
13
-
14
- require 'ftp_service'
15
-
16
- FtpService.open('host', 'user', 'pass') do |service|
17
- path = '/the/remote/path'
18
- service.write_request("#{path}/request.xml", '<foo>bar</foo>')
19
- response = service.read_response("#{path}/response.xml")
20
- end
21
-
22
- * +read_response+ will block while it polls the server waiting for a
23
- response.
24
- * Temp files are created for the local request and response files and
25
- deleted when no longer needed.
26
-
27
- == Note on Patches/Pull Requests
28
-
29
- * Fork the project.
30
- * Make your feature addition or bug fix.
31
- * Add tests for it. This is important so I don't break it in a
32
- future version unintentionally.
33
- * Commit, do not mess with rakefile, version, or history. (if you want
34
- to have your own version, that is fine but bump version in a commit by
35
- itself I can ignore when I pull)
36
- * Send me a pull request. Bonus points for topic branches.
37
-
38
- == Copyright
39
-
40
- Copyright (c) 2010 Justin Blake. See LICENSE for details.