stockboy 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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