stockboy 0.6.0 → 0.7.0

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.
@@ -0,0 +1,64 @@
1
+ require 'stockboy/provider'
2
+
3
+ module Stockboy
4
+ class ProviderRepeater
5
+
6
+ YIELD_ONCE = proc { |output, provider| output << provider }
7
+
8
+ attr_reader :base_provider
9
+
10
+ def initialize(provider, &yielder)
11
+ @orig_provider = provider
12
+ @base_provider = provider.dup
13
+ @yielder = yielder || YIELD_ONCE
14
+ end
15
+
16
+ def data
17
+ # return base_provider.data unless block_given?
18
+ return nil unless block_given?
19
+ each do |nth_provider|
20
+ yield nth_provider.data
21
+ end
22
+ end
23
+
24
+ def clear
25
+ @base_provider = @orig_provider.dup
26
+ super
27
+ end
28
+
29
+ def each
30
+ return to_enum unless block_given?
31
+ enum = to_enum
32
+ while true
33
+ begin
34
+ provider = enum.next
35
+ unless provider.respond_to? :data
36
+ raise ArgumentError, "expected Provider, got #{provider.class}"
37
+ end
38
+ rescue StopIteration
39
+ return $!.result
40
+ end
41
+ y = yield provider
42
+ provider.clear
43
+ enum.feed y
44
+ end
45
+ end
46
+
47
+ def to_enum
48
+ Enumerator.new do |y|
49
+ begin
50
+ @yielder.call(y, base_provider)
51
+ rescue LocalJumpError
52
+ raise $!, "use output << provider instead of yield", $!.backtrace
53
+ end
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def method_missing(method, *args, &block)
60
+ base_provider.public_send(method, *args, &block)
61
+ end
62
+
63
+ end
64
+ end
@@ -78,7 +78,7 @@ module Stockboy::Providers
78
78
  private
79
79
 
80
80
  def fetch_data
81
- errors.add(:base, "File #{file_name} not found") unless matching_file
81
+ errors << "file #{file_name} not found" unless matching_file
82
82
  data_file = ::File.new(matching_file, 'r') if matching_file
83
83
  validate_file(data_file)
84
84
  if valid?
@@ -89,7 +89,8 @@ module Stockboy::Providers
89
89
  end
90
90
 
91
91
  def validate
92
- errors.add_on_blank [:file_dir, :file_name]
92
+ errors << "file_dir must be specified" if file_dir.blank?
93
+ errors << "file_name must be specified" if file_name.blank?
93
94
  errors.empty?
94
95
  end
95
96
 
@@ -98,7 +99,7 @@ module Stockboy::Providers
98
99
  end
99
100
 
100
101
  def validate_file(data_file)
101
- return errors.add :response, "No matching files" unless data_file
102
+ return errors << "no matching files" unless data_file
102
103
  validate_file_newer(data_file)
103
104
  validate_file_smaller(data_file)
104
105
  validate_file_larger(data_file)
@@ -107,21 +108,21 @@ module Stockboy::Providers
107
108
  def validate_file_newer(data_file)
108
109
  @data_time ||= data_file.mtime
109
110
  if file_newer && @data_time < file_newer
110
- errors.add :response, "No new files since #{file_newer}"
111
+ errors << "no new files since #{file_newer}"
111
112
  end
112
113
  end
113
114
 
114
115
  def validate_file_smaller(data_file)
115
116
  @data_size ||= data_file.size
116
117
  if file_smaller && @data_size > file_smaller
117
- errors.add :response, "File size larger than #{file_smaller}"
118
+ errors << "file size larger than #{file_smaller}"
118
119
  end
119
120
  end
120
121
 
121
122
  def validate_file_larger(data_file)
122
123
  @data_size ||= data_file.size
123
124
  if file_larger && @data_size < file_larger
124
- errors.add :response, "File size smaller than #{file_larger}"
125
+ errors << "file size smaller than #{file_larger}"
125
126
  end
126
127
  end
127
128
  end
