wash_out 0.2.6 → 0.3.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.
@@ -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: []