rbook-pacstream 0.6 → 0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +8 -2
- data/lib/rbook/pacstream.rb +125 -33
- data/specs/pacstream_spec.rb +167 -0
- metadata +5 -4
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'rake/testtask'
|
|
6
6
|
require "rake/gempackagetask"
|
7
7
|
require 'spec/rake/spectask'
|
8
8
|
|
9
|
-
PKG_VERSION = "0.
|
9
|
+
PKG_VERSION = "0.7"
|
10
10
|
PKG_NAME = "rbook-pacstream"
|
11
11
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
12
12
|
RUBYFORGE_PROJECT = 'rbook'
|
@@ -24,7 +24,13 @@ task :cruise => [ :spec, :spec_report, :doc ]
|
|
24
24
|
desc "Run all rspec files"
|
25
25
|
Spec::Rake::SpecTask.new("spec") do |t|
|
26
26
|
t.spec_files = FileList['specs/**/*.rb']
|
27
|
-
|
27
|
+
|
28
|
+
if RUBY_VERSION >= "1.8.6" && RUBY_PATCHLEVEL >= 110
|
29
|
+
t.rcov = false
|
30
|
+
else
|
31
|
+
t.rcov = true
|
32
|
+
end
|
33
|
+
|
28
34
|
t.rcov_dir = (ENV['CC_BUILD_ARTIFACTS'] || 'doc') + "/rcov"
|
29
35
|
t.rcov_opts = ["--exclude","spec.*\.rb"]
|
30
36
|
end
|
data/lib/rbook/pacstream.rb
CHANGED
@@ -5,21 +5,131 @@ require 'tempfile'
|
|
5
5
|
|
6
6
|
module RBook
|
7
7
|
|
8
|
+
# an error indicating pacstream authentication issues
|
9
|
+
class PacstreamAuthError < RuntimeError; end
|
10
|
+
|
11
|
+
# an error indocating a problem with executing a pacstream command
|
12
|
+
class PacstreamCommandError < RuntimeError; end
|
13
|
+
|
14
|
+
# an error indicating a problem connecting to the pacstream server
|
15
|
+
class PacstreamConnectionError < RuntimeError; end
|
16
|
+
|
8
17
|
# Ruby class for sending and retrieving electronic orders
|
9
18
|
# via pacstream, a service run by the ECN Group
|
10
19
|
# (http://www.ecngroup.com.au/)
|
11
20
|
#
|
12
21
|
# = Basic Usage
|
13
22
|
#
|
14
|
-
# RBook::Pacstream.
|
23
|
+
# pac = RBook::Pacstream.new(:username => "myusername", :password => "mypass")
|
24
|
+
# pac.login
|
25
|
+
# pac.get(:orders) do |order|
|
15
26
|
# puts order
|
16
27
|
# end
|
28
|
+
# pac.get(:poacks) do |poa|
|
29
|
+
# puts poa
|
30
|
+
# end
|
31
|
+
# pac.put(:order, 1000, order_text)
|
32
|
+
# pac.quit
|
33
|
+
#
|
34
|
+
# = Alternative Usage
|
35
|
+
# RBook::Pacstream.open(:username => "myusername", :password => "mypass") do |pac|
|
36
|
+
# pac.get(:orders) do |order|
|
37
|
+
# puts order
|
38
|
+
# end
|
39
|
+
# pac.put(:order, 1000, order_text)
|
40
|
+
# end
|
17
41
|
class Pacstream
|
18
42
|
|
19
43
|
FILE_EXTENSIONS = { :orders => "ORD", :invoices => "ASN", :poacks => "POA" }
|
44
|
+
FILE_EXTENSIONS_SINGULAR = { :order => "ORD", :invoice => "ASN", :poack => "POA" }
|
45
|
+
|
46
|
+
def initialize(*args)
|
47
|
+
if args[0][:username].nil? && args[0][:password].nil?
|
48
|
+
raise ArgumentError, 'username and password must be specified'
|
49
|
+
end
|
50
|
+
|
51
|
+
@server = args[0][:servername].to_s || "pacstream.tedis.com.au"
|
52
|
+
@username = args[0][:username].to_s
|
53
|
+
@password = args[0][:password].to_s
|
54
|
+
end
|
20
55
|
|
21
|
-
#
|
22
|
-
#
|
56
|
+
# download all documents of a particular type from the pacstream server
|
57
|
+
#
|
58
|
+
# pac.get(:orders) do |order|
|
59
|
+
# puts order
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# WARNING: as soon as you download the order, the file is deleted from the server
|
63
|
+
# and cannot be retrieved again
|
64
|
+
def get(type, &block)
|
65
|
+
raise PacstreamCommandError, "No current session open" unless @ftp
|
66
|
+
raise ArgumentError, 'unrecognised type' unless FILE_EXTENSIONS.include?(type.to_sym)
|
67
|
+
|
68
|
+
# determine the filename pattern we're searching for
|
69
|
+
file_regexp = Regexp.new(".*\.#{FILE_EXTENSIONS[type.to_sym]}$", Regexp::IGNORECASE)
|
70
|
+
@ftp.chdir("outgoing/")
|
71
|
+
|
72
|
+
# loop over each file in the outgoing dir and check if it matches the file type we're after
|
73
|
+
@ftp.nlst.each do |file|
|
74
|
+
if file.match(file_regexp)
|
75
|
+
|
76
|
+
# for all matching files, download to a temp file, return the contents, then delete the file
|
77
|
+
tempfile = Tempfile.new("pacstream")
|
78
|
+
tempfile.close
|
79
|
+
@ftp.getbinaryfile(file, tempfile.path)
|
80
|
+
yield File.read(tempfile.path)
|
81
|
+
tempfile.unlink
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
@ftp.chdir("..")
|
86
|
+
end
|
87
|
+
|
88
|
+
# logs into to the pacstream server. Can raise several exceptions
|
89
|
+
# RBook::PacstreamConnectionError - Can't connect to server
|
90
|
+
# RBook::PacstreamAuthError - Invalid username or password
|
91
|
+
def login
|
92
|
+
begin
|
93
|
+
@ftp = Net::FTP.open(@server)
|
94
|
+
@ftp.login(@username, @password)
|
95
|
+
rescue Net::FTPPermError => e
|
96
|
+
raise PacstreamAuthError, e.message
|
97
|
+
rescue SocketError => e
|
98
|
+
raise PacstreamConnectionError, e.message
|
99
|
+
rescue Errno::ECONNREFUSED => e
|
100
|
+
raise PacstreamConnectionError, e.message
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# upload a file to the pacstream server
|
105
|
+
# type - :order, invoice or :poack
|
106
|
+
# ref - a reference number, used to name the file
|
107
|
+
# content - the content to upload
|
108
|
+
def put(type, ref, content)
|
109
|
+
raise PacstreamCommandError, "No current session open" unless @ftp
|
110
|
+
raise ArgumentError, 'unrecognised type' unless FILE_EXTENSIONS_SINGULAR.include?(type.to_sym)
|
111
|
+
|
112
|
+
remote_filename = "#{ref}.#{FILE_EXTENSIONS_SINGULAR[type.to_sym]}"
|
113
|
+
@ftp.chdir("incoming/")
|
114
|
+
|
115
|
+
tempfile = Tempfile.new("pacstream")
|
116
|
+
tempfile.write(content)
|
117
|
+
tempfile.close
|
118
|
+
|
119
|
+
@ftp.putbinaryfile(tempfile.path, remote_filename)
|
120
|
+
|
121
|
+
tempfile.unlink
|
122
|
+
|
123
|
+
@ftp.chdir("..")
|
124
|
+
end
|
125
|
+
|
126
|
+
# logout from the pacstream server
|
127
|
+
def quit
|
128
|
+
raise PacstreamCommandError, "No current session open" unless @ftp
|
129
|
+
@ftp.quit
|
130
|
+
end
|
131
|
+
|
132
|
+
# Deprecated way to download files from the pacstream server
|
23
133
|
#
|
24
134
|
# Document types available:
|
25
135
|
#
|
@@ -31,38 +141,20 @@ module RBook
|
|
31
141
|
# puts order
|
32
142
|
# end
|
33
143
|
def self.get(type = :orders, *args, &block)
|
34
|
-
|
35
|
-
|
144
|
+
pac = RBook::Pacstream.new(args[0])
|
145
|
+
pac.login
|
146
|
+
pac.get(type) do |content|
|
147
|
+
yield content
|
36
148
|
end
|
149
|
+
pac.quit
|
150
|
+
end
|
37
151
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
Net::FTP.open(server) do |ftp|
|
45
|
-
|
46
|
-
file_regexp = Regexp.new(".*\.#{FILE_EXTENSIONS[type.to_sym]}$", Regexp::IGNORECASE)
|
47
|
-
ftp.login(args[0][:username].to_s, args[0][:password].to_s)
|
48
|
-
ftp.chdir("outgoing/")
|
49
|
-
ftp.nlst.each do |file|
|
50
|
-
if file.match(file_regexp)
|
51
|
-
tempfile = Tempfile.new("pacstream")
|
52
|
-
tempfile.close
|
53
|
-
ftp.getbinaryfile(file, tempfile.path)
|
54
|
-
yield File.read(tempfile.path)
|
55
|
-
tempfile.unlink
|
56
|
-
end
|
57
|
-
end
|
58
|
-
transaction_complete = true
|
59
|
-
#ftp.quit
|
60
|
-
end
|
61
|
-
rescue EOFError
|
62
|
-
raise "Connection terminated by remote server" unless transaction_complete
|
63
|
-
rescue Net::FTPPermError
|
64
|
-
raise "Error while communicating with the pacstream server"
|
65
|
-
end
|
152
|
+
# Alternative, block syntax. See notes at the top of the class for usage
|
153
|
+
def self.open(*args, &block)
|
154
|
+
pac = RBook::Pacstream.new(args[0])
|
155
|
+
pac.login
|
156
|
+
yield pac
|
157
|
+
pac.quit
|
66
158
|
end
|
67
159
|
end
|
68
160
|
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../vendor')
|
3
|
+
|
4
|
+
require 'rbook/pacstream'
|
5
|
+
require 'not_a_mock'
|
6
|
+
require 'rubygems'
|
7
|
+
require 'spec'
|
8
|
+
|
9
|
+
Spec::Runner.configure do |config|
|
10
|
+
config.mock_with NotAMock::RspecMockFrameworkAdapter
|
11
|
+
end
|
12
|
+
|
13
|
+
context "The pacstream class" do
|
14
|
+
|
15
|
+
setup do
|
16
|
+
@options = {:servername => "127.0.0.1",
|
17
|
+
:username => "test",
|
18
|
+
:password => "pass"}
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
specify "should open and close an ftp connection when login and logout are called in the right order" do
|
23
|
+
# prevent a real ftp session from being opened. If the lib attempts to open
|
24
|
+
# a connection, just return a stubbed class
|
25
|
+
ftp = Net::FTP.stub_instance(:login => true, :quit => true)
|
26
|
+
Net::FTP.stub_method(:new => ftp, :open => ftp)
|
27
|
+
|
28
|
+
pac = RBook::Pacstream.new(@options)
|
29
|
+
pac.login
|
30
|
+
pac.quit
|
31
|
+
|
32
|
+
Net::FTP.should have_received(:open).once.with(@options[:servername])
|
33
|
+
ftp.should have_received(:login).once.with(@options[:username], @options[:password])
|
34
|
+
ftp.should have_received(:quit).once.without_args
|
35
|
+
end
|
36
|
+
|
37
|
+
specify "should return the contents of a invoice when looping over all available invoices's" do
|
38
|
+
# prevent a real ftp session from being opened. If the lib attempts to open
|
39
|
+
# a connection, just return a stubbed class
|
40
|
+
# this stub will allow the user to call chdir, and pretends that there is a single invoice available
|
41
|
+
# for download
|
42
|
+
ftp = Net::FTP.stub_instance(:login => true, :chdir => true, :nlst => ["1.ASN"], :getbinaryfile => true, :quit => true)
|
43
|
+
Net::FTP.stub_method(:new => ftp, :open => ftp)
|
44
|
+
File.stub_method(:read => "this is an invoice")
|
45
|
+
|
46
|
+
pac = RBook::Pacstream.new(@options)
|
47
|
+
pac.login
|
48
|
+
pac.get(:invoices) do |ord|
|
49
|
+
ord.should eql("this is an invoice")
|
50
|
+
end
|
51
|
+
pac.quit
|
52
|
+
|
53
|
+
ftp.should have_received(:chdir).twice
|
54
|
+
ftp.should have_received(:nlst).once.without_args
|
55
|
+
ftp.should have_received(:getbinaryfile).once
|
56
|
+
end
|
57
|
+
|
58
|
+
specify "should return the contents of an order when looping over all available orders" do
|
59
|
+
# prevent a real ftp session from being opened. If the lib attempts to open
|
60
|
+
# a connection, just return a stubbed class
|
61
|
+
# this stub will allow the user to call chdir, and rpretends that there is a single order available
|
62
|
+
# for download
|
63
|
+
ftp = Net::FTP.stub_instance(:login => true, :chdir => true, :nlst => ["1.ORD"], :getbinaryfile => true, :quit => true)
|
64
|
+
Net::FTP.stub_method(:new => ftp, :open => ftp)
|
65
|
+
File.stub_method(:read => "this is an order")
|
66
|
+
|
67
|
+
pac = RBook::Pacstream.new(@options)
|
68
|
+
pac.login
|
69
|
+
pac.get(:orders) do |ord|
|
70
|
+
ord.should eql("this is an order")
|
71
|
+
end
|
72
|
+
pac.quit
|
73
|
+
|
74
|
+
ftp.should have_received(:chdir).twice
|
75
|
+
ftp.should have_received(:nlst).once.without_args
|
76
|
+
ftp.should have_received(:getbinaryfile).once
|
77
|
+
end
|
78
|
+
|
79
|
+
specify "should return the contents of a POA when looping over all available poa's" do
|
80
|
+
# prevent a real ftp session from being opened. If the lib attempts to open
|
81
|
+
# a connection, just return a stubbed class
|
82
|
+
# this stub will allow the user to call chdir, and pretends that there is a single poa available
|
83
|
+
# for download
|
84
|
+
ftp = Net::FTP.stub_instance(:login => true, :chdir => true, :nlst => ["1.POA"], :getbinaryfile => true, :quit => true)
|
85
|
+
Net::FTP.stub_method(:new => ftp, :open => ftp)
|
86
|
+
File.stub_method(:read => "this is a poa")
|
87
|
+
|
88
|
+
pac = RBook::Pacstream.new(@options)
|
89
|
+
pac.login
|
90
|
+
pac.get(:poacks) do |ord|
|
91
|
+
ord.should eql("this is a poa")
|
92
|
+
end
|
93
|
+
pac.quit
|
94
|
+
|
95
|
+
ftp.should have_received(:chdir).twice
|
96
|
+
ftp.should have_received(:nlst).once.without_args
|
97
|
+
ftp.should have_received(:getbinaryfile).once
|
98
|
+
end
|
99
|
+
|
100
|
+
specify "should download a file correctly when the alternative, block syntax is used" do
|
101
|
+
# prevent a real ftp session from being opened. If the lib attempts to open
|
102
|
+
# a connection, just return a stubbed class
|
103
|
+
ftp = Net::FTP.stub_instance(:login => true, :chdir => true, :nlst => ["1.ORD"], :getbinaryfile => true, :quit => true)
|
104
|
+
Net::FTP.stub_method(:new => ftp, :open => ftp)
|
105
|
+
File.stub_method(:read => "this is an order")
|
106
|
+
|
107
|
+
RBook::Pacstream.open(@options) do |pac|
|
108
|
+
pac.get(:orders) do |ord|
|
109
|
+
ord.should eql("this is an order")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
Net::FTP.should have_received(:open).once.with(@options[:servername])
|
114
|
+
ftp.should have_received(:login).once.with(@options[:username], @options[:password])
|
115
|
+
ftp.should have_received(:chdir).twice
|
116
|
+
ftp.should have_received(:nlst).once.without_args
|
117
|
+
ftp.should have_received(:getbinaryfile).once
|
118
|
+
ftp.should have_received(:quit).once.without_args
|
119
|
+
end
|
120
|
+
|
121
|
+
specify "should raise an exception if incorrect login details are provided" do
|
122
|
+
# prevent a real ftp session from being opened. If the lib attempts to open
|
123
|
+
# a connection, just return a stubbed class
|
124
|
+
ftp = Net::FTP.stub_instance(:login => Net::FTPPermError.new("530 incorrect login. not logged in."))
|
125
|
+
Net::FTP.stub_method(:new => ftp, :open => ftp)
|
126
|
+
|
127
|
+
pac = RBook::Pacstream.new(@options)
|
128
|
+
lambda { pac.login }.should raise_error(RBook::PacstreamAuthError)
|
129
|
+
end
|
130
|
+
|
131
|
+
specify "should raise an exception if an invalid server is provided" do
|
132
|
+
# prevent a real ftp session from being opened. If the lib attempts to open
|
133
|
+
# a connection, just return a stubbed class
|
134
|
+
ftp = Net::FTP.stub_instance(:login => SocketError.new("getaddrinfo: Name or service not known"))
|
135
|
+
Net::FTP.stub_method(:new => ftp, :open => ftp)
|
136
|
+
|
137
|
+
pac = RBook::Pacstream.new(@options)
|
138
|
+
lambda { pac.login }.should raise_error(RBook::PacstreamConnectionError)
|
139
|
+
end
|
140
|
+
|
141
|
+
specify "should save an order to the server" do
|
142
|
+
# prevent a real ftp session from being opened. If the lib attempts to open
|
143
|
+
# a connection, just return a stubbed class
|
144
|
+
# this stub will allow the user to call chdir, and pretends that there is a single poa available
|
145
|
+
# for download
|
146
|
+
ftp = Net::FTP.stub_instance(:login => true, :chdir => true, :putbinaryfile => true, :quit => true)
|
147
|
+
Net::FTP.stub_method(:new => ftp, :open => ftp)
|
148
|
+
|
149
|
+
pac = RBook::Pacstream.new(@options)
|
150
|
+
pac.login
|
151
|
+
pac.put(:order, 1, "order content")
|
152
|
+
pac.quit
|
153
|
+
|
154
|
+
ftp.should have_received(:chdir).twice
|
155
|
+
ftp.should have_received(:putbinaryfile).once
|
156
|
+
end
|
157
|
+
|
158
|
+
specify "should raise an exception if quit is called before login" do
|
159
|
+
# prevent a real ftp session from being opened. If the lib attempts to open
|
160
|
+
# a connection, just return a stubbed class
|
161
|
+
ftp = Net::FTP.stub_instance(:login => true, :quit => true)
|
162
|
+
Net::FTP.stub_method(:new => ftp, :open => ftp)
|
163
|
+
|
164
|
+
pac = RBook::Pacstream.new(@options)
|
165
|
+
lambda { pac.quit }.should raise_error(RBook::PacstreamCommandError)
|
166
|
+
end
|
167
|
+
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: rbook-pacstream
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "0.
|
7
|
-
date: 2007-10-
|
6
|
+
version: "0.7"
|
7
|
+
date: 2007-10-24 00:00:00 +10:00
|
8
8
|
summary: A library for interaction with the PACSTREAM service
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -32,12 +32,13 @@ files:
|
|
32
32
|
- examples/pacstream.rb
|
33
33
|
- lib/rbook
|
34
34
|
- lib/rbook/pacstream.rb
|
35
|
+
- specs/pacstream_spec.rb
|
35
36
|
- Rakefile
|
36
37
|
- README
|
37
38
|
- COPYING
|
38
39
|
- LICENSE
|
39
|
-
test_files:
|
40
|
-
|
40
|
+
test_files:
|
41
|
+
- specs/pacstream_spec.rb
|
41
42
|
rdoc_options:
|
42
43
|
- --title
|
43
44
|
- pacstream Documentation
|