@@ -114,7 +114,7 @@ module Stockboy::Providers
114
114
  response
115
115
  end
116
116
  rescue Net::FTPError => e
117
- errors.add :response, e.message
117
+ errors << e.message
118
118
  logger.warn e.message
119
119
  end
120
120
 
@@ -161,7 +161,8 @@ module Stockboy::Providers
161
161
  end
162
162
 
163
163
  def validate
164
- errors.add_on_blank [:host, :file_name]
164
+ errors << "host must be specified" if host.blank?
165
+ errors << "file_name must be specified" if file_name.blank?
165
166
  errors.empty?
166
167
  end
167
168
 
@@ -175,7 +176,7 @@ module Stockboy::Providers
175
176
  end
176
177
 
177
178
  def validate_file(data_file)
178
- return errors.add :response, "No matching files" unless data_file
179
+ return errors << "No matching files" unless data_file
179
180
  validate_file_newer(data_file)
180
181
  validate_file_smaller(data_file)
181
182
  validate_file_larger(data_file)
@@ -184,21 +185,21 @@ module Stockboy::Providers
184
185
  def validate_file_newer(data_file)
185
186
  @data_time ||= client { |ftp| ftp.mtime(data_file) }
186
187
  if file_newer and @data_time < file_newer
187
- errors.add :response, "No new files since #{file_newer}"
188
+ errors << "No new files since #{file_newer}"
188
189
  end
189
190
  end
190
191
 
191
192
  def validate_file_smaller(data_file)
192
193
  @data_size ||= client { |ftp| ftp.size(data_file) }
193
194
  if file_smaller and @data_size > file_smaller
194
- errors.add :response, "File size larger than #{file_smaller}"
195
+ errors << "File size larger than #{file_smaller}"
195
196
  end
196
197
  end
197
198
 
198
199
  def validate_file_larger(data_file)
199
200
  @data_size ||= client { |ftp| ftp.size(data_file) }
200
201
  if file_larger and @data_size < file_larger
201
- errors.add :response, "File size smaller than #{file_larger}"
202
+ errors << "File size smaller than #{file_larger}"
202
203
  end
203
204
  end
204
205
  end
@@ -132,7 +132,8 @@ module Stockboy::Providers
132
132
  private
133
133
 
134
134
  def validate
135
- errors.add_on_blank [:uri, :method]
135
+ errors << "uri must be specified" if uri.blank?
136
+ errors << "method (:get, :post) must be specified" if method.blank?
136
137
  errors.empty?
137
138
  end
138
139
 
@@ -142,7 +143,7 @@ module Stockboy::Providers
142
143
  request.auth.basic(username, password) if username && password
143
144
  response = HTTPI.send(method, request)
144
145
  if response.error?
145
- errors.add :response, "HTTP respone error: #{response.code}"
146
+ errors << "HTTP response error: #{response.code}"
146
147
  else
147
148
  @data = response.body
148
149
  end
@@ -162,7 +162,7 @@ module Stockboy::Providers
162
162
  end
163
163
  yield @open_client
164
164
  rescue ::Net::IMAP::Error => e
165
- errors.add :response, "IMAP connection error"
165
+ errors << "IMAP connection error"
166
166
  ensure
167
167
  if first_connection
168
168
  @open_client.disconnect
@@ -253,7 +253,9 @@ module Stockboy::Providers
253
253
  end
254
254
 
255
255
  def validate
256
- errors.add_on_blank [:host, :username, :password]
256
+ errors << "host must be specified" if host.blank?
257
+ errors << "username must be specified" if username.blank?
258
+ errors << "password must be specified" if password.blank?
257
259
  errors.empty?
258
260
  end
259
261
 
@@ -281,7 +283,7 @@ module Stockboy::Providers
281
283
  end
282
284
 
283
285
  def validate_file(data_file)
284
- return errors.add :response, "No matching attachments" unless data_file
286
+ return errors << "No matching attachments" unless data_file
285
287
  validate_file_smaller(data_file)
286
288
  validate_file_larger(data_file)
287
289
  end
