click_and_send 0.0.4 → 0.0.5

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/.gitignore CHANGED
@@ -9,6 +9,7 @@ _yardoc
9
9
  coverage
10
10
  doc/
11
11
  lib/bundler/man
12
+ log/*.log
12
13
  pkg
13
14
  rdoc
14
15
  spec/fixtures/config.yml
data/README.md CHANGED
@@ -1,10 +1,12 @@
1
- # ClickAndSend
1
+ ClickAndSend
2
+ ============
2
3
 
3
4
  Ruby adapter for Australia Post's [ClickAndSend](http://www.clickandsend.com.au/) API.
4
5
 
5
6
  [![Build Status](https://secure.travis-ci.org/zubin/click_and_send.png)](http://travis-ci.org/zubin/click_and_send)
6
7
 
7
- ## Installation
8
+ Installation
9
+ ------------
8
10
 
9
11
  Add this line to your application's Gemfile:
10
12
 
@@ -18,7 +20,8 @@ Or install it yourself as:
18
20
 
19
21
  $ gem install click_and_send
20
22
 
21
- ## Usage
23
+ Usage
24
+ -----
22
25
 
23
26
  Configure like this:
24
27
 
@@ -32,15 +35,30 @@ Configure like this:
32
35
  Note that the WSDL URL above is for ClickAndSend's staging environment.
33
36
 
34
37
  You should only need to call methods on the `ClickAndSend` class.
35
- Refer to the docs and acceptance tests for usage examples.
38
+ Refer to ClickAndSend docs and acceptance tests for usage examples.
36
39
 
37
- ## Gotchas
40
+ Optionally configure a logger. It defaults to a standard Logger instance writing to log/click\_and\_send.log or
41
+ Rails.logger when applicable.
42
+
43
+ # Set logfile
44
+ ClickAndSend.configure do |c|
45
+ c.logfile = 'path/to/my/logfile'
46
+ end
47
+
48
+ # Custom logger
49
+ ClickAndSend.configure do |c|
50
+ c.logger = MyApp.logger
51
+ end
52
+
53
+ Gotchas
54
+ -------
38
55
 
39
56
  Order is important for ClickAndSend API data structures. Therefore, under ruby 1.8, use
40
57
  [`ActiveSupport::OrderedHash`](http://rdoc.info/gems/activesupport/ActiveSupport/OrderedHash.html) instead of a regular
41
58
  hash.
42
59
 
43
- ## Contributing
60
+ Contributing
61
+ ------------
44
62
 
45
63
  1. Fork it
46
64
  2. Create your feature branch (`git checkout -b my-new-feature`)
@@ -58,7 +58,7 @@ module ClickAndSend
58
58
 
59
59
  def find_tracking_numbers(refs)
60
60
  item_summary.inject({}) do |hash,item|
61
- if refs.include?(item[:cust_transaction_id])
61
+ if item.kind_of?(Hash) && refs.include?(item[:cust_transaction_id])
62
62
  hash[item[:cust_transaction_id]] ||= []
63
63
  hash[item[:cust_transaction_id]] << item[:tracking_number]
64
64
  end
@@ -70,8 +70,18 @@ module ClickAndSend
70
70
  Request::ItemSummary.new.result.fetch(:item_summary_transaction)
71
71
  end
72
72
 
73
+ def logger
74
+ @logger ||= begin
75
+ configuration.logger or if rails? && !configured_logfile
76
+ Rails.logger
77
+ else
78
+ Logger.new(logfile)
79
+ end
80
+ end
81
+ end
82
+
73
83
  def pdf_url(ref)
74
- tracking_numbers = find_tracking_numbers([ref]).fetch(ref)
84
+ tracking_numbers = find_tracking_numbers([ref])[ref] || {}
75
85
  case tracking_numbers.length
76
86
  when 0 then raise(Errors::APIError, "Not found: '#{ref}'")
77
87
  when 1 then tracking_number = tracking_numbers.first
@@ -87,11 +97,27 @@ module ClickAndSend
87
97
 
88
98
  private
89
99
 
100
+ def configured_logfile
101
+ ClickAndSend.configuration.logfile
102
+ end
103
+
90
104
  def ensure_keys_present(hash, required_keys)
91
105
  missing_keys = required_keys - hash.keys
92
106
  if missing_keys.any?
93
107
  raise(Errors::InvalidInput, "Missing: #{missing_keys.join(', ')}")
94
108
  end
95
109
  end
110
+
111
+ def gem_root
112
+ File.expand_path('..', File.dirname(__FILE__))
113
+ end
114
+
115
+ def logfile
116
+ configured_logfile || File.join(gem_root, 'log/click_and_send.log')
117
+ end
118
+
119
+ def rails?
120
+ defined?(Rails)
121
+ end
96
122
  end
97
123
  end
@@ -1,6 +1,6 @@
1
1
  module ClickAndSend
2
2
  class Configuration
3
- ATTRIBUTES = [:account_number, :api_version, :api_key, :user_name, :wsdl]
3
+ ATTRIBUTES = [:account_number, :api_version, :api_key, :logfile, :logger, :user_name, :wsdl]
4
4
  attr_accessor *ATTRIBUTES
5
5
 
6
6
  def initialize
@@ -8,11 +8,19 @@ module ClickAndSend
8
8
  end
9
9
 
10
10
  def errors
11
- Hash[ATTRIBUTES.collect { |attribute| [attribute, ("is required" if send(attribute).nil?)] }]
11
+ Hash[(ATTRIBUTES - optional_attributes).collect do |attribute|
12
+ [attribute, ("is required" if send(attribute).nil?)]
13
+ end]
12
14
  end
13
15
 
14
16
  def valid?
15
17
  errors.values.compact.empty?
16
18
  end
19
+
20
+ private
21
+
22
+ def optional_attributes
23
+ [:logfile, :logger]
24
+ end
17
25
  end
18
26
  end
@@ -90,7 +90,14 @@ module ClickAndSend
90
90
  end
91
91
 
92
92
  def response
93
- @response ||= Nori.parse(request.to_hash[key(:response)][key(:response)]).fetch(key(:answer))
93
+ @response ||= begin
94
+ raw = request.to_hash[key(:response)][key(:response)]
95
+ result = Nori.parse(raw)
96
+ result.fetch(key(:answer))
97
+ rescue IndexError => e
98
+ # binding.pry
99
+ raise
100
+ end
94
101
  end
95
102
 
96
103
  def request
@@ -1,3 +1,3 @@
1
1
  module ClickAndSend
2
- VERSION = '0.0.4'
2
+ VERSION = '0.0.5'
3
3
  end
data/log/.gitkeep ADDED
File without changes
@@ -1,8 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ClickAndSend, :acceptance do
4
- let(:item_details) { }
5
4
  before { load_config(:acceptance) }
5
+ after(:all) { cleanup }
6
6
 
7
7
  describe '.check_services' do
8
8
  subject { ClickAndSend.check_services(attributes_for(%w(Sender Receiver ItemDetails))) }
@@ -67,6 +67,8 @@ describe ClickAndSend, :acceptance do
67
67
  ClickAndSend.delete_items('DeleteItems' => items)
68
68
  end.to change { ClickAndSend.find_tracking_numbers(ref).empty? }.to(true)
69
69
  end
70
+
71
+ it "deletes multiple items"
70
72
  end
71
73
  end
72
74
 
@@ -14,5 +14,22 @@ describe ClickAndSend::XML do
14
14
  let(:input) { {:a => {:b => 2}} }
15
15
  it { should == "<a><b>2</b></a>" }
16
16
  end
17
+
18
+ context "hash/array combo" do
19
+ let(:input) do
20
+ {'DeleteItems' => [
21
+ {'DeleteItem' => {'CustTransactionID' => 1, 'TrackingNumber' => 'A'}},
22
+ {'DeleteItem' => {'CustTransactionID' => 2, 'TrackingNumber' => 'B'}},
23
+ ]}
24
+ end
25
+ it "encapsulates hash value with key" do
26
+ pending "required for deleting multiple items (?) but not how gyoku generates xml"
27
+ expected_xml = '<DeleteItems>'+
28
+ '<DeleteItem><CustTransactionID>1</CustTransactionID><TrackingNumber>A</TrackingNumber></DeleteItem>'+
29
+ '<DeleteItem><CustTransactionID>2</CustTransactionID><TrackingNumber>B</TrackingNumber></DeleteItem>'+
30
+ '</DeleteItems>'
31
+ should eq(expected_xml)
32
+ end
33
+ end
17
34
  end
18
35
  end
@@ -35,6 +35,45 @@ describe ClickAndSend do
35
35
  end
36
36
  end
37
37
 
38
+ describe '.logger' do
39
+ subject { ClickAndSend.logger }
40
+ let(:logfile) { File.join(root_path, 'log/click_and_send.log') }
41
+ before { ClickAndSend.configure {}; reset_logger }
42
+
43
+ it "defaults to Logger instance" do
44
+ subject.should be_a(Logger)
45
+ end
46
+
47
+ it "writes to logfile log/click_and_send.log" do
48
+ Logger.should_receive(:new).with(logfile)
49
+ subject
50
+ end
51
+
52
+ context "external logger configured" do
53
+ before { ClickAndSend.configure { |c| c.logger = other_logger } }
54
+ let(:other_logger) { stub(:other_logger) }
55
+
56
+ it "uses configured logger" do
57
+ subject.should eq(other_logger)
58
+ end
59
+ end
60
+
61
+ context "when Rails" do
62
+ before { Rails = stub(:logger => "rails_logger") }
63
+ it { should eq("rails_logger") }
64
+
65
+ context "when logfile set in configuration" do
66
+ before { ClickAndSend.configure { |c| c.logfile = configured_logfile } }
67
+ let(:configured_logfile) { File.join(root_path, 'log/click_and_send.configured.log') }
68
+
69
+ it "writes to configured logfile" do
70
+ Logger.should_receive(:new).with(configured_logfile)
71
+ subject
72
+ end
73
+ end
74
+ end
75
+ end
76
+
38
77
  context "requests" do
39
78
  describe '.check_services' do
40
79
  subject { ClickAndSend.check_services(options) }
@@ -79,7 +118,7 @@ describe ClickAndSend do
79
118
  let(:required_inputs) { %w(DeleteItems) }
80
119
  it_behaves_like "data required"
81
120
  it "calls DeleteItems result" do
82
- ClickAndSend::Request::DeleteItems.should_receive(:new) { stub(:result => 'deleted') }
121
+ ClickAndSend::Request::DeleteItems.should_receive(:new).with(options) { stub(:result => 'deleted') }
83
122
  subject.should == 'deleted'
84
123
  end
85
124
  end
@@ -140,7 +179,7 @@ describe ClickAndSend do
140
179
  end
141
180
 
142
181
  context "no matching tracking numbers" do
143
- let(:tracking_numbers) { [] }
182
+ before { ClickAndSend.stub(:find_tracking_numbers).with(['REF']) { {} } }
144
183
  it "raises API error" do
145
184
  expect { subject }.to raise_error(ClickAndSend::Errors::APIError, "Not found: 'REF'")
146
185
  end
@@ -3,12 +3,20 @@ require 'yaml'
3
3
  module ClickAndSend
4
4
  module Test
5
5
  module Helpers
6
+ def cleanup
7
+ puts "--> Cleaning up"
8
+ refs = ClickAndSend.item_summary.collect { |item| item[:cust_transaction_id] }
9
+ # TODO: Delete in one API call when delete multiple items implemented.
10
+ # ClickAndSend.delete_items_by_ref(refs) if refs.any?
11
+ refs.each { |ref| ClickAndSend.delete_items_by_ref(ref) }
12
+ end
13
+
6
14
  def load_config(mode = :test)
7
15
  yaml_config_path = case mode
8
16
  when :test
9
- File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/config.example.yml'))
17
+ File.join(root_path, 'spec/fixtures/config.example.yml')
10
18
  when :acceptance
11
- File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/config.yml'))
19
+ File.join(root_path, 'spec/fixtures/config.yml')
12
20
  end
13
21
  if File.exists?(yaml_config_path)
14
22
  ClickAndSend.configure do |config|
@@ -18,6 +26,14 @@ module ClickAndSend
18
26
  pending "Can't run acceptance tests because #{yaml_config_path} is missing. See fixtures/config.example.yml."
19
27
  end
20
28
  end
29
+
30
+ def reset_logger
31
+ ClickAndSend.instance_variable_set('@logger', nil)
32
+ end
33
+
34
+ def root_path
35
+ File.expand_path('../..', File.dirname(__FILE__))
36
+ end
21
37
  end
22
38
  end
23
39
  end
metadata CHANGED
@@ -1,132 +1,135 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: click_and_send
3
- version: !ruby/object:Gem::Version
4
- hash: 23
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 4
10
- version: 0.0.4
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Zubin Henner
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-09-10 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- version_requirements: &id001 !ruby/object:Gem::Requirement
12
+ date: 2012-09-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
22
17
  none: false
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- hash: 31
27
- segments:
28
- - 1
29
- - 2
30
- - 0
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
31
21
  version: 1.2.0
32
22
  type: :runtime
33
- requirement: *id001
34
23
  prerelease: false
35
- name: activesupport
36
- - !ruby/object:Gem::Dependency
37
- version_requirements: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
38
25
  none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
46
- type: :runtime
47
- requirement: *id002
48
- prerelease: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.2.0
30
+ - !ruby/object:Gem::Dependency
49
31
  name: nori
50
- - !ruby/object:Gem::Dependency
51
- version_requirements: &id003 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
52
33
  none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- hash: 3
57
- segments:
58
- - 0
59
- version: "0"
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
60
38
  type: :runtime
61
- requirement: *id003
62
39
  prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
63
47
  name: savon
64
- - !ruby/object:Gem::Dependency
65
- version_requirements: &id004 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
66
49
  none: false
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- hash: 3
71
- segments:
72
- - 0
73
- version: "0"
74
- type: :development
75
- requirement: *id004
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
76
55
  prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
77
63
  name: rake
78
- - !ruby/object:Gem::Dependency
79
- version_requirements: &id005 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
80
65
  none: false
81
- requirements:
82
- - - ">="
83
- - !ruby/object:Gem::Version
84
- hash: 3
85
- segments:
86
- - 0
87
- version: "0"
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
88
70
  type: :development
89
- requirement: *id005
90
71
  prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
91
79
  name: rspec
92
- - !ruby/object:Gem::Dependency
93
- version_requirements: &id006 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
94
81
  none: false
95
- requirements:
96
- - - ">="
97
- - !ruby/object:Gem::Version
98
- hash: 3
99
- segments:
100
- - 0
101
- version: "0"
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
102
86
  type: :development
103
- requirement: *id006
104
87
  prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
105
95
  name: faker
106
- - !ruby/object:Gem::Dependency
107
- version_requirements: &id007 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
108
97
  none: false
109
- requirements:
110
- - - ">="
111
- - !ruby/object:Gem::Version
112
- hash: 3
113
- segments:
114
- - 0
115
- version: "0"
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
116
102
  type: :development
117
- requirement: *id007
118
103
  prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
119
111
  name: pry
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
120
126
  description: Ruby adapter for Australia Post's ClickAndSend API
121
- email:
127
+ email:
122
128
  - zubin.henner@gmail.com
123
129
  executables: []
124
-
125
130
  extensions: []
126
-
127
131
  extra_rdoc_files: []
128
-
129
- files:
132
+ files:
130
133
  - .gitignore
131
134
  - .rspec
132
135
  - .travis.yml
@@ -147,6 +150,7 @@ files:
147
150
  - lib/click_and_send/request/print_item.rb
148
151
  - lib/click_and_send/version.rb
149
152
  - lib/click_and_send/xml.rb
153
+ - log/.gitkeep
150
154
  - spec/acceptance_spec.rb
151
155
  - spec/click_and_send/request_spec.rb
152
156
  - spec/click_and_send/xml_spec.rb
@@ -159,38 +163,35 @@ files:
159
163
  - spec/support/shared_examples.rb
160
164
  homepage: https://github.com/zubin/click_and_send
161
165
  licenses: []
162
-
163
166
  post_install_message:
164
167
  rdoc_options: []
165
-
166
- require_paths:
168
+ require_paths:
167
169
  - lib
168
- required_ruby_version: !ruby/object:Gem::Requirement
170
+ required_ruby_version: !ruby/object:Gem::Requirement
169
171
  none: false
170
- requirements:
171
- - - ">="
172
- - !ruby/object:Gem::Version
173
- hash: 3
174
- segments:
172
+ requirements:
173
+ - - ! '>='
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ segments:
175
177
  - 0
176
- version: "0"
177
- required_rubygems_version: !ruby/object:Gem::Requirement
178
+ hash: -1313746178528198946
179
+ required_rubygems_version: !ruby/object:Gem::Requirement
178
180
  none: false
179
- requirements:
180
- - - ">="
181
- - !ruby/object:Gem::Version
182
- hash: 3
183
- segments:
181
+ requirements:
182
+ - - ! '>='
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ segments:
184
186
  - 0
185
- version: "0"
187
+ hash: -1313746178528198946
186
188
  requirements: []
187
-
188
189
  rubyforge_project:
189
190
  rubygems_version: 1.8.24
190
191
  signing_key:
191
192
  specification_version: 3
192
193
  summary: Ruby adapter for Australia Post's ClickAndSend API
193
- test_files:
194
+ test_files:
194
195
  - spec/acceptance_spec.rb
195
196
  - spec/click_and_send/request_spec.rb
196
197
  - spec/click_and_send/xml_spec.rb