rbook-pacstream 0.6 → 0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|