@@ -289,14 +291,14 @@ module Stockboy::Providers
289
291
  def validate_file_smaller(data_file)
290
292
  @data_size ||= data_file.bytesize
291
293
  if file_smaller && @data_size > file_smaller
292
- errors.add :response, "File size larger than #{file_smaller}"
294
+ errors << "File size larger than #{file_smaller}"
293
295
  end
294
296
  end
295
297
 
296
298
  def validate_file_larger(data_file)
297
299
  @data_size ||= data_file.bytesize
298
300
  if file_larger && @data_size < file_larger
299
- errors.add :response, "File size smaller than #{file_larger}"
301
+ errors << "File size smaller than #{file_larger}"
300
302
  end
301
303
  end
302
304
  end
@@ -34,12 +34,24 @@ module Stockboy::Providers
34
34
  #
35
35
  dsl_attr :request
36
36
 
37
+ # @return [Symbol]
38
+ # @example
39
+ # env_namespace :soapenv
40
+ #
41
+ dsl_attr :env_namespace
42
+
37
43
  # @return [String]
38
44
  # @!attribute [rw] namespace
39
45
  # Optional if specified in WSDL
40
46
  #
41
47
  dsl_attr :namespace
42
48
 
49
+ # @return [Hash]
50
+ # @!attribute [rw] namespaces
51
+ # Optional if specified in WSDL
52
+ #
53
+ dsl_attr :namespaces
54
+
43
55
  # @return [String]
44
56
  # @!attribute [rw] namespace_id
45
57
  # Optional if specified in WSDL
@@ -62,6 +74,45 @@ module Stockboy::Providers
62
74
  #
63
75
  dsl_attr :message
64
76
 
77
+ # Message tag name
78
+ #
79
+ # @!attribute [rw] message_tag
80
+ # @return [String]
81
+ # @example
82
+ # message_tag "GetResult"
83
+ #
84
+ dsl_attr :message_tag
85
+
86
+ # @return [String]
87
+ # @example
88
+ # soap_action "urn:processMessage"
89
+ #
90
+ dsl_attr :soap_action
91
+
92
+ # XML string to override the Soap headers
93
+ #
94
+ # @!attribute [rw] soap_header
95
+ # @return [String]
96
+ # @example
97
+ # soap_header "<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">..."
98
+ #
99
+ dsl_attr :soap_header
100
+
101
+ # @return [Hash]
102
+ # @example
103
+ # attributes {}
104
+ #
105
+ dsl_attr :attributes
106
+
107
+ # Change the default response type, default :hash
108
+ #
109
+ # @!attribute [rw] response_format
110
+ # @return [Symbol]
111
+ # @example
112
+ # response_format :xml
113
+ #
114
+ dsl_attr :response_format
115
+
65
116
  # Hash of optional HTTP request headers
66
117
  #
67
118
  # @!attribute [rw] headers
@@ -71,12 +122,22 @@ module Stockboy::Providers
71
122
  #
72
123
  dsl_attr :headers
73
124
 
125
+ # Array of WSSE Auth values
126
+ #
127
+ # @!attribute [rw] wsse_auth
128
+ # @return [Array]
129
+ # @example
130
+ # wsse_auth ["Username", "Password"]
131
+ #
132
+ dsl_attr :wsse_auth
133
+
74
134
  # @!endgroup
75
135
 
76
136
  # Initialize a new SOAP provider
77
137
  #
78
138
  def initialize(opts={}, &block)
79
139
  super
140
+ @response_format = opts[:response_format] || :hash
80
141
  DSL.new(self).instance_eval(&block) if block_given?
81
142
  end
82
143
 
@@ -100,21 +161,36 @@ module Stockboy::Providers
100
161
  end
101
162
  opts[:convert_response_tags_to] = ->(tag) { string_pool(tag) }
102
163
  opts[:namespace] = namespace if namespace
164
+ opts[:namespaces] = namespaces if namespaces
103
165
  opts[:namespace_identifier] = namespace_id if namespace_id
