wash_out 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,55 @@
1
+ == Wash Out
2
+
3
+ Wash Out is very simple SOAP service solution. It allows you to create SOAP services on top of your controllers in 3 steps (see Usage).
4
+
5
+ == Install
6
+
7
+ gem install wash_out
8
+
9
+ == Usage
10
+
11
+ === I. Define structure in your controller
12
+
13
+ class TestController < ApplicationController
14
+ wash_with_soap :my_soap_method => {
15
+ :in => { 'structure' => { 'foo' => :string }, 'bar' => :integer },
16
+ :out => :boolean
17
+ }
18
+
19
+ Defined this way method "my_soap_method" will wait for two parameters:
20
+
21
+ 1. 'structure' will wait for complex type (defined separately in WSDL)
22
+ 2. 'bar' will wait for string (xsd:string in WSDL)
23
+
24
+ On the other side it will return boolean (xsd:boolean in WSDL).
25
+
26
+ === II. Define worker
27
+
28
+ At same controller define action "my_soap_method"
29
+
30
+ def my_soap_method
31
+ @soap # this will contain data passed by SOAP request
32
+ end
33
+
34
+ Parameters are handling by WashOut::Param entity. To get values use 'value' and '[]' methods.
35
+
36
+ To get 'bar' parameter:
37
+ @soap['bar'].value
38
+
39
+ To get 'foo' from 'structure':
40
+ @soap['structure']['foo'].value
41
+
42
+ === III. Return something
43
+
44
+ Return from your method to respond. In our case we should just respond with
45
+ return true #or return false
46
+
47
+ In complex scenarios we can do
48
+ return { :foo => 'foo', :bar => 'bar' }
49
+
50
+
51
+ == Complex cases
52
+
53
+ === I have same substructures for several methods. Are there any ways to define WSDL besides hash?
54
+
55
+ === How to respond with SOAP error?
@@ -0,0 +1,41 @@
1
+ module WashOutHelper
2
+ def wsdl_data(xml, param)
3
+ if param.struct?
4
+ param.value.values.each do |p|
5
+ wsdl_data xml, p
6
+ end
7
+ else
8
+ xml.tag! param.name, param.value.to_s
9
+ end
10
+ end
11
+
12
+ def wsdl_type(xml, param)
13
+ more = []
14
+
15
+ if param.struct?
16
+ return if param.value.blank?
17
+
18
+ xml.complexType :name => param.name do
19
+ xml.sequence do
20
+ param.value.each do |key, value|
21
+ more << value if value.struct?
22
+ xml.element wsdl_occurence(value, :name => key, :type => value.namespaced_type)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ more.each do |p|
29
+ wsdl_type xml, p
30
+ end
31
+ end
32
+
33
+ def wsdl_occurence(param, extend_with = {})
34
+ data = !param.multiplied ? {} : {
35
+ :minOccurs => 0,
36
+ :maxOccurs => 'unbounded'
37
+ }
38
+
39
+ return extend_with.merge(data)
40
+ end
41
+ end
@@ -0,0 +1,10 @@
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
+ xml.Fault :encodingStyle => 'http://schemas.xmlsoap.org/soap/encoding/' do
6
+ xml.faultcode "Server", 'xsi:type' => 'xsd:QName'
7
+ xml.faultstring @error, 'xsi:type' => 'xsd:string'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,7 @@
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
6
+ end
7
+ end
@@ -0,0 +1,75 @@
1
+ xml.instruct!
2
+ xml.definitions 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
3
+ 'xmlns:soap' => 'http://schemas.xmlsoap.org/wsdl/soap/',
4
+ 'xmlns:soapenc' => 'http://schemas.xmlsoap.org/soap/encoding/',
5
+ 'xmlns:wsdl' => 'http://schemas.xmlsoap.org/wsdl/',
6
+ 'xmlns:typens' => @namespace,
7
+ 'targetNamespace' => @namespace,
8
+ 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/' do
9
+ xml.types do
10
+ xml.tag! "xsd:schema", :xmlns => 'http://www.w3.org/2001/XMLSchema', :targetNamespace => @namespace
11
+
12
+ @map.each do |operation, formats|
13
+ formats.each do |kind, params|
14
+ if params.struct?
15
+ params.value.each{|foo, p| wsdl_type xml, p}
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ @map.each do |operation, formats|
22
+ xml.message :name => "#{operation}" do
23
+ if formats[:in].struct?
24
+ formats[:in].value.each do |name, p|
25
+ xml.part wsdl_occurence(p, :name => p.name, :type => p.namespaced_type)
26
+ end
27
+ else
28
+ xml.part wsdl_occurence(formats[:in], :name => operation, :type => formats[:in].namespaced_type)
29
+ end
30
+ end
31
+ xml.message :name => "#{operation}_responce" do
32
+ if formats[:out].struct?
33
+ formats[:out].value.each do |name, p|
34
+ xml.part wsdl_occurence(p, :name => p.name, :type => p.namespaced_type)
35
+ end
36
+ else
37
+ xml.part wsdl_occurence(formats[:out], :name => operation, :type => formats[:out].namespaced_type)
38
+ end
39
+ end
40
+ end
41
+
42
+ xml.portType :name => "#{@name}_port" do
43
+ @map.keys.each do |operation|
44
+ xml.operation :name => operation do
45
+ xml.input :message => "typens:#{operation}"
46
+ xml.otput :message => "typens:#{operation}_responce"
47
+ end
48
+ end
49
+ end
50
+
51
+ xml.binding :name => "#{@name}_binding", :type => "typens:#{@name}_port" do
52
+ xml.tag! "soap:binding", :style => 'rpc', :transport => 'http://schemas.xmlsoap.org/soap/http'
53
+ @map.keys.each do |operation|
54
+ xml.operation :name => operation do
55
+ xml.tag! "soap:operation", :soapAction => operation
56
+ xml.input do
57
+ xml.tag! "soap:body",
58
+ :use => "encoded", :encodingStyle => 'http://schemas.xmlsoap.org/soap/encoding/',
59
+ :namespace => @namespace
60
+ end
61
+ xml.output do
62
+ xml.tag! "soap:body",
63
+ :use => "encoded", :encodingStyle => 'http://schemas.xmlsoap.org/soap/encoding/',
64
+ :namespace => @namespace
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ xml.service :name => "service" do
71
+ xml.port :name => "#{@name}_port", :binding => "#{@name}_binding" do
72
+ xml.tag! "soap:address", :location => url_for(:action => :soap, :only_path => false)
73
+ end
74
+ end
75
+ end
data/init.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'crack/xml'
2
+ require 'wash_out/param'
3
+ require 'wash_out/dispatcher'
4
+ require 'wash_out/wash_with_soap'
5
+
6
+ ActionController::Base.class_eval do
7
+ include WashOut::WashWithSoap
8
+ end
9
+
10
+ ActionController::Base.helper(WashOutHelper)
11
+
12
+ module ActionDispatch::Routing
13
+ class Mapper
14
+ def wash_with_soap(controller)
15
+ match "#{controller.to_s}/wsdl" => "#{controller.to_s}#wsdl"
16
+ match "#{controller.to_s}/soap" => "#{controller.to_s}#soap"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ module WashOut
2
+ module Dispatcher
3
+ def wsdl
4
+ @map = self.class.wash_with_soap_map
5
+ @name = controller_path.gsub('/', '_')
6
+ @namespace = 'urn:WashOut'
7
+
8
+ render :template => 'wash_with_soap/wsdl'
9
+ end
10
+
11
+ def soap
12
+ @map = self.class.wash_with_soap_map
13
+ @method = request.env['HTTP_SOAPACTION'].gsub(/^\"(.*)\"$/, '\1')
14
+ @current = @map[@method] || @map[@method.to_sym]
15
+
16
+ wash_out_error("Method does not exist") and return if @current.blank?
17
+
18
+ data = Crack::XML.parse(request.raw_post).values.first.select{|k,v| k[-4,4] == "Body"}.values.first[@method]
19
+
20
+ @soap = @current[:in].load(data)
21
+ @result = @current[:out].load(send @method.to_sym)
22
+
23
+ render :template => 'wash_with_soap/response'
24
+ end
25
+
26
+ private
27
+
28
+ def wash_out_error(description)
29
+ @error = description and render :template => 'wash_with_soap/error'
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,66 @@
1
+ module WashOut
2
+ class Param
3
+ attr_accessor :name
4
+ attr_accessor :map
5
+ attr_accessor :type
6
+ attr_accessor :multiplied
7
+
8
+ attr_accessor :value
9
+ def value
10
+ struct? ? map : @value
11
+ end
12
+
13
+ def [](key)
14
+ map[key]
15
+ end
16
+
17
+ def struct?
18
+ type == 'struct'
19
+ end
20
+
21
+ def namespaced_type
22
+ struct? ? "typens:#{name}" : "xsd:#{type}"
23
+ end
24
+
25
+ def initialize(name, type, multiplied = false)
26
+ type ||= {}
27
+
28
+ @name = name.to_s
29
+ @map = {}
30
+ @multiplied = multiplied
31
+
32
+ if type.is_a?(Hash)
33
+ @type = 'struct'
34
+
35
+ type.each do |name, type|
36
+ if type.is_a?(Array)
37
+ @map[name.to_s] = Param.new(name, type[0], true)
38
+ else
39
+ @map[name.to_s] = Param.new(name, type)
40
+ end
41
+ end
42
+ else
43
+ @type = type.to_s
44
+ end
45
+ end
46
+
47
+ def load(data)
48
+ if struct?
49
+ map.each do |name, param|
50
+ param.load(data[name] || data[name.to_sym])
51
+ end
52
+ else
53
+ @value = Param.convert_scalar(data, type)
54
+ end
55
+
56
+ self
57
+ end
58
+
59
+ def self.convert_scalar(data, type)
60
+ return data.to_s if type == 'string'
61
+ return data.to_i if type == 'integer'
62
+ return data.to_f if type == 'double'
63
+ return data.to_bool if type == 'boolean'
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,24 @@
1
+ module WashOut
2
+ module WashWithSoap
3
+ def self.included(base)
4
+
5
+ base.class_eval do
6
+ class <<self
7
+ attr_accessor :wash_with_soap_map
8
+ end
9
+
10
+ def self.wash_with_soap(map)
11
+ map.each do |method, params|
12
+ params[:in] = WashOut::Param.new(method, map[method][:in]) unless map[method][:in].is_a?(Param)
13
+ params[:out] = WashOut::Param.new("#{method}_responce", map[method][:out]) unless map[method][:out].is_a?(Param)
14
+ end
15
+
16
+ self.wash_with_soap_map = map
17
+
18
+ include WashOut::Dispatcher
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
data/wash_out.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ SPEC = Gem::Specification.new do |s|
2
+ s.name = "wash_out"
3
+ s.version = "0.1"
4
+ s.platform = Gem::Platform::RUBY
5
+ s.summary = "Dead simple Rails 3 SOAP server library"
6
+ s.email = "boris@roundlake.ru"
7
+ s.homepage = "http://github.com/roundlake/wash_out"
8
+ s.description = "Dead simple Rails 3 SOAP server library"
9
+ s.authors = ['Boris Staal']
10
+
11
+ s.add_dependency "crack"
12
+
13
+ s.has_rdoc = false # disable rdoc generation until we've got more
14
+ s.files = `git ls-files`.split("\n")
15
+ s.require_paths = ["lib"]
16
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wash_out
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Boris Staal
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-08-15 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: crack
16
+ requirement: &70092761237000 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70092761237000
25
+ description: Dead simple Rails 3 SOAP server library
26
+ email: boris@roundlake.ru
27
+ executables: []
28
+ extensions: []
29
+ extra_rdoc_files: []
30
+ files:
31
+ - README.rdoc
32
+ - app/helpers/wash_out_helper.rb
33
+ - app/views/wash_with_soap/error.builder
34
+ - app/views/wash_with_soap/response.builder
35
+ - app/views/wash_with_soap/wsdl.builder
36
+ - init.rb
37
+ - lib/wash_out/dispatcher.rb
38
+ - lib/wash_out/param.rb
39
+ - lib/wash_out/wash_with_soap.rb
40
+ - wash_out.gemspec
41
+ homepage: http://github.com/roundlake/wash_out
42
+ licenses: []
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project:
61
+ rubygems_version: 1.8.6
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: Dead simple Rails 3 SOAP server library
65
+ test_files: []