wash_out 0.2.6 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- wash_out (0.2.5)
4
+ wash_out (0.3.0)
5
5
  nori
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -59,7 +59,7 @@ class RumbasController < ApplicationController
59
59
  :args => { :circle => { :center => { :x => :integer,
60
60
  :y => :integer },
61
61
  :radius => :double } },
62
- :return => [],
62
+ :return => nil, # [] for wash_out below 0.3.0
63
63
  :to => :add_circle
64
64
  def add_circle
65
65
  circle = params[:circle]
@@ -100,6 +100,11 @@ client.wsdl.soap_actions # => [:integer_to_string, :concat, :add_circle]
100
100
  result = client.request(:concat) do
101
101
  soap.body = { :a => "123", :b => "abc" }
102
102
  end
103
+
104
+ # actual wash_out
105
+ result.to_hash # => {:concat_reponse => {:value=>"123abc"}}
106
+
107
+ # wash_out below 0.3.0 (and this is malformed response so please update)
103
108
  result.to_hash # => {:value=>"123abc"}
104
109
  ```
105
110
 
@@ -1,11 +1,24 @@
1
1
  module WashOutHelper
2
- def wsdl_data(xml, param)
3
- if param.is_a? Hash
4
- wsdl_data xml, param.map
5
- else
6
- param.each do |opt, value|
7
- xml.tag! opt.name, value.to_s
2
+ def wsdl_data(xml, params)
3
+ params.each do |param|
4
+ if param.multiplied
5
+ param.value.each{|v| wsdl_data_value xml, param, v}
6
+ else
7
+ wsdl_data_value xml, param
8
+ end
9
+ end
10
+ end
11
+
12
+ def wsdl_data_value(xml, param, value=false)
13
+ value ||= param.value.to_s
14
+ tag_name = "tns:#{param.name}"
15
+
16
+ if param.struct?
17
+ xml.tag! tag_name, "xsi:type" => param.namespaced_type do
18
+ wsdl_data(xml, param.map)
8
19
  end
20
+ else
21
+ xml.tag! tag_name, value, "xsi:type" => param.namespaced_type
9
22
  end
10
23
  end
11
24
 
@@ -30,8 +43,8 @@ module WashOutHelper
30
43
 
31
44
  def wsdl_occurence(param, extend_with = {})
32
45
  data = !param.multiplied ? {} : {
33
- :minOccurs => 0,
34
- :maxOccurs => 'unbounded'
46
+ "xsi:minOccurs" => 0,
47
+ "xsi:maxOccurs" => 'unbounded'
35
48
  }
36
49
 
37
50
  extend_with.merge(data)
@@ -1,7 +1,10 @@
1
1
  xml.instruct!
2
- xml.Envelope "xmlns:xsi" => 'http://www.w3.org/2001/XMLSchema-instance',
3
- :xmlns => 'http://schemas.xmlsoap.org/soap/envelope/' do
4
- xml.Body do
5
- wsdl_data xml, result
2
+ xml.tag! "soap:Envelope", "xmlns:soap" => 'http://schemas.xmlsoap.org/soap/envelope/',
3
+ "xmlns:xsi" => 'http://www.w3.org/2001/XMLSchema-instance',
4
+ "xmlns:tns" => @namespace do
5
+ xml.tag! "soap:Body" do
6
+ xml.tag! "tns:#{@operation}_response" do
7
+ wsdl_data xml, result
8
+ end
6
9
  end
7
- end
10
+ end
@@ -3,6 +3,7 @@ xml.definitions 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/',
3
3
  'xmlns:tns' => @namespace,
4
4
  'xmlns:soap' => 'http://schemas.xmlsoap.org/wsdl/soap/',
5
5
  'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
6
+ "xmlns:xsi" => 'http://www.w3.org/2001/XMLSchema-instance',
6
7
  'xmlns:soap-enc' => 'http://schemas.xmlsoap.org/soap/encoding/',
7
8
  'xmlns:wsdl' => 'http://schemas.xmlsoap.org/wsdl/',
8
9
  'name' => @name,
@@ -5,6 +5,9 @@ module WashOut
5
5
  # as a SOAP endpoint. It includes actions for generating WSDL and handling
6
6
  # SOAP requests.
7
7
  module Dispatcher
8
+ # Default Type namespace
9
+ NAMESPACE = 'urn:WashOut'
10
+
8
11
  # A SOAPError exception can be raised to return a correct SOAP error
9
12
  # response.
10
13
  class SOAPError < Exception; end
@@ -35,7 +38,7 @@ module WashOut
35
38
  # This action generates the WSDL for defined SOAP methods.
36
39
  def _generate_wsdl
37
40
  @map = self.class.soap_actions
38
- @namespace = 'urn:WashOut'
41
+ @namespace = NAMESPACE
39
42
  @name = controller_path.gsub('/', '_')
40
43
 
41
44
  render :template => 'wash_with_soap/wsdl'
@@ -43,17 +46,25 @@ module WashOut
43
46
 
44
47
  # Render a SOAP response.
45
48
  def _render_soap(result, options)
46
- soap_action = request.env['wash_out.soap_action']
47
- action_spec = self.class.soap_actions[soap_action]
49
+ @namespace = NAMESPACE
50
+ @operation = soap_action = request.env['wash_out.soap_action']
51
+ action_spec = self.class.soap_actions[soap_action][:out].clone
48
52
 
49
53
  result = { 'value' => result } unless result.is_a? Hash
50
54
  result = HashWithIndifferentAccess.new(result)
51
- result = Hash[*action_spec[:out].map do |param|
52
- [param, param.store(result[param.name])]
53
- end.flatten]
55
+
56
+ inject = lambda {|data, spec|
57
+ spec.each do |param|
58
+ if param.struct?
59
+ inject.call(data[param.name], param.map)
60
+ else
61
+ param.value = data[param.name]
62
+ end
63
+ end
64
+ }
54
65
 
55
66
  render :template => 'wash_with_soap/response',
56
- :locals => { :result => result }
67
+ :locals => { :result => inject.call(result, action_spec) }
57
68
  end
58
69
 
59
70
  # This action is a fallback for all undefined SOAP actions.
@@ -4,6 +4,7 @@ module WashOut
4
4
  attr_accessor :map
5
5
  attr_accessor :type
6
6
  attr_accessor :multiplied
7
+ attr_accessor :value
7
8
 
8
9
  # Defines a WSDL parameter with name +name+ and type specifier +type+.
9
10
  # The type specifier format is described in #parse_def.
@@ -27,27 +28,26 @@ module WashOut
27
28
  def load(data)
28
29
  check_if_missing(data)
29
30
 
31
+ data = Array(data) if @multiplied
32
+
30
33
  if struct?
31
34
  map_struct(data) { |param, elem| param.load(elem) }
32
35
  else
33
- case type
34
- when 'string'; data.to_s
35
- when 'integer'; data.to_i
36
- when 'double'; data.to_f
37
- when 'boolean'; data # Nori handles that for us
36
+ operation = case type
37
+ when 'string'; :to_s
38
+ when 'integer'; :to_i
39
+ when 'double'; :to_f
40
+ when 'boolean'; nil # Nori handles that for us
38
41
  else raise RuntimeError, "Invalid WashOut simple type: #{type}"
39
42
  end
40
- end
41
- end
42
-
43
- # The opposite of #load.
44
- def store(data)
45
- check_if_missing(data)
46
-
47
- if struct?
48
- map_struct(data) { |param, elem| param.store(elem) }
49
- else
50
- data.to_s
43
+
44
+ if operation.nil?
45
+ data
46
+ elsif data.is_a? Array
47
+ data.map{|x| x.send(operation)}
48
+ else
49
+ data.send(operation)
50
+ end
51
51
  end
52
52
  end
53
53
 
@@ -78,24 +78,37 @@ module WashOut
78
78
  #
79
79
  # This function returns an array of WashOut::Param objects.
80
80
  def self.parse_def(definition)
81
- definition = { :value => definition } if definition.is_a? Symbol
81
+ raise RuntimeError, "[] should not be used in your params. Use nil if you want to mark empty set." if definition == []
82
+ return [] if definition == nil
83
+
84
+ if [Array, Symbol].include?(definition.class)
85
+ definition = { :value => definition }
86
+ end
82
87
 
83
88
  if definition.is_a? Hash
84
89
  definition.map do |name, opt|
85
90
  if opt.is_a? WashOut::Param
86
91
  opt
92
+ elsif opt.is_a? Array
93
+ WashOut::Param.new(name, opt[0], true)
87
94
  else
88
95
  WashOut::Param.new(name, opt)
89
96
  end
90
97
  end
91
98
  else
92
- definition.to_a
99
+ raise RuntimeError, "Wrong definition: #{type.inspect}"
93
100
  end
94
101
  end
102
+
103
+ def clone
104
+ copy = self.class.new(@name, @type.to_sym, @multiplied)
105
+ copy.map = @map.map{|x| x.clone}
106
+ copy
107
+ end
95
108
 
96
109
  private
97
110
 
98
- # Used to load or store an entire structure.
111
+ # Used to load an entire structure.
99
112
  def map_struct(data)
100
113
  data = data.with_indifferent_access
101
114
  struct = {}.with_indifferent_access
@@ -1,3 +1,3 @@
1
1
  module WashOut
2
- VERSION = "0.2.6"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -17,12 +17,12 @@ describe WashOut do
17
17
 
18
18
  it "should generate WSDL" do
19
19
  mock_controller do
20
- soap_action "answer", :args => [], :return => :int
20
+ soap_action "answer", :args => nil, :return => :int
21
21
  def answer
22
22
  render :soap => "42"
23
23
  end
24
24
 
25
- soap_action "getArea", :args => { :circle => { :center => { :x => :integer,
25
+ soap_action "getArea", :args => { :circle => { :center => { :x => [:integer],
26
26
  :y => :integer },
27
27
  :radius => :double } },
28
28
  :return => { :area => :double,
@@ -34,7 +34,7 @@ describe WashOut do
34
34
  :distance_from_o => Math.sqrt(circle[:center][:x] ** 2 + circle[:center][:y] ** 2) }
35
35
  end
36
36
  end
37
-
37
+
38
38
  client = savon_instance
39
39
  xml = Nori.parse client.wsdl.xml
40
40
 
@@ -42,27 +42,31 @@ describe WashOut do
42
42
  # get back just what we have at controller
43
43
  client.wsdl.soap_actions.should == [:answer, :get_area]
44
44
 
45
+ x = xml[:definitions][:types][:schema][:complex_type].find{|x| x[:'@name'] == 'center'}[:sequence][:element].find{|x| x[:'@name'] == 'x'}
46
+ x[:'@xsi:min_occurs'].should == "0"
47
+ x[:'@xsi:max_occurs'].should == "unbounded"
48
+
45
49
  xml[:definitions][:binding][:operation].map{|e| e[:'@name']}.should == ['answer', 'getArea']
46
50
  end
47
51
 
48
52
  it "should allow definition of a simple action" do
49
53
  lambda {
50
54
  mock_controller do
51
- soap_action "answer", :args => [], :return => :int
55
+ soap_action "answer", :args => nil, :return => :int
52
56
  end
53
57
  }.should_not raise_exception
54
58
  end
55
59
 
56
60
  it "should answer to request without parameters" do
57
61
  mock_controller do
58
- soap_action "answer", :args => [], :return => :int
62
+ soap_action "answer", :args => nil, :return => :int
59
63
  def answer
60
64
  render :soap => "42"
61
65
  end
62
66
  end
63
67
 
64
68
  client = savon_instance
65
- client.request(:answer).to_hash[:value].should == "42"
69
+ client.request(:answer).to_hash[:answer_response][:value].should == "42"
66
70
  end
67
71
 
68
72
  it "should answer to request with one parameter" do
@@ -76,10 +80,10 @@ describe WashOut do
76
80
  client = savon_instance
77
81
  client.request(:check_answer) do
78
82
  soap.body = { :value => 42 }
79
- end.to_hash[:value].should == true
83
+ end.to_hash[:check_answer_response][:value].should == true
80
84
  client.request(:check_answer) do
81
85
  soap.body = { :value => 13 }
82
- end.to_hash[:value].should == false
86
+ end.to_hash[:check_answer_response][:value].should == false
83
87
  end
84
88
 
85
89
  it "should answer to request with two parameter" do
@@ -93,7 +97,7 @@ describe WashOut do
93
97
  client = savon_instance
94
98
  client.request(:funky) do
95
99
  soap.body = { :a => 42, :b => 'k' }
96
- end.to_hash[:value].should == '420k'
100
+ end.to_hash[:funky_response][:value].should == '420k'
97
101
  end
98
102
 
99
103
  it "should understand nested parameter specifications" do
@@ -115,25 +119,27 @@ describe WashOut do
115
119
  client.request(:get_area) do
116
120
  soap.body = { :circle => { :center => { :x => 3, :y => 4 },
117
121
  :radius => 5 } }
118
- end.to_hash.should == ({ :area => (Math::PI * 25).to_s, :distance_from_o => (5.0).to_s })
122
+ end.to_hash[:get_area_response].should == ({ :area => (Math::PI * 25).to_s, :distance_from_o => (5.0).to_s })
119
123
  end
120
124
 
121
125
  it "should allow arbitrary action names" do
126
+ name = 'AnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything'
127
+
122
128
  mock_controller do
123
- soap_action "AnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything",
124
- :args => [], :return => :integer, :to => :answer
129
+ soap_action name,
130
+ :args => nil, :return => :integer, :to => :answer
125
131
  def answer
126
132
  render :soap => "forty two"
127
133
  end
128
134
  end
129
135
 
130
136
  client = savon_instance
131
- client.request('AnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything').to_hash[:value].should == "forty two"
137
+ client.request(name).to_hash["#{name.underscore}_response".to_sym][:value].should == "forty two"
132
138
  end
133
139
 
134
140
  it "should correctly report SOAP errors" do
135
141
  mock_controller do
136
- soap_action "error", :args => { :need_error => :boolean }, :return => []
142
+ soap_action "error", :args => { :need_error => :boolean }, :return => nil
137
143
  def error
138
144
  raise self.class.const_get(:SOAPError), "you wanted one" if params[:need_error]
139
145
 
@@ -165,7 +171,7 @@ describe WashOut do
165
171
 
166
172
  it "should be possible to explicitly render a SOAP error" do
167
173
  mock_controller do
168
- soap_action "error", :args => [], :return => []
174
+ soap_action "error", :args => nil, :return => nil
169
175
  def error
170
176
  render_soap_error "a message"
171
177
  end
@@ -176,4 +182,81 @@ describe WashOut do
176
182
  client.request(:error)
177
183
  }.should raise_exception(Savon::SOAP::Fault)
178
184
  end
185
+
186
+ it "should handle nested returns" do
187
+ mock_controller do
188
+ soap_action "gogogo",
189
+ :args => nil,
190
+ :return => {
191
+ :zoo => :string,
192
+ :boo => {
193
+ :moo => :string,
194
+ :doo => :string
195
+ }
196
+ }
197
+ def gogogo
198
+ render :soap => {
199
+ :zoo => 'zoo',
200
+ :boo => {
201
+ :moo => 'moo',
202
+ :doo => 'doo'
203
+ }
204
+ }
205
+ end
206
+ end
207
+
208
+ savon_instance.request(:gogogo)[:gogogo_response].should == {:zoo=>"zoo", :boo=>{:moo=>"moo", :doo=>"doo", :"@xsi:type"=>"tns:boo"}}
209
+ end
210
+
211
+ it "should handle arrays" do
212
+ mock_controller do
213
+ soap_action "rumba",
214
+ :args => {
215
+ :rumbas => [:integer]
216
+ },
217
+ :return => nil
218
+ def rumba
219
+ params.should == {"rumbas" => [1, 2, 3]}
220
+ render :soap => nil
221
+ end
222
+ end
223
+
224
+ savon_instance.request(:rumba) do
225
+ soap.body = {
226
+ :rumbas => [1, 2, 3]
227
+ }
228
+ end
229
+ end
230
+
231
+ it "should be able to return arrays" do
232
+ mock_controller do
233
+ soap_action "rumba",
234
+ :args => nil,
235
+ :return => {
236
+ :rumbas => [:integer]
237
+ }
238
+ def rumba
239
+ render :soap => {:rumbas => [1, 2, 3]}
240
+ end
241
+ end
242
+
243
+ savon_instance.request(:rumba).to_hash[:rumba_response].should == {:rumbas => ["1", "2", "3"]}
244
+ end
245
+
246
+ it "should deprecate old syntax" do
247
+ # save rspec context check
248
+ raise_runtime_exception = raise_exception(RuntimeError)
249
+
250
+ mock_controller do
251
+ lambda {
252
+ soap_action "rumba",
253
+ :args => :integer,
254
+ :return => []
255
+ }.should raise_runtime_exception
256
+ def rumba
257
+ render :soap => nil
258
+ end
259
+ end
260
+ end
261
+
179
262
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wash_out
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-01-21 00:00:00.000000000 Z
13
+ date: 2012-01-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: nori
17
- requirement: &70359974011000 !ruby/object:Gem::Requirement
17
+ requirement: &70332337988240 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70359974011000
25
+ version_requirements: *70332337988240
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: rspec-rails
28
- requirement: &70359974009900 !ruby/object:Gem::Requirement
28
+ requirement: &70332337984940 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *70359974009900
36
+ version_requirements: *70332337984940
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: appraisal
39
- requirement: &70359974008240 !ruby/object:Gem::Requirement
39
+ requirement: &70332346016840 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *70359974008240
47
+ version_requirements: *70332346016840
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: tzinfo
50
- requirement: &70359974007200 !ruby/object:Gem::Requirement
50
+ requirement: &70332346016420 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: '0'
56
56
  type: :development
57
57
  prerelease: false
58
- version_requirements: *70359974007200
58
+ version_requirements: *70332346016420
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: savon
61
- requirement: &70359974006560 !ruby/object:Gem::Requirement
61
+ requirement: &70332346016000 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ! '>='
@@ -66,7 +66,7 @@ dependencies:
66
66
  version: '0'
67
67
  type: :development
68
68
  prerelease: false
69
- version_requirements: *70359974006560
69
+ version_requirements: *70332346016000
70
70
  description: Dead simple Rails 3 SOAP server library
71
71
  email: boris@roundlake.ru
72
72
  executables: []