166
+ opts[:env_namespace] = env_namespace if env_namespace
104
167
  opts[:headers] = headers if headers
168
+ opts[:wsse_auth] = wsse_auth if wsse_auth
105
169
  opts
106
170
  end
107
171
 
108
172
  def validate
109
- errors.add_on_blank(:endpoint) unless wsdl
173
+ errors << "endpoint or wsdl must be specified" if endpoint.blank? unless wsdl
110
174
  errors.blank?
111
175
  end
112
176
 
113
177
  def fetch_data
114
178
  with_string_pool do
115
- @data = client.call(@request, message: message).body
179
+ response = client.call(
180
+ @request,
181
+ message: message,
182
+ message_tag: message_tag,
183
+ soap_action: soap_action,
184
+ soap_header: soap_header,
185
+ attributes: attributes
186
+ )
187
+ @data = case response_format
188
+ when :xml
189
+ response.xml
190
+ else
191
+ response.body
192
+ end
116
193
  end
117
194
  end
118
-
119
195
  end
120
196
  end
@@ -38,5 +38,16 @@ module Stockboy
38
38
  @registry
39
39
  end
40
40
 
41
+ def build(key, options, block)
42
+ case key
43
+ when Symbol
44
+ find(key).new(options, &block)
45
+ when Class
46
+ key.new(options, &block)
47
+ else
48
+ key
49
+ end
50
+ end
51
+
41
52
  end
42
53
  end
@@ -45,6 +45,7 @@ module Stockboy
45
45
  context = OpenStruct.new(context) if context.is_a? Hash
46
46
  translate(context)
47
47
  end
48
+ alias_method :[], :call
48
49
 
49
50
  # String representation for a more helpful representation
50
51
  #
@@ -1,3 +1,3 @@
1
1
  module Stockboy
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -12,14 +12,15 @@ module Stockboy
12
12
  end
13
13
 
14
14
  describe ".new" do
15
+ let(:row) { Attribute.new(:email, "email", []) }
16
+
15
17
  it "initializes from hash attribute" do
16
- row = Attribute.new(:email, "email", [])
17
18
  map = AttributeMap.new(:email => row)
18
19
  map[:email].should == row
19
20
  end
20
21
  end
21
22
 
22
- it "captures same destination as default" do
23
+ it "sets same destination as default" do
23
24
  subject[:email].should == Attribute.new(:email, "email", [])
24
25
  end
25
26
 
@@ -55,5 +56,15 @@ module Stockboy
55
56
  subject.map(&:to).should == [:email, :updated_at]
56
57
  end
57
58
 
59
+ describe "#insert" do
60
+ subject(:map) { AttributeMap.new }
61
+
62
+ it "sets options from hash" do
63
+ upcase = ->(r) { r.upcase }
64
+ map.insert :test, from: "Test", as: upcase
65
+ map[:test].should == Attribute.new(:test, "Test", [upcase])
66
+ end
67
+ end
68
+
58
69
  end
59
70
  end
@@ -72,6 +72,27 @@ module Stockboy
72
72
  subject.attributes &proc{}
73
73
  subject.config[:attributes].should be attribute_map
74
74
  end
75
+
76
+ it "replaces existing attributes" do
77
+ subject.attribute :first_name
78
+ subject.attributes do last_name end
79
+ subject.config[:attributes][:first_name].should be_nil
80
+ subject.config[:attributes][:last_name].should be_an Attribute
81
+ end
82
+ end
83
+
84
+ describe "#attribute" do
85
+ it "inserts a single attribute" do
86
+ subject.attribute :test, from: "Test"
87
+ subject.config[:attributes][:test].should == Attribute.new(:test, "Test", [])
88
+ end
89
+
90
+ it "respects existing attributes added first" do
91
+ subject.attributes do first_name end
92
+ subject.attribute :last_name
93
+ subject.config[:attributes][:first_name].should be_an Attribute
94
+ subject.config[:attributes][:last_name].should be_an Attribute
95
+ end
75
96
  end
76
97
 
77
98
  describe "#on" do