actionwebservice 1.0.0 → 1.1.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.
data/CHANGELOG CHANGED
@@ -1,8 +1,34 @@
1
+ *1.1.0* (March 27th, 2005)
2
+
3
+ * Make ActiveWebService::Struct type reloadable
4
+
5
+ * Fix scaffolding action when one of the members of a structural type has date or time type
6
+
7
+ * Remove extra index hash when generating scaffold html for parameters of structural type #4374 [joe@mjg2.com]
8
+
9
+ * Fix Scaffold Fails with Struct as a Parameter #4363 [joe@mjg2.com]
10
+
11
+ * Fix soap type registration of multidimensional arrays (#4232)
12
+
13
+ * Fix that marshaler couldn't handle ActiveRecord models defined in a different namespace (#2392).
14
+
15
+ * Fix that marshaler couldn't handle structs with members of ActiveRecord type (#1889).
16
+
17
+ * Fix that marshaler couldn't handle nil values for inner structs (#3576).
18
+
19
+ * Fix that changes to ActiveWebService::API::Base required restarting of the server (#2390).
20
+
21
+ * Fix scaffolding for signatures with :date, :time and :base64 types (#3321, #2769, #2078).
22
+
23
+ * Fix for incorrect casting of TrueClass/FalseClass instances (#2633, #3421).
24
+
25
+ * Fix for incompatibility problems with SOAP4R 1.5.5 (#2553) [Kent Sibilev]
26
+
27
+
1
28
  *1.0.0* (December 13th, 2005)
2
29
 
3
30
  * Become part of Rails 1.0
4
31
 
5
-
6
32
  *0.9.4* (December 7th, 2005)
7
33
 
8
34
  * Update from LGPL to MIT license as per Minero Aoki's permission. [Marcel Molina Jr.]
@@ -11,7 +37,6 @@
11
37
 
12
38
  * Fix that XML-RPC date/time values did not have well-defined behaviour (#2516, #2534). This fix has one caveat, in that we can't support pre-1970 dates from XML-RPC clients.
13
39
 
14
-
15
40
  *0.9.3* (November 7th, 2005)
16
41
 
17
42
  * Upgraded to Action Pack 1.11.0 and Active Record 1.13.0
data/Rakefile CHANGED
@@ -30,12 +30,20 @@ Rake::TestTask.new { |t|
30
30
  t.verbose = true
31
31
  }
32
32
 
33
+ SCHEMA_PATH = File.join(File.dirname(__FILE__), *%w(test fixtures db_definitions))
34
+
35
+ desc 'Build the MySQL test database'
36
+ task :build_database do
37
+ %x( mysqladmin create activewebservice_unittest )
38
+ %x( mysql activewebservice_unittest < #{File.join(SCHEMA_PATH, 'mysql.sql')} )
39
+ end
40
+
33
41
 
34
42
  # Generate the RDoc documentation
35
43
  Rake::RDocTask.new { |rdoc|
36
44
  rdoc.rdoc_dir = 'doc'
37
45
  rdoc.title = "Action Web Service -- Web services for Action Pack"
38
- rdoc.options << '--line-numbers --inline-source --main README --accessor class_inheritable_option=RW'
46
+ rdoc.options << '--line-numbers' << '--inline-source'
39
47
  rdoc.template = "#{ENV['template']}.rb" if ENV['template']
40
48
  rdoc.rdoc_files.include('README')
41
49
  rdoc.rdoc_files.include('CHANGELOG')
@@ -63,8 +71,8 @@ spec = Gem::Specification.new do |s|
63
71
  s.rubyforge_project = "aws"
64
72
  s.homepage = "http://www.rubyonrails.org"
65
73
 
66
- s.add_dependency('actionpack', '= 1.11.2' + PKG_BUILD)
67
- s.add_dependency('activerecord', '= 1.13.2' + PKG_BUILD)
74
+ s.add_dependency('actionpack', '= 1.12.0' + PKG_BUILD)
75
+ s.add_dependency('activerecord', '= 1.14.0' + PKG_BUILD)
68
76
 
69
77
  s.has_rdoc = true
70
78
  s.requirements << 'none'
@@ -14,6 +14,10 @@ module ActionWebService # :nodoc:
14
14
  # See ActionWebService::Container::Direct::ClassMethods for an example
15
15
  # of use.
16
16
  class Base
17
+ # Action WebService API subclasses should be reloaded by the dispatcher in Rails
18
+ # when Dependencies.mechanism = :load.
19
+ include Reloadable::Subclasses
20
+
17
21
  # Whether to transform the public API method names into camel-cased names
18
22
  class_inheritable_option :inflect_names, true
19
23
 
@@ -25,12 +25,16 @@ module ActionWebService # :nodoc:
25
25
  # api_method :delete_person, :expects => [:int]
26
26
  # end
27
27
  #
28
- # class SearchCriteria < ActionStruct::Base
28
+ # class SearchCriteria < ActionWebService::Struct
29
29
  # member :firstname, :string
30
30
  # member :lastname, :string
31
31
  # member :email, :string
32
32
  # end
33
33
  class Base
34
+ # Action WebService subclasses should be reloaded by the dispatcher in Rails
35
+ # when Dependencies.mechanism = :load.
36
+ include Reloadable::Subclasses
37
+
34
38
  # Whether to report exceptions back to the caller in the protocol's exception
35
39
  # format
36
40
  class_inheritable_option :web_service_exception_reporting, true
@@ -41,6 +41,11 @@ module ActionWebService # :nodoc:
41
41
  def cast(value, signature_type) # :nodoc:
42
42
  return value if signature_type.nil? # signature.length != params.length
43
43
  return nil if value.nil?
44
+ # XMLRPC protocol doesn't support nil values. It uses false instead.
45
+ # It should never happen for SOAP.
46
+ if signature_type.structured? && value.equal?(false)
47
+ return nil
48
+ end
44
49
  unless signature_type.array? || signature_type.structured?
45
50
  return value if canonical_type(value.class) == signature_type.type
46
51
  end
@@ -91,10 +96,13 @@ module ActionWebService # :nodoc:
91
96
  when :float
92
97
  Float(value)
93
98
  when :time
99
+ value = "#{value['2']}/#{value['3']}/#{value['1']} #{value['4']}:#{value['5']}:#{value['6']}" if value.kind_of?(Hash)
94
100
  Time.parse(value.to_s)
95
101
  when :date
102
+ value = "#{value['2']}/#{value['3']}/#{value['1']}" if value.kind_of?(Hash)
96
103
  Date.parse(value.to_s)
97
104
  when :datetime
105
+ value = "#{value['2']}/#{value['3']}/#{value['1']} #{value['4']}:#{value['5']}:#{value['6']}" if value.kind_of?(Hash)
98
106
  DateTime.parse(value.to_s)
99
107
  end
100
108
  end
@@ -108,6 +116,8 @@ module ActionWebService # :nodoc:
108
116
  value.each_pair do |name, val|
109
117
  type = klass.respond_to?(:member_type) ? klass.member_type(name) : nil
110
118
  val = cast(val, type) if type
119
+ # See http://dev.rubyonrails.com/ticket/3567
120
+ val = val.to_time if val.is_a?(XMLRPC::DateTime)
111
121
  obj.__send__("#{name}=", val) if obj.respond_to?(name)
112
122
  end
113
123
  elsif value.respond_to?(:attributes)
@@ -80,12 +80,20 @@ module ActionWebService # :nodoc:
80
80
  if expects
81
81
  expects.each do |type|
82
82
  type_binding = @protocol.marshaler.lookup_type(type)
83
- param_def << ['in', type.name, type_binding.mapping]
83
+ if SOAP::Version >= "1.5.5"
84
+ param_def << ['in', type.name.to_s, [type_binding.type.type_class.to_s]]
85
+ else
86
+ param_def << ['in', type.name, type_binding.mapping]
87
+ end
84
88
  end
85
89
  end
86
90
  if returns
87
91
  type_binding = @protocol.marshaler.lookup_type(returns[0])
88
- param_def << ['retval', 'return', type_binding.mapping]
92
+ if SOAP::Version >= "1.5.5"
93
+ param_def << ['retval', 'return', [type_binding.type.type_class.to_s]]
94
+ else
95
+ param_def << ['retval', 'return', type_binding.mapping]
96
+ end
89
97
  end
90
98
  driver.add_method(qname, action, method.name.to_s, param_def)
91
99
  end
@@ -32,43 +32,47 @@ module ActionWebService
32
32
  end
33
33
 
34
34
  def ruby_to_soap(obj)
35
- SOAP::Mapping.obj2soap(obj, @registry)
35
+ soap = SOAP::Mapping.obj2soap(obj, @registry)
36
+ soap.elename = XSD::QName.new if SOAP::Version >= "1.5.5" && soap.elename == XSD::QName::EMPTY
37
+ soap
36
38
  end
37
39
 
38
40
  def register_type(type)
39
41
  return @type2binding[type] if @type2binding.has_key?(type)
40
42
 
41
- type_class = type.array?? type.element_type.type_class : type.type_class
42
- type_type = type.array?? type.element_type : type
43
- type_binding = nil
44
- if (mapping = @registry.find_mapped_soap_class(type_class) rescue nil)
45
- qname = mapping[2] ? mapping[2][:type] : nil
46
- qname ||= soap_base_type_name(mapping[0])
47
- type_binding = SoapBinding.new(self, qname, type_type, mapping)
48
- else
49
- qname = XSD::QName.new(@namespace, soap_type_name(type_class.name))
50
- @registry.add(type_class,
51
- SOAP::SOAPStruct,
52
- typed_struct_factory(type_class),
53
- { :type => qname })
54
- mapping = @registry.find_mapped_soap_class(type_class)
55
- type_binding = SoapBinding.new(self, qname, type_type, mapping)
56
- end
57
-
58
- array_binding = nil
59
43
  if type.array?
60
44
  array_mapping = @registry.find_mapped_soap_class(Array)
61
45
  qname = XSD::QName.new(@namespace, soap_type_name(type.element_type.type_class.name) + 'Array')
62
- array_binding = SoapBinding.new(self, qname, type, array_mapping, type_binding)
46
+ element_type_binding = register_type(type.element_type)
47
+ @type2binding[type] = SoapBinding.new(self, qname, type, array_mapping, element_type_binding)
48
+ elsif (mapping = @registry.find_mapped_soap_class(type.type_class) rescue nil)
49
+ qname = mapping[2] ? mapping[2][:type] : nil
50
+ qname ||= soap_base_type_name(mapping[0])
51
+ @type2binding[type] = SoapBinding.new(self, qname, type, mapping)
52
+ else
53
+ qname = XSD::QName.new(@namespace, soap_type_name(type.type_class.name))
54
+ @registry.add(type.type_class,
55
+ SOAP::SOAPStruct,
56
+ typed_struct_factory(type.type_class),
57
+ { :type => qname })
58
+ mapping = @registry.find_mapped_soap_class(type.type_class)
59
+ @type2binding[type] = SoapBinding.new(self, qname, type, mapping)
60
+ end
61
+
62
+ if type.structured?
63
+ type.each_member do |m_name, m_type|
64
+ register_type(m_type)
65
+ end
63
66
  end
64
-
65
- @type2binding[type] = array_binding ? array_binding : type_binding
67
+
66
68
  @type2binding[type]
67
69
  end
68
70
  alias :lookup_type :register_type
69
71
 
70
72
  def annotate_arrays(binding, value)
71
- if binding.type.array?
73
+ if value.nil?
74
+ return
75
+ elsif binding.type.array?
72
76
  mark_typed_array(value, binding.element_binding.qname)
73
77
  if binding.element_binding.type.custom?
74
78
  value.each do |element|
@@ -50,10 +50,10 @@ module ActionWebService # :nodoc:
50
50
  end
51
51
 
52
52
  def encode_response(method_name, return_value, return_type, protocol_options={})
53
- return_value = true if return_value.nil?
54
- if return_type
53
+ if return_value && return_type
55
54
  return_value = value_to_xmlrpc_wire_format(return_value, return_type)
56
55
  end
56
+ return_value = false if return_value.nil?
57
57
  raw_response = XMLRPC::Marshal.dump_response(return_value)
58
58
  Response.new(raw_response, 'text/xml', return_value)
59
59
  end
@@ -65,16 +65,13 @@ module ActionWebService
65
65
  when :xmlrpc
66
66
  @protocol = Protocol::XmlRpc::XmlRpcProtocol.create(self)
67
67
  end
68
- @invocation_cgi = request.respond_to?(:cgi) ? request.cgi : nil
69
68
  bm = Benchmark.measure do
70
69
  @protocol.register_api(@scaffold_service.api)
71
70
  post_params = params['method_params'] ? params['method_params'].dup : nil
72
71
  params = []
73
- if @scaffold_method.expects
74
- @scaffold_method.expects.length.times do |i|
75
- params << post_params[i.to_s]
76
- end
77
- end
72
+ @scaffold_method.expects.each_with_index do |spec, i|
73
+ params << post_params[i.to_s]
74
+ end if @scaffold_method.expects
78
75
  params = @scaffold_method.cast_expects(params)
79
76
  method_name = public_method_name(@scaffold_service.name, @scaffold_method.public_name)
80
77
  @method_request_xml = @protocol.encode_request(method_name, params, @scaffold_method.expects)
@@ -130,14 +127,8 @@ module ActionWebService
130
127
  end
131
128
 
132
129
  def reset_invocation_response
133
- template = response.template
134
- if @invocation_cgi
135
- @response = ::ActionController::CgiResponse.new(@invocation_cgi)
136
- else
137
- @response = ::ActionController::TestResponse.new
138
- end
139
- response.template = template
140
- @performed_render = false
130
+ erase_render_results
131
+ @response.headers = ::ActionController::AbstractResponse::DEFAULT_HEADERS.merge("cookie" => [])
141
132
  end
142
133
 
143
134
  def public_method_name(service_name, method_name)
@@ -173,18 +164,21 @@ module ActionWebService
173
164
  end
174
165
 
175
166
  module Helpers # :nodoc:
176
- def method_parameter_input_fields(method, type, field_name_base)
167
+ def method_parameter_input_fields(method, type, field_name_base, idx, was_structured=false)
177
168
  if type.array?
178
169
  return content_tag('em', "Typed array input fields not supported yet (#{type.name})")
179
170
  end
180
171
  if type.structured?
172
+ return content_tag('em', "Nested structural types not supported yet (#{type.name})") if was_structured
181
173
  parameters = ""
182
174
  type.each_member do |member_name, member_type|
183
175
  label = method_parameter_label(member_name, member_type)
184
176
  nested_content = method_parameter_input_fields(
185
177
  method,
186
178
  member_type,
187
- field_name_base + '[' + member_name.to_s + ']')
179
+ "#{field_name_base}[#{idx}][#{member_name}]",
180
+ idx,
181
+ true)
188
182
  if member_type.custom?
189
183
  parameters << content_tag('li', label)
190
184
  parameters << content_tag('ul', nested_content)
@@ -194,20 +188,35 @@ module ActionWebService
194
188
  end
195
189
  content_tag('ul', parameters)
196
190
  else
191
+ # If the data source was structured previously we already have the index set
192
+ field_name_base = "#{field_name_base}[#{idx}]" unless was_structured
193
+
197
194
  case type.type
198
195
  when :int
199
- text_field_tag field_name_base
196
+ text_field_tag "#{field_name_base}"
200
197
  when :string
201
- text_field_tag field_name_base
198
+ text_field_tag "#{field_name_base}"
199
+ when :base64
200
+ text_area_tag "#{field_name_base}", nil, :size => "40x5"
202
201
  when :bool
203
- radio_button_tag(field_name_base, "true") + " True" +
204
- radio_button_tag(field_name_base, "false") + "False"
202
+ radio_button_tag("#{field_name_base}", "true") + " True" +
203
+ radio_button_tag("#{field_name_base}", "false") + "False"
205
204
  when :float
206
- text_field_tag field_name_base
207
- when :time
208
- select_datetime Time.now, 'name' => field_name_base
205
+ text_field_tag "#{field_name_base}"
206
+ when :time, :datetime
207
+ time = Time.now
208
+ i = 0
209
+ %w|year month day hour minute second|.map do |name|
210
+ i += 1
211
+ send("select_#{name}", time, :prefix => "#{field_name_base}[#{i}]", :discard_type => true)
212
+ end.join
209
213
  when :date
210
- select_date Date.today, 'name' => field_name_base
214
+ date = Date.today
215
+ i = 0
216
+ %w|year month day|.map do |name|
217
+ i += 1
218
+ send("select_#{name}", date, :prefix => "#{field_name_base}[#{i}]", :discard_type => true)
219
+ end.join
211
220
  end
212
221
  end
213
222
  end
@@ -19,6 +19,9 @@ module ActionWebService
19
19
  # Active Record model classes are already implicitly supported in method
20
20
  # signatures.
21
21
  class Struct
22
+ # Action WebService Struct subclasses should be reloaded by the dispatcher in Rails
23
+ # when Dependencies.mechanism = :load.
24
+ include Reloadable::Subclasses
22
25
 
23
26
  # If a Hash is given as argument to an ActionWebService::Struct constructor,
24
27
  # it can contain initial values for the structure member.
@@ -53,9 +53,9 @@ module ActionWebService # :nodoc:
53
53
  case name
54
54
  when :int, :integer, :fixnum, :bignum
55
55
  :int
56
- when :string
56
+ when :string, :text
57
57
  :string
58
- when :base64
58
+ when :base64, :binary
59
59
  :base64
60
60
  when :bool, :boolean
61
61
  :bool
@@ -203,7 +203,7 @@ module ActionWebService # :nodoc:
203
203
  elsif @type_class.respond_to?(:columns)
204
204
  i = -1
205
205
  @type_class.columns.each do |column|
206
- yield column.name, canonical_signature_entry(column.klass, i += 1)
206
+ yield column.name, canonical_signature_entry(column.type, i += 1)
207
207
  end
208
208
  end
209
209
  end
@@ -26,7 +26,7 @@
26
26
  display: table;
27
27
  }
28
28
 
29
- #ErrorExplanation {
29
+ #errorExplanation {
30
30
  width: 400px;
31
31
  border: 2px solid red;
32
32
  padding: 7px;
@@ -35,7 +35,7 @@
35
35
  background-color: #f0f0f0;
36
36
  }
37
37
 
38
- #ErrorExplanation h2 {
38
+ #errorExplanation h2 {
39
39
  text-align: left;
40
40
  font-weight: bold;
41
41
  padding: 5px 5px 5px 15px;
@@ -45,13 +45,13 @@
45
45
  color: #fff;
46
46
  }
47
47
 
48
- #ErrorExplanation p {
48
+ #errorExplanation p {
49
49
  color: #333;
50
50
  margin-bottom: 0;
51
51
  padding: 5px;
52
52
  }
53
53
 
54
- #ErrorExplanation ul li {
54
+ #errorExplanation ul li {
55
55
  font-size: 12px;
56
56
  list-style: square;
57
57
  }
@@ -10,20 +10,19 @@
10
10
  </p>
11
11
 
12
12
  <% if @scaffold_method.expects %>
13
- <% i = 0 %>
14
13
 
15
14
  <strong>Method Parameters:</strong><br />
16
- <% @scaffold_method.expects.each do |type| %>
15
+ <% @scaffold_method.expects.each_with_index do |type, i| %>
17
16
  <p>
18
17
  <label for="method_params[<%= i %>]"><%= method_parameter_label(type.name, type) %> </label><br />
19
- <%= method_parameter_input_fields(@scaffold_method, type, "method_params[#{i}]") %>
18
+ <%= method_parameter_input_fields(@scaffold_method, type, "method_params", i) %>
20
19
  </p>
21
- <% i += 1 %>
22
20
  <% end %>
23
21
 
24
22
  <% end %>
25
23
 
26
24
  <%= submit_tag "Invoke" %>
25
+ <%= end_form_tag %>
27
26
 
28
27
  <p>
29
28
  <%= link_to "Back", :action => @scaffold_action_name %>
@@ -1,7 +1,7 @@
1
1
  module ActionWebService
2
- module VERSION
2
+ module VERSION #:nodoc:
3
3
  MAJOR = 1
4
- MINOR = 0
4
+ MINOR = 1
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
@@ -12,17 +12,49 @@ module ClientTest
12
12
  firstnames == other.firstnames && lastname == other.lastname
13
13
  end
14
14
  end
15
+
16
+ class Inner < ActionWebService::Struct
17
+ member :name, :string
18
+ end
19
+
20
+ class Outer < ActionWebService::Struct
21
+ member :name, :string
22
+ member :inner, Inner
23
+ end
24
+
25
+ class User < ActiveRecord::Base
26
+ end
27
+
28
+ module Accounting
29
+ class User < ActiveRecord::Base
30
+ end
31
+ end
32
+
33
+ class WithModel < ActionWebService::Struct
34
+ member :user, User
35
+ member :users, [User]
36
+ end
37
+
38
+ class WithMultiDimArray < ActionWebService::Struct
39
+ member :pref, [[:string]]
40
+ end
15
41
 
16
42
  class API < ActionWebService::API::Base
17
43
  api_method :void
18
- api_method :normal, :expects => [:int, :int], :returns => [:int]
19
- api_method :array_return, :returns => [[Person]]
20
- api_method :struct_pass, :expects => [[Person]], :returns => [:bool]
21
- api_method :client_container, :returns => [:int]
22
- api_method :named_parameters, :expects => [{:key=>:string}, {:id=>:int}]
44
+ api_method :normal, :expects => [:int, :int], :returns => [:int]
45
+ api_method :array_return, :returns => [[Person]]
46
+ api_method :struct_pass, :expects => [[Person]], :returns => [:bool]
47
+ api_method :nil_struct_return, :returns => [Person]
48
+ api_method :inner_nil, :returns => [Outer]
49
+ api_method :client_container, :returns => [:int]
50
+ api_method :named_parameters, :expects => [{:key=>:string}, {:id=>:int}]
23
51
  api_method :thrower
52
+ api_method :user_return, :returns => [User]
53
+ api_method :with_model_return, :returns => [WithModel]
54
+ api_method :scoped_model_return, :returns => [Accounting::User]
55
+ api_method :multi_dim_return, :returns => [WithMultiDimArray]
24
56
  end
25
-
57
+
26
58
  class NullLogOut
27
59
  def <<(*args); end
28
60
  end
@@ -65,6 +97,14 @@ module ClientTest
65
97
  @value_struct_pass = @method_params
66
98
  true
67
99
  end
100
+
101
+ def nil_struct_return
102
+ nil
103
+ end
104
+
105
+ def inner_nil
106
+ Outer.new :name => 'outer', :inner => nil
107
+ end
68
108
 
69
109
  def client_container
70
110
  50
@@ -77,6 +117,22 @@ module ClientTest
77
117
  def thrower
78
118
  raise "Hi"
79
119
  end
120
+
121
+ def user_return
122
+ User.find(1)
123
+ end
124
+
125
+ def with_model_return
126
+ WithModel.new :user => User.find(1), :users => User.find(:all)
127
+ end
128
+
129
+ def scoped_model_return
130
+ Accounting::User.find(1)
131
+ end
132
+
133
+ def multi_dim_return
134
+ WithMultiDimArray.new :pref => [%w{pref1 value1}, %w{pref2 value2}]
135
+ end
80
136
  end
81
137
 
82
138
  class AbstractClientLet < WEBrick::HTTPServlet::AbstractServlet
@@ -5,10 +5,34 @@ $:.unshift(File.dirname(__FILE__) + '/../../actionpack/lib')
5
5
  $:.unshift(File.dirname(__FILE__) + '/../../activerecord/lib')
6
6
 
7
7
  require 'test/unit'
8
- require 'active_record'
9
8
  require 'action_web_service'
10
9
  require 'action_controller'
11
10
  require 'action_controller/test_process'
12
11
 
13
12
  ActionController::Base.logger = nil
14
13
  ActionController::Base.ignore_missing_templates = true
14
+
15
+ begin
16
+ PATH_TO_AR = File.dirname(__FILE__) + '/../../activerecord'
17
+ require "#{PATH_TO_AR}/lib/active_record" unless Object.const_defined?(:ActiveRecord)
18
+ require "#{PATH_TO_AR}/lib/active_record/fixtures" unless Object.const_defined?(:Fixtures)
19
+ rescue Object => e
20
+ fail "\nFailed to load activerecord: #{e}"
21
+ end
22
+
23
+ ActiveRecord::Base.establish_connection(
24
+ :adapter => "mysql",
25
+ :username => "rails",
26
+ :encoding => "utf8",
27
+ :database => "activewebservice_unittest"
28
+ )
29
+ ActiveRecord::Base.connection
30
+
31
+ Test::Unit::TestCase.fixture_path = "#{File.dirname(__FILE__)}/fixtures/"
32
+
33
+ # restore default raw_post functionality
34
+ class ActionController::TestRequest
35
+ def raw_post
36
+ super
37
+ end
38
+ end
@@ -49,6 +49,8 @@ end
49
49
  class TC_ClientSoap < Test::Unit::TestCase
50
50
  include ClientTest
51
51
  include ClientSoapTest
52
+
53
+ fixtures :users
52
54
 
53
55
  def setup
54
56
  @server = SoapServer.instance
@@ -88,6 +90,16 @@ class TC_ClientSoap < Test::Unit::TestCase
88
90
  assert_equal(true, @client.struct_pass([new_person]))
89
91
  assert_equal([[new_person]], @container.value_struct_pass)
90
92
  end
93
+
94
+ def test_nil_struct_return
95
+ assert_nil @client.nil_struct_return
96
+ end
97
+
98
+ def test_inner_nil
99
+ outer = @client.inner_nil
100
+ assert_equal 'outer', outer.name
101
+ assert_nil outer.inner
102
+ end
91
103
 
92
104
  def test_client_container
93
105
  assert_equal(50, ClientContainer.new.get_client.client_container)
@@ -106,4 +118,35 @@ class TC_ClientSoap < Test::Unit::TestCase
106
118
  assert_equal([5, 6], @container.value_normal)
107
119
  @container.value_normal = nil
108
120
  end
121
+
122
+ def test_model_return
123
+ user = @client.user_return
124
+ assert_equal 1, user.id
125
+ assert_equal 'Kent', user.name
126
+ assert user.active?
127
+ assert_kind_of Date, user.created_on
128
+ assert_equal Date.today, user.created_on
129
+ end
130
+
131
+ def test_with_model
132
+ with_model = @client.with_model_return
133
+ assert_equal 'Kent', with_model.user.name
134
+ assert_equal 2, with_model.users.size
135
+ with_model.users.each do |user|
136
+ assert_kind_of User, user
137
+ end
138
+ end
139
+
140
+ def test_scoped_model_return
141
+ scoped_model = @client.scoped_model_return
142
+ assert_kind_of Accounting::User, scoped_model
143
+ assert_equal 'Kent', scoped_model.name
144
+ end
145
+
146
+ def test_multi_dim_return
147
+ md_struct = @client.multi_dim_return
148
+ assert_kind_of Array, md_struct.pref
149
+ assert_equal 2, md_struct.pref.size
150
+ assert_kind_of Array, md_struct.pref[0]
151
+ end
109
152
  end
@@ -12,7 +12,7 @@ module ClientXmlRpcTest
12
12
  test_request.env['HTTP_CONTENT_TYPE'] = 'text/xml'
13
13
  test_request.env['RAW_POST_DATA'] = req.body
14
14
  response = ActionController::TestResponse.new
15
- @controller.process(test_request, response)
15
+ @controller.process(test_request, response)
16
16
  res.header['content-type'] = 'text/xml'
17
17
  res.body = response.body
18
18
  # puts res.body
@@ -44,6 +44,8 @@ end
44
44
  class TC_ClientXmlRpc < Test::Unit::TestCase
45
45
  include ClientTest
46
46
  include ClientXmlRpcTest
47
+
48
+ fixtures :users
47
49
 
48
50
  def setup
49
51
  @server = XmlRpcServer.instance
@@ -83,6 +85,16 @@ class TC_ClientXmlRpc < Test::Unit::TestCase
83
85
  assert_equal(true, @client.struct_pass([new_person]))
84
86
  assert_equal([[new_person]], @container.value_struct_pass)
85
87
  end
88
+
89
+ def test_nil_struct_return
90
+ assert_equal false, @client.nil_struct_return
91
+ end
92
+
93
+ def test_inner_nil
94
+ outer = @client.inner_nil
95
+ assert_equal 'outer', outer.name
96
+ assert_nil outer.inner
97
+ end
86
98
 
87
99
  def test_client_container
88
100
  assert_equal(50, ClientContainer.new.get_client.client_container)
@@ -90,7 +102,7 @@ class TC_ClientXmlRpc < Test::Unit::TestCase
90
102
 
91
103
  def test_named_parameters
92
104
  assert(@container.value_named_parameters.nil?)
93
- assert_equal(true, @client.named_parameters("xxx", 7))
105
+ assert_equal(false, @client.named_parameters("xxx", 7))
94
106
  assert_equal(["xxx", 7], @container.value_named_parameters)
95
107
  end
96
108
 
@@ -105,4 +117,35 @@ class TC_ClientXmlRpc < Test::Unit::TestCase
105
117
  @client.normal
106
118
  end
107
119
  end
120
+
121
+ def test_model_return
122
+ user = @client.user_return
123
+ assert_equal 1, user.id
124
+ assert_equal 'Kent', user.name
125
+ assert user.active?
126
+ assert_kind_of Time, user.created_on
127
+ assert_equal Time.utc(Time.now.year, Time.now.month, Time.now.day), user.created_on
128
+ end
129
+
130
+ def test_with_model
131
+ with_model = @client.with_model_return
132
+ assert_equal 'Kent', with_model.user.name
133
+ assert_equal 2, with_model.users.size
134
+ with_model.users.each do |user|
135
+ assert_kind_of User, user
136
+ end
137
+ end
138
+
139
+ def test_scoped_model_return
140
+ scoped_model = @client.scoped_model_return
141
+ assert_kind_of Accounting::User, scoped_model
142
+ assert_equal 'Kent', scoped_model.name
143
+ end
144
+
145
+ def test_multi_dim_return
146
+ md_struct = @client.multi_dim_return
147
+ assert_kind_of Array, md_struct.pref
148
+ assert_equal 2, md_struct.pref.size
149
+ assert_kind_of Array, md_struct.pref[0]
150
+ end
108
151
  end
@@ -0,0 +1,7 @@
1
+ CREATE TABLE `users` (
2
+ `id` int(11) NOT NULL auto_increment,
3
+ `name` varchar(30) default NULL,
4
+ `active` tinyint(4) default NULL,
5
+ `created_on` date default NULL,
6
+ PRIMARY KEY (`id`)
7
+ ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
@@ -0,0 +1,10 @@
1
+ user1:
2
+ id: 1
3
+ name: Kent
4
+ active: 1
5
+ created_on: <%= Date.today %>
6
+ user2:
7
+ id: 2
8
+ name: David
9
+ active: 1
10
+ created_on: <%= Date.today %>
@@ -2,11 +2,15 @@ require File.dirname(__FILE__) + '/abstract_unit'
2
2
 
3
3
  ActionController::Routing::Routes.draw do |map|
4
4
  map.connect '', :controller => 'scaffolded'
5
+ map.connect ':controller/:action/:id'
5
6
  end
6
7
 
8
+ ActionController::Base.template_root = '.'
9
+
7
10
  class ScaffoldPerson < ActionWebService::Struct
8
- member :id, :int
9
- member :name, :string
11
+ member :id, :int
12
+ member :name, :string
13
+ member :birth, :date
10
14
 
11
15
  def ==(other)
12
16
  self.id == other.id && self.name == other.name
@@ -15,7 +19,12 @@ end
15
19
 
16
20
  class ScaffoldedControllerTestAPI < ActionWebService::API::Base
17
21
  api_method :hello, :expects => [{:integer=>:int}, :string], :returns => [:bool]
22
+ api_method :hello_struct_param, :expects => [{:person => ScaffoldPerson}], :returns => [:bool]
23
+ api_method :date_of_birth, :expects => [ScaffoldPerson], :returns => [:string]
18
24
  api_method :bye, :returns => [[ScaffoldPerson]]
25
+ api_method :date_diff, :expects => [{:start_date => :date}, {:end_date => :date}], :returns => [:int]
26
+ api_method :time_diff, :expects => [{:start_time => :time}, {:end_time => :time}], :returns => [:int]
27
+ api_method :base64_upcase, :expects => [:base64], :returns => [:base64]
19
28
  end
20
29
 
21
30
  class ScaffoldedController < ActionController::Base
@@ -25,6 +34,14 @@ class ScaffoldedController < ActionController::Base
25
34
  def hello(int, string)
26
35
  0
27
36
  end
37
+
38
+ def hello_struct_param(person)
39
+ 0
40
+ end
41
+
42
+ def date_of_birth(person)
43
+ person.birth.to_s
44
+ end
28
45
 
29
46
  def bye
30
47
  [ScaffoldPerson.new(:id => 1, :name => "leon"), ScaffoldPerson.new(:id => 2, :name => "paul")]
@@ -33,6 +50,18 @@ class ScaffoldedController < ActionController::Base
33
50
  def rescue_action(e)
34
51
  raise e
35
52
  end
53
+
54
+ def date_diff(start_date, end_date)
55
+ end_date - start_date
56
+ end
57
+
58
+ def time_diff(start_time, end_time)
59
+ end_time - start_time
60
+ end
61
+
62
+ def base64_upcase(data)
63
+ data.upcase
64
+ end
36
65
  end
37
66
 
38
67
  class ScaffoldedControllerTest < Test::Unit::TestCase
@@ -51,6 +80,12 @@ class ScaffoldedControllerTest < Test::Unit::TestCase
51
80
  get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'Hello'
52
81
  assert_rendered_file 'parameters.rhtml'
53
82
  end
83
+
84
+ def test_scaffold_invoke_method_params_with_struct
85
+ get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'HelloStructParam'
86
+ assert_rendered_file 'parameters.rhtml'
87
+ assert_tag :tag => 'input', :attributes => {:name => "method_params[0][name]"}
88
+ end
54
89
 
55
90
  def test_scaffold_invoke_submit_hello
56
91
  post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'Hello', :method_params => {'0' => '5', '1' => 'hello world'}
@@ -64,4 +99,47 @@ class ScaffoldedControllerTest < Test::Unit::TestCase
64
99
  persons = [ScaffoldPerson.new(:id => 1, :name => "leon"), ScaffoldPerson.new(:id => 2, :name => "paul")]
65
100
  assert_equal persons, @controller.instance_eval{ @method_return_value }
66
101
  end
102
+
103
+ def test_scaffold_date_params
104
+ get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'DateDiff'
105
+ (0..1).each do |param|
106
+ (1..3).each do |date_part|
107
+ assert_tag :tag => 'select', :attributes => {:name => "method_params[#{param}][#{date_part}]"},
108
+ :children => {:greater_than => 1, :only => {:tag => 'option'}}
109
+ end
110
+ end
111
+
112
+ post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'DateDiff',
113
+ :method_params => {'0' => {'1' => '2006', '2' => '2', '3' => '1'}, '1' => {'1' => '2006', '2' => '2', '3' => '2'}}
114
+ assert_equal 1, @controller.instance_eval{ @method_return_value }
115
+ end
116
+
117
+ def test_scaffold_struct_date_params
118
+ post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'DateOfBirth',
119
+ :method_params => {'0' => {'birth' => {'1' => '2006', '2' => '2', '3' => '1'}, 'id' => '1', 'name' => 'person'}}
120
+ assert_equal '2006-02-01', @controller.instance_eval{ @method_return_value }
121
+ end
122
+
123
+ def test_scaffold_time_params
124
+ get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'TimeDiff'
125
+ (0..1).each do |param|
126
+ (1..6).each do |date_part|
127
+ assert_tag :tag => 'select', :attributes => {:name => "method_params[#{param}][#{date_part}]"},
128
+ :children => {:greater_than => 1, :only => {:tag => 'option'}}
129
+ end
130
+ end
131
+
132
+ post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'TimeDiff',
133
+ :method_params => {'0' => {'1' => '2006', '2' => '2', '3' => '1', '4' => '1', '5' => '1', '6' => '1'},
134
+ '1' => {'1' => '2006', '2' => '2', '3' => '2', '4' => '1', '5' => '1', '6' => '1'}}
135
+ assert_equal 86400, @controller.instance_eval{ @method_return_value }
136
+ end
137
+
138
+ def test_scaffold_base64
139
+ get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'Base64Upcase'
140
+ assert_tag :tag => 'textarea', :attributes => {:name => 'method_params[0]'}
141
+
142
+ post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'Base64Upcase', :method_params => {'0' => 'scaffold'}
143
+ assert_equal 'SCAFFOLD', @controller.instance_eval{ @method_return_value }
144
+ end
67
145
  end
metadata CHANGED
@@ -3,11 +3,11 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: actionwebservice
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.0
7
- date: 2005-12-13 00:00:00 -06:00
6
+ version: 1.1.0
7
+ date: 2006-03-27 00:00:00 -06:00
8
8
  summary: Web service support for Action Pack.
9
9
  require_paths:
10
- - lib
10
+ - lib
11
11
  email: bitserf@gmail.com
12
12
  homepage: http://www.rubyonrails.org
13
13
  rubyforge_project: aws
@@ -18,129 +18,135 @@ bindir: bin
18
18
  has_rdoc: true
19
19
  required_ruby_version: !ruby/object:Gem::Version::Requirement
20
20
  requirements:
21
- -
22
- - ">"
23
- - !ruby/object:Gem::Version
24
- version: 0.0.0
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
25
24
  version:
26
25
  platform: ruby
27
26
  signing_key:
28
27
  cert_chain:
29
28
  authors:
30
- - Leon Breedt
29
+ - Leon Breedt
31
30
  files:
32
- - Rakefile
33
- - setup.rb
34
- - README
35
- - TODO
36
- - CHANGELOG
37
- - MIT-LICENSE
38
- - examples/googlesearch
39
- - examples/metaWeblog
40
- - examples/googlesearch/autoloading
41
- - examples/googlesearch/delegated
42
- - examples/googlesearch/direct
43
- - examples/googlesearch/README
44
- - examples/googlesearch/autoloading/google_search_api.rb
45
- - examples/googlesearch/autoloading/google_search_controller.rb
46
- - examples/googlesearch/delegated/google_search_service.rb
47
- - examples/googlesearch/delegated/search_controller.rb
48
- - examples/googlesearch/direct/google_search_api.rb
49
- - examples/googlesearch/direct/search_controller.rb
50
- - examples/metaWeblog/apis
51
- - examples/metaWeblog/controllers
52
- - examples/metaWeblog/README
53
- - examples/metaWeblog/apis/blogger_api.rb
54
- - examples/metaWeblog/apis/blogger_service.rb
55
- - examples/metaWeblog/apis/meta_weblog_api.rb
56
- - examples/metaWeblog/apis/meta_weblog_service.rb
57
- - examples/metaWeblog/controllers/xmlrpc_controller.rb
58
- - lib/action_web_service
59
- - lib/action_web_service.rb
60
- - lib/action_web_service/api.rb
61
- - lib/action_web_service/base.rb
62
- - lib/action_web_service/casting.rb
63
- - lib/action_web_service/client
64
- - lib/action_web_service/client.rb
65
- - lib/action_web_service/container
66
- - lib/action_web_service/container.rb
67
- - lib/action_web_service/dispatcher
68
- - lib/action_web_service/dispatcher.rb
69
- - lib/action_web_service/invocation.rb
70
- - lib/action_web_service/protocol
71
- - lib/action_web_service/protocol.rb
72
- - lib/action_web_service/scaffolding.rb
73
- - lib/action_web_service/struct.rb
74
- - lib/action_web_service/support
75
- - lib/action_web_service/templates
76
- - lib/action_web_service/test_invoke.rb
77
- - lib/action_web_service/version.rb
78
- - lib/action_web_service/client/base.rb
79
- - lib/action_web_service/client/soap_client.rb
80
- - lib/action_web_service/client/xmlrpc_client.rb
81
- - lib/action_web_service/container/action_controller_container.rb
82
- - lib/action_web_service/container/delegated_container.rb
83
- - lib/action_web_service/container/direct_container.rb
84
- - lib/action_web_service/dispatcher/abstract.rb
85
- - lib/action_web_service/dispatcher/action_controller_dispatcher.rb
86
- - lib/action_web_service/protocol/abstract.rb
87
- - lib/action_web_service/protocol/discovery.rb
88
- - lib/action_web_service/protocol/soap_protocol
89
- - lib/action_web_service/protocol/soap_protocol.rb
90
- - lib/action_web_service/protocol/xmlrpc_protocol.rb
91
- - lib/action_web_service/protocol/soap_protocol/marshaler.rb
92
- - lib/action_web_service/support/class_inheritable_options.rb
93
- - lib/action_web_service/support/signature_types.rb
94
- - lib/action_web_service/templates/scaffolds
95
- - lib/action_web_service/templates/scaffolds/layout.rhtml
96
- - lib/action_web_service/templates/scaffolds/methods.rhtml
97
- - lib/action_web_service/templates/scaffolds/parameters.rhtml
98
- - lib/action_web_service/templates/scaffolds/result.rhtml
99
- - test/abstract_client.rb
100
- - test/abstract_dispatcher.rb
101
- - test/abstract_unit.rb
102
- - test/api_test.rb
103
- - test/apis
104
- - test/base_test.rb
105
- - test/casting_test.rb
106
- - test/client_soap_test.rb
107
- - test/client_xmlrpc_test.rb
108
- - test/container_test.rb
109
- - test/dispatcher_action_controller_soap_test.rb
110
- - test/dispatcher_action_controller_xmlrpc_test.rb
111
- - test/gencov
112
- - test/invocation_test.rb
113
- - test/run
114
- - test/scaffolded_controller_test.rb
115
- - test/struct_test.rb
116
- - test/test_invoke_test.rb
117
- - test/apis/auto_load_api.rb
118
- - test/apis/broken_auto_load_api.rb
31
+ - Rakefile
32
+ - setup.rb
33
+ - README
34
+ - TODO
35
+ - CHANGELOG
36
+ - MIT-LICENSE
37
+ - examples/googlesearch
38
+ - examples/metaWeblog
39
+ - examples/googlesearch/autoloading
40
+ - examples/googlesearch/delegated
41
+ - examples/googlesearch/direct
42
+ - examples/googlesearch/README
43
+ - examples/googlesearch/autoloading/google_search_api.rb
44
+ - examples/googlesearch/autoloading/google_search_controller.rb
45
+ - examples/googlesearch/delegated/google_search_service.rb
46
+ - examples/googlesearch/delegated/search_controller.rb
47
+ - examples/googlesearch/direct/google_search_api.rb
48
+ - examples/googlesearch/direct/search_controller.rb
49
+ - examples/metaWeblog/apis
50
+ - examples/metaWeblog/controllers
51
+ - examples/metaWeblog/README
52
+ - examples/metaWeblog/apis/blogger_api.rb
53
+ - examples/metaWeblog/apis/blogger_service.rb
54
+ - examples/metaWeblog/apis/meta_weblog_api.rb
55
+ - examples/metaWeblog/apis/meta_weblog_service.rb
56
+ - examples/metaWeblog/controllers/xmlrpc_controller.rb
57
+ - lib/action_web_service
58
+ - lib/action_web_service.rb
59
+ - lib/action_web_service/api.rb
60
+ - lib/action_web_service/base.rb
61
+ - lib/action_web_service/casting.rb
62
+ - lib/action_web_service/client
63
+ - lib/action_web_service/client.rb
64
+ - lib/action_web_service/container
65
+ - lib/action_web_service/container.rb
66
+ - lib/action_web_service/dispatcher
67
+ - lib/action_web_service/dispatcher.rb
68
+ - lib/action_web_service/invocation.rb
69
+ - lib/action_web_service/protocol
70
+ - lib/action_web_service/protocol.rb
71
+ - lib/action_web_service/scaffolding.rb
72
+ - lib/action_web_service/struct.rb
73
+ - lib/action_web_service/support
74
+ - lib/action_web_service/templates
75
+ - lib/action_web_service/test_invoke.rb
76
+ - lib/action_web_service/version.rb
77
+ - lib/action_web_service/client/base.rb
78
+ - lib/action_web_service/client/soap_client.rb
79
+ - lib/action_web_service/client/xmlrpc_client.rb
80
+ - lib/action_web_service/container/action_controller_container.rb
81
+ - lib/action_web_service/container/delegated_container.rb
82
+ - lib/action_web_service/container/direct_container.rb
83
+ - lib/action_web_service/dispatcher/abstract.rb
84
+ - lib/action_web_service/dispatcher/action_controller_dispatcher.rb
85
+ - lib/action_web_service/protocol/abstract.rb
86
+ - lib/action_web_service/protocol/discovery.rb
87
+ - lib/action_web_service/protocol/soap_protocol
88
+ - lib/action_web_service/protocol/soap_protocol.rb
89
+ - lib/action_web_service/protocol/xmlrpc_protocol.rb
90
+ - lib/action_web_service/protocol/soap_protocol/marshaler.rb
91
+ - lib/action_web_service/support/class_inheritable_options.rb
92
+ - lib/action_web_service/support/signature_types.rb
93
+ - lib/action_web_service/templates/scaffolds
94
+ - lib/action_web_service/templates/scaffolds/layout.rhtml
95
+ - lib/action_web_service/templates/scaffolds/methods.rhtml
96
+ - lib/action_web_service/templates/scaffolds/parameters.rhtml
97
+ - lib/action_web_service/templates/scaffolds/result.rhtml
98
+ - test/abstract_client.rb
99
+ - test/abstract_dispatcher.rb
100
+ - test/abstract_unit.rb
101
+ - test/api_test.rb
102
+ - test/apis
103
+ - test/base_test.rb
104
+ - test/casting_test.rb
105
+ - test/client_soap_test.rb
106
+ - test/client_xmlrpc_test.rb
107
+ - test/container_test.rb
108
+ - test/dispatcher_action_controller_soap_test.rb
109
+ - test/dispatcher_action_controller_xmlrpc_test.rb
110
+ - test/fixtures
111
+ - test/gencov
112
+ - test/invocation_test.rb
113
+ - test/run
114
+ - test/scaffolded_controller_test.rb
115
+ - test/struct_test.rb
116
+ - test/test_invoke_test.rb
117
+ - test/apis/auto_load_api.rb
118
+ - test/apis/broken_auto_load_api.rb
119
+ - test/fixtures/db_definitions
120
+ - test/fixtures/users.yml
121
+ - test/fixtures/db_definitions/mysql.sql
119
122
  test_files: []
123
+
120
124
  rdoc_options: []
125
+
121
126
  extra_rdoc_files: []
127
+
122
128
  executables: []
129
+
123
130
  extensions: []
131
+
124
132
  requirements:
125
- - none
133
+ - none
126
134
  dependencies:
127
- - !ruby/object:Gem::Dependency
128
- name: actionpack
129
- version_requirement:
130
- version_requirements: !ruby/object:Gem::Version::Requirement
131
- requirements:
132
- -
133
- - "="
134
- - !ruby/object:Gem::Version
135
- version: 1.11.2
136
- version:
137
- - !ruby/object:Gem::Dependency
138
- name: activerecord
139
- version_requirement:
140
- version_requirements: !ruby/object:Gem::Version::Requirement
141
- requirements:
142
- -
143
- - "="
144
- - !ruby/object:Gem::Version
145
- version: 1.13.2
146
- version:
135
+ - !ruby/object:Gem::Dependency
136
+ name: actionpack
137
+ version_requirement:
138
+ version_requirements: !ruby/object:Gem::Version::Requirement
139
+ requirements:
140
+ - - "="
141
+ - !ruby/object:Gem::Version
142
+ version: 1.12.0
143
+ version:
144
+ - !ruby/object:Gem::Dependency
145
+ name: activerecord
146
+ version_requirement:
147
+ version_requirements: !ruby/object:Gem::Version::Requirement
148
+ requirements:
149
+ - - "="
150
+ - !ruby/object:Gem::Version
151
+ version: 1.14.0
152
+ version: