diff --git a/README.md b/README.md index dc6c4bd9..0e6b53ee 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,47 @@ Keep in mind that the password may already be hashed by the SOAP client, so you Use `config.wash_out...` inside your environment configuration to setup WashOut globally. To override the values on a specific controller just add an override as part of the arguments to the `soap_service` method. +## WSDL Documentation + +To generate a document of WSDL If the style is default "document" then generated document will be consist of nillable=true. To make a particular field as optional can do it by below: + +```ruby +# config/routes.rb + # Reading SOAP Headers + # This is different than normal SOAP params, because we don't specify the incoming format of the header, + # but we can still access it through `soap_request.headers`. Note that the values are all strings or hashes. + soap_action "AddCircleWithHeaderRadius", + :args => { :circle => { :center => { :x => [:integer,true], + :y => :integer } } }, + :return => nil, # [] for wash_out below 0.3.0 + :to => :add_circle + # e.g. for a request to the 'AddCircleWithHeaderRadius' action: + # + # + # 12345 + # + # + # + # + #
+ # + # + # + # + def add_circle_with_header_radius + circle = params[:circle] + radius = soap_request.headers[:radius] + raise SOAPError, "radius must be specified in the SOAP header" if radius.blank? + radius = radius.to_f + raise SOAPError, "radius is too small" if radius < 3.0 + + Circle.new(circle[:center][:x], circle[:center][:y], radius) + + render :soap => nil + end +``` +If it generates nillable true for all then it will not valid a WSDL so to avoid it above option can help to make nillable true for particular section. + Available properties are: * **parser**: XML parser to use – `:rexml` or `:nokogiri`. The first one is default but the latter is much faster. Be sure to add `gem nokogiri` if you want to use it. diff --git a/app/helpers/wash_out_helper.rb b/app/helpers/wash_out_helper.rb index 7a6008b0..1b42835d 100644 --- a/app/helpers/wash_out_helper.rb +++ b/app/helpers/wash_out_helper.rb @@ -3,15 +3,13 @@ module WashOutHelper def wsdl_data_options(param) case controller.soap_config.wsdl_style when 'rpc' - if param.map.present? || !param.value.nil? + if param.map.present? || param.value { :"xsi:type" => param.namespaced_type } else { :"xsi:nil" => true } end when 'document' - {} - else - {} + { } end end @@ -24,46 +22,9 @@ def wsdl_data_attrs(param) end end end - - def wsdl_data(xml, params) - params.each do |param| - next if param.attribute? - - tag_name = param.name - param_options = wsdl_data_options(param) - param_options.merge! wsdl_data_attrs(param) - - if param.struct? - if param.multiplied - param.map.each do |p| - attrs = wsdl_data_attrs p - if p.is_a?(Array) || p.map.size > attrs.size - blk = proc { wsdl_data(xml, p.map) } - end - attrs.reject! { |_, v| v.nil? } - xml.tag! tag_name, param_options.merge(attrs), &blk - end - else - xml.tag! tag_name, param_options do - wsdl_data(xml, param.map) - end - end - else - if param.multiplied - param.value = [] unless param.value.is_a?(Array) - param.value.each do |v| - xml.tag! tag_name, v, param_options - end - else - xml.tag! tag_name, param.value, param_options - end - end - end - end - + def wsdl_type(xml, param, defined=[]) more = [] - if param.struct? if !defined.include?(param.basic_type) xml.tag! "xsd:complexType", :name => param.basic_type do @@ -75,8 +36,7 @@ def wsdl_type(xml, param, defined=[]) else elems << value end - end - + end if elems.any? xml.tag! "xsd:sequence" do elems.each do |value| @@ -101,12 +61,68 @@ def wsdl_type(xml, param, defined=[]) end end - def wsdl_occurence(param, inject, extend_with = {}) - data = {"#{'xsi:' if inject}nillable" => 'true'} - if param.multiplied - data["#{'xsi:' if inject}minOccurs"] = 0 - data["#{'xsi:' if inject}maxOccurs"] = 'unbounded' + def wsdl_occurence(param, inject, extend_with = {}) + if (param.multiplied && param.optional) + data = { + "#{'xsi:' if inject}minOccurs" => 0, + "#{'xsi:' if inject}maxOccurs" => 'unbounded', + "#{'xsi:' if inject}nillable" => 'true' + } + + elsif param.multiplied + data = { + "#{'xsi:' if inject}minOccurs" => 0, + "#{'xsi:' if inject}maxOccurs" => 'unbounded' + } + elsif param.optional + data = {"#{'xsi:' if inject}nillable" => 'true'} + # data = { + # "#{'xsi:' if inject}minOccurs" => 0, + # } + else + data = {} end + extend_with.merge(data) end + + def wsdl_data(xml, params) + Rails.logger.debug params + params.each do |param| + tag_name = param.name + + if !param.struct? + if param.multiplied + param.value = [] unless param.value.is_a?(Array) + param.value.each do |v| + xml.tag! tag_name, v, "xsi:type" => param.namespaced_type + end + elsif param.optional + if !param.value.nil? + xml.tag! tag_name, param.value, "xsi:type" => param.namespaced_type + end + else + xml.tag! tag_name, param.value, "xsi:type" => param.namespaced_type + end + else + if param.multiplied + param.map.each do |p| + xml.tag! tag_name, "xsi:type" => param.namespaced_type do + wsdl_data(xml, p.map) + end + end + elsif param.optional + if !param.map.empty? + xml.tag! tag_name, "xsi:type" => param.namespaced_type do + wsdl_data(xml, param.map) + end + end + else + xml.tag! tag_name, "xsi:type" => param.namespaced_type do + wsdl_data(xml, param.map) + end + end + end + end + end end diff --git a/lib/wash_out/param.rb b/lib/wash_out/param.rb index 83c9bf5e..0857e958 100644 --- a/lib/wash_out/param.rb +++ b/lib/wash_out/param.rb @@ -8,16 +8,18 @@ class Param attr_accessor :value attr_accessor :source_class attr_accessor :soap_config + attr_accessor :optional # Defines a WSDL parameter with name +name+ and type specifier +type+. # The type specifier format is described in #parse_def. - def initialize(soap_config, name, type, multiplied = false) + def initialize(soap_config, name, type, multiplied = false,optional=false) type ||= {} @soap_config = soap_config @name = name.to_s @raw_name = name.to_s @map = {} @multiplied = multiplied + @optional = optional if soap_config.camelize_wsdl.to_s == 'lower' @name = @name.camelize(:lower) @@ -43,7 +45,6 @@ def load(data, key) if !data.has_key? key raise WashOut::Dispatcher::SOAPError, "Required SOAP parameter '#{key}' is missing" end - data = data[key] data = [data] if @multiplied && !data.is_a?(Array) @@ -148,10 +149,12 @@ def self.parse_def(soap_config, definition) definition.map do |name, opt| if opt.is_a? WashOut::Param opt + elsif (opt.is_a?(Array)) && (opt[0].is_a?(Array)) + WashOut::Param.new(soap_config, name, opt[0][0], true,opt[0][1]) elsif opt.is_a? Array - WashOut::Param.new(soap_config, name, opt[0], true) + WashOut::Param.new(soap_config, name, opt[0], false,opt[1]) else - WashOut::Param.new(soap_config, name, opt) + WashOut::Param.new(soap_config, name, opt,false) end end else @@ -160,7 +163,7 @@ def self.parse_def(soap_config, definition) end def flat_copy - copy = self.class.new(@soap_config, @name, @type.to_sym, @multiplied) + copy = self.class.new(@soap_config, @name, @type.to_sym, @multiplied,@optional) copy.raw_name = raw_name copy.source_class = source_class copy