backlog 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -0
- data/Rakefile +2 -1
- data/app/controllers/application.rb +55 -8
- data/app/controllers/groups_controller.rb +62 -0
- data/app/controllers/periods_controller.rb +13 -55
- data/app/controllers/tasks_controller.rb +9 -5
- data/app/controllers/works_controller.rb +43 -6
- data/app/helpers/application_helper.rb +20 -2
- data/app/helpers/groups_helper.rb +2 -0
- data/app/models/backlog.rb +19 -10
- data/app/models/estimate.rb +2 -1
- data/app/models/group.rb +11 -0
- data/app/models/party.rb +3 -0
- data/app/models/period.rb +43 -6
- data/app/models/task.rb +27 -14
- data/app/models/user.rb +37 -8
- data/app/models/work.rb +4 -6
- data/app/views/backlogs/_name_list.rhtml +5 -0
- data/app/views/backlogs/show.rhtml +4 -4
- data/app/views/groups/_form.rhtml +7 -0
- data/app/views/groups/edit.rhtml +31 -0
- data/app/views/groups/list.rhtml +27 -0
- data/app/views/groups/new.rhtml +8 -0
- data/app/views/layouts/wide.rhtml +2 -2
- data/app/views/periods/_burn_down_chart.rhtml +1 -1
- data/app/views/periods/_form.rhtml +13 -9
- data/app/views/periods/_show_active.rhtml +6 -12
- data/app/views/periods/_title.rhtml +4 -5
- data/app/views/periods/edit.rhtml +1 -1
- data/app/views/periods/new.rhtml +1 -1
- data/app/views/periods/show.rhtml +10 -6
- data/app/views/tasks/_backlog_header.rhtml +22 -0
- data/app/views/tasks/_description_list.rhtml +5 -0
- data/app/views/tasks/_form.rhtml +26 -7
- data/app/views/tasks/_task.rhtml +4 -4
- data/app/views/tasks/edit.rhtml +2 -3
- data/app/views/tasks/list_started.rhtml +1 -0
- data/app/views/tasks/new.rhtml +2 -2
- data/app/views/works/_buttons.rhtml +3 -0
- data/app/views/works/_form.rhtml +15 -10
- data/app/views/works/daily_work_sheet.rhtml +30 -18
- data/app/views/works/edit.rhtml +4 -4
- data/app/views/works/list.rhtml +2 -2
- data/app/views/works/new.rhtml +3 -2
- data/app/views/works/weekly_work_sheet.rhtml +2 -2
- data/bin/backlog +2 -0
- data/bin/backlog_init.d_kubosch_production +27 -0
- data/bin/copy_production2development.rb +33 -0
- data/config/database.yml +13 -7
- data/config/deploy_kubosch.rb +1 -0
- data/config/environment.rb +2 -0
- data/config/environments/development_mysql.rb +27 -0
- data/config/environments/kubosch_production_mysql.rb +21 -0
- data/config/routes.rb +1 -1
- data/db/migrate/{001_tasks.rb → 001_create_tasks.rb} +1 -1
- data/db/migrate/{002_backlogs.rb → 002_create_backlogs.rb} +2 -2
- data/db/migrate/003_add_estimation_points.rb +1 -1
- data/db/migrate/004_add_period.rb +2 -2
- data/db/migrate/013_create_estimates.rb +1 -1
- data/db/migrate/015_add_user_option.rb +9 -5
- data/db/migrate/017_insert_datek_projects.rb +13 -10
- data/db/migrate/018_create_groups.rb +115 -0
- data/db/schema.rb +72 -12
- data/lang/en.yaml +7 -0
- data/lang/no.yaml +7 -0
- data/lib/big_decimal_yaml_fix.rb +27 -0
- data/lib/class_table_inheritance.rb +163 -0
- data/lib/tasks/backup.rake +92 -0
- data/public/images/person.org.png +0 -0
- data/public/images/person.png +0 -0
- data/public/stylesheets/backlog.css +3 -1
- data/public/stylesheets/mwrt002.css +1 -1
- data/test/fixtures/groups.yml +6 -0
- data/test/fixtures/parties.yml +31 -0
- data/test/fixtures/periods.yml +2 -2
- data/test/fixtures/tasks.yml +2 -0
- data/test/fixtures/users.yml +6 -6
- data/test/functional/backlogs_controller_test.rb +1 -1
- data/test/functional/groups_controller_test.rb +120 -0
- data/test/functional/periods_controller_test.rb +1 -1
- data/test/functional/tasks_controller_test.rb +16 -1
- data/test/functional/user_controller_test.rb +8 -2
- data/test/test_helper.rb +5 -0
- data/test/unit/big_decimal_yaml_fix_test.rb +14 -0
- data/test/unit/estimate_test.rb +1 -1
- data/test/unit/group_test.rb +10 -0
- data/test/unit/user_test.rb +56 -44
- data/tmp/sessions/ruby_sess.22dec3e9df47fb4e +0 -0
- data/tmp/sessions/ruby_sess.8037e0ab58cbcf1a +0 -0
- data/vendor/plugins/activerecord_foreign_key_extensions/lib/active_record_extensions.rb +35 -0
- data/vendor/rails/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.rhtml.bak +1 -0
- data/vendor/rails/{actionwebservice/lib/action_web_service/templates/scaffolds/layout.rhtml → railties/configs/empty.log} +0 -0
- metadata +36 -105
- data/backlog.gemspec +0 -21
- data/vendor/rails/actionwebservice/CHANGELOG +0 -265
- data/vendor/rails/actionwebservice/MIT-LICENSE +0 -21
- data/vendor/rails/actionwebservice/README +0 -364
- data/vendor/rails/actionwebservice/Rakefile +0 -171
- data/vendor/rails/actionwebservice/TODO +0 -32
- data/vendor/rails/actionwebservice/examples/googlesearch/README +0 -143
- data/vendor/rails/actionwebservice/examples/googlesearch/autoloading/google_search_api.rb +0 -50
- data/vendor/rails/actionwebservice/examples/googlesearch/autoloading/google_search_controller.rb +0 -57
- data/vendor/rails/actionwebservice/examples/googlesearch/delegated/google_search_service.rb +0 -108
- data/vendor/rails/actionwebservice/examples/googlesearch/delegated/search_controller.rb +0 -7
- data/vendor/rails/actionwebservice/examples/googlesearch/direct/google_search_api.rb +0 -50
- data/vendor/rails/actionwebservice/examples/googlesearch/direct/search_controller.rb +0 -58
- data/vendor/rails/actionwebservice/examples/metaWeblog/README +0 -17
- data/vendor/rails/actionwebservice/examples/metaWeblog/apis/blogger_api.rb +0 -60
- data/vendor/rails/actionwebservice/examples/metaWeblog/apis/blogger_service.rb +0 -34
- data/vendor/rails/actionwebservice/examples/metaWeblog/apis/meta_weblog_api.rb +0 -67
- data/vendor/rails/actionwebservice/examples/metaWeblog/apis/meta_weblog_service.rb +0 -48
- data/vendor/rails/actionwebservice/examples/metaWeblog/controllers/xmlrpc_controller.rb +0 -16
- data/vendor/rails/actionwebservice/install.rb +0 -30
- data/vendor/rails/actionwebservice/lib/action_web_service.rb +0 -66
- data/vendor/rails/actionwebservice/lib/action_web_service/api.rb +0 -301
- data/vendor/rails/actionwebservice/lib/action_web_service/base.rb +0 -42
- data/vendor/rails/actionwebservice/lib/action_web_service/casting.rb +0 -138
- data/vendor/rails/actionwebservice/lib/action_web_service/client.rb +0 -3
- data/vendor/rails/actionwebservice/lib/action_web_service/client/base.rb +0 -28
- data/vendor/rails/actionwebservice/lib/action_web_service/client/soap_client.rb +0 -113
- data/vendor/rails/actionwebservice/lib/action_web_service/client/xmlrpc_client.rb +0 -58
- data/vendor/rails/actionwebservice/lib/action_web_service/container.rb +0 -3
- data/vendor/rails/actionwebservice/lib/action_web_service/container/action_controller_container.rb +0 -93
- data/vendor/rails/actionwebservice/lib/action_web_service/container/delegated_container.rb +0 -86
- data/vendor/rails/actionwebservice/lib/action_web_service/container/direct_container.rb +0 -69
- data/vendor/rails/actionwebservice/lib/action_web_service/dispatcher.rb +0 -2
- data/vendor/rails/actionwebservice/lib/action_web_service/dispatcher/abstract.rb +0 -207
- data/vendor/rails/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +0 -379
- data/vendor/rails/actionwebservice/lib/action_web_service/invocation.rb +0 -202
- data/vendor/rails/actionwebservice/lib/action_web_service/protocol.rb +0 -4
- data/vendor/rails/actionwebservice/lib/action_web_service/protocol/abstract.rb +0 -112
- data/vendor/rails/actionwebservice/lib/action_web_service/protocol/discovery.rb +0 -37
- data/vendor/rails/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb +0 -176
- data/vendor/rails/actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb +0 -235
- data/vendor/rails/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb +0 -122
- data/vendor/rails/actionwebservice/lib/action_web_service/scaffolding.rb +0 -283
- data/vendor/rails/actionwebservice/lib/action_web_service/struct.rb +0 -68
- data/vendor/rails/actionwebservice/lib/action_web_service/support/class_inheritable_options.rb +0 -26
- data/vendor/rails/actionwebservice/lib/action_web_service/support/signature_types.rb +0 -226
- data/vendor/rails/actionwebservice/lib/action_web_service/templates/scaffolds/layout.erb +0 -65
- data/vendor/rails/actionwebservice/lib/action_web_service/templates/scaffolds/methods.erb +0 -6
- data/vendor/rails/actionwebservice/lib/action_web_service/templates/scaffolds/methods.rhtml +0 -0
- data/vendor/rails/actionwebservice/lib/action_web_service/templates/scaffolds/parameters.erb +0 -29
- data/vendor/rails/actionwebservice/lib/action_web_service/templates/scaffolds/parameters.rhtml +0 -0
- data/vendor/rails/actionwebservice/lib/action_web_service/templates/scaffolds/result.erb +0 -30
- data/vendor/rails/actionwebservice/lib/action_web_service/templates/scaffolds/result.rhtml +0 -0
- data/vendor/rails/actionwebservice/lib/action_web_service/test_invoke.rb +0 -110
- data/vendor/rails/actionwebservice/lib/action_web_service/version.rb +0 -9
- data/vendor/rails/actionwebservice/setup.rb +0 -1379
- data/vendor/rails/actionwebservice/test/abstract_client.rb +0 -183
- data/vendor/rails/actionwebservice/test/abstract_dispatcher.rb +0 -551
- data/vendor/rails/actionwebservice/test/abstract_unit.rb +0 -45
- data/vendor/rails/actionwebservice/test/api_test.rb +0 -102
- data/vendor/rails/actionwebservice/test/apis/auto_load_api.rb +0 -3
- data/vendor/rails/actionwebservice/test/apis/broken_auto_load_api.rb +0 -2
- data/vendor/rails/actionwebservice/test/base_test.rb +0 -42
- data/vendor/rails/actionwebservice/test/casting_test.rb +0 -86
- data/vendor/rails/actionwebservice/test/client_soap_test.rb +0 -153
- data/vendor/rails/actionwebservice/test/client_xmlrpc_test.rb +0 -152
- data/vendor/rails/actionwebservice/test/container_test.rb +0 -73
- data/vendor/rails/actionwebservice/test/dispatcher_action_controller_soap_test.rb +0 -137
- data/vendor/rails/actionwebservice/test/dispatcher_action_controller_xmlrpc_test.rb +0 -59
- data/vendor/rails/actionwebservice/test/fixtures/db_definitions/mysql.sql +0 -8
- data/vendor/rails/actionwebservice/test/fixtures/users.yml +0 -12
- data/vendor/rails/actionwebservice/test/gencov +0 -3
- data/vendor/rails/actionwebservice/test/invocation_test.rb +0 -185
- data/vendor/rails/actionwebservice/test/run +0 -6
- data/vendor/rails/actionwebservice/test/scaffolded_controller_test.rb +0 -146
- data/vendor/rails/actionwebservice/test/struct_test.rb +0 -52
- data/vendor/rails/actionwebservice/test/test_invoke_test.rb +0 -112
data/vendor/rails/actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb
DELETED
@@ -1,235 +0,0 @@
|
|
1
|
-
require 'soap/mapping'
|
2
|
-
|
3
|
-
module ActionWebService
|
4
|
-
module Protocol
|
5
|
-
module Soap
|
6
|
-
# Workaround for SOAP4R return values changing
|
7
|
-
class Registry < SOAP::Mapping::Registry
|
8
|
-
if SOAP::Version >= "1.5.4"
|
9
|
-
def find_mapped_soap_class(obj_class)
|
10
|
-
return @map.instance_eval { @obj2soap[obj_class][0] }
|
11
|
-
end
|
12
|
-
|
13
|
-
def find_mapped_obj_class(soap_class)
|
14
|
-
return @map.instance_eval { @soap2obj[soap_class][0] }
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class SoapMarshaler
|
20
|
-
attr :namespace
|
21
|
-
attr :registry
|
22
|
-
|
23
|
-
def initialize(namespace=nil)
|
24
|
-
@namespace = namespace || 'urn:ActionWebService'
|
25
|
-
@registry = Registry.new
|
26
|
-
@type2binding = {}
|
27
|
-
register_static_factories
|
28
|
-
end
|
29
|
-
|
30
|
-
def soap_to_ruby(obj)
|
31
|
-
SOAP::Mapping.soap2obj(obj, @registry)
|
32
|
-
end
|
33
|
-
|
34
|
-
def ruby_to_soap(obj)
|
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
|
38
|
-
end
|
39
|
-
|
40
|
-
def register_type(type)
|
41
|
-
return @type2binding[type] if @type2binding.has_key?(type)
|
42
|
-
|
43
|
-
if type.array?
|
44
|
-
array_mapping = @registry.find_mapped_soap_class(Array)
|
45
|
-
qname = XSD::QName.new(@namespace, soap_type_name(type.element_type.type_class.name) + 'Array')
|
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
|
66
|
-
end
|
67
|
-
|
68
|
-
@type2binding[type]
|
69
|
-
end
|
70
|
-
alias :lookup_type :register_type
|
71
|
-
|
72
|
-
def annotate_arrays(binding, value)
|
73
|
-
if value.nil?
|
74
|
-
return
|
75
|
-
elsif binding.type.array?
|
76
|
-
mark_typed_array(value, binding.element_binding.qname)
|
77
|
-
if binding.element_binding.type.custom?
|
78
|
-
value.each do |element|
|
79
|
-
annotate_arrays(binding.element_binding, element)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
elsif binding.type.structured?
|
83
|
-
binding.type.each_member do |name, type|
|
84
|
-
member_binding = register_type(type)
|
85
|
-
member_value = value.respond_to?('[]') ? value[name] : value.send(name)
|
86
|
-
annotate_arrays(member_binding, member_value) if type.custom?
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
def typed_struct_factory(type_class)
|
93
|
-
if Object.const_defined?('ActiveRecord')
|
94
|
-
if type_class.ancestors.include?(ActiveRecord::Base)
|
95
|
-
qname = XSD::QName.new(@namespace, soap_type_name(type_class.name))
|
96
|
-
type_class.instance_variable_set('@qname', qname)
|
97
|
-
return SoapActiveRecordStructFactory.new
|
98
|
-
end
|
99
|
-
end
|
100
|
-
SOAP::Mapping::Registry::TypedStructFactory
|
101
|
-
end
|
102
|
-
|
103
|
-
def mark_typed_array(array, qname)
|
104
|
-
(class << array; self; end).class_eval do
|
105
|
-
define_method(:arytype) do
|
106
|
-
qname
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def soap_base_type_name(type)
|
112
|
-
xsd_type = type.ancestors.find{ |c| c.const_defined? 'Type' }
|
113
|
-
xsd_type ? xsd_type.const_get('Type') : XSD::XSDAnySimpleType::Type
|
114
|
-
end
|
115
|
-
|
116
|
-
def soap_type_name(type_name)
|
117
|
-
type_name.gsub(/::/, '..')
|
118
|
-
end
|
119
|
-
|
120
|
-
def register_static_factories
|
121
|
-
@registry.add(ActionWebService::Base64, SOAP::SOAPBase64, SoapBase64Factory.new, nil)
|
122
|
-
mapping = @registry.find_mapped_soap_class(ActionWebService::Base64)
|
123
|
-
@type2binding[ActionWebService::Base64] =
|
124
|
-
SoapBinding.new(self, SOAP::SOAPBase64::Type, ActionWebService::Base64, mapping)
|
125
|
-
@registry.add(Array, SOAP::SOAPArray, SoapTypedArrayFactory.new, nil)
|
126
|
-
@registry.add(::BigDecimal, SOAP::SOAPDouble, SOAP::Mapping::Registry::BasetypeFactory, {:derived_class => true})
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
class SoapBinding
|
131
|
-
attr :qname
|
132
|
-
attr :type
|
133
|
-
attr :mapping
|
134
|
-
attr :element_binding
|
135
|
-
|
136
|
-
def initialize(marshaler, qname, type, mapping, element_binding=nil)
|
137
|
-
@marshaler = marshaler
|
138
|
-
@qname = qname
|
139
|
-
@type = type
|
140
|
-
@mapping = mapping
|
141
|
-
@element_binding = element_binding
|
142
|
-
end
|
143
|
-
|
144
|
-
def type_name
|
145
|
-
@type.custom? ? @qname.name : nil
|
146
|
-
end
|
147
|
-
|
148
|
-
def qualified_type_name(ns=nil)
|
149
|
-
if @type.custom?
|
150
|
-
"#{ns ? ns : @qname.namespace}:#{@qname.name}"
|
151
|
-
else
|
152
|
-
ns = XSD::NS.new
|
153
|
-
ns.assign(XSD::Namespace, SOAP::XSDNamespaceTag)
|
154
|
-
ns.assign(SOAP::EncodingNamespace, "soapenc")
|
155
|
-
xsd_klass = mapping[0].ancestors.find{|c| c.const_defined?('Type')}
|
156
|
-
return ns.name(XSD::AnyTypeName) unless xsd_klass
|
157
|
-
ns.name(xsd_klass.const_get('Type'))
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
def eql?(other)
|
162
|
-
@qname == other.qname
|
163
|
-
end
|
164
|
-
alias :== :eql?
|
165
|
-
|
166
|
-
def hash
|
167
|
-
@qname.hash
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
class SoapActiveRecordStructFactory < SOAP::Mapping::Factory
|
172
|
-
def obj2soap(soap_class, obj, info, map)
|
173
|
-
unless obj.is_a?(ActiveRecord::Base)
|
174
|
-
return nil
|
175
|
-
end
|
176
|
-
soap_obj = soap_class.new(obj.class.instance_variable_get('@qname'))
|
177
|
-
obj.class.columns.each do |column|
|
178
|
-
key = column.name.to_s
|
179
|
-
value = obj.send(key)
|
180
|
-
soap_obj[key] = SOAP::Mapping._obj2soap(value, map)
|
181
|
-
end
|
182
|
-
soap_obj
|
183
|
-
end
|
184
|
-
|
185
|
-
def soap2obj(obj_class, node, info, map)
|
186
|
-
unless node.type == obj_class.instance_variable_get('@qname')
|
187
|
-
return false
|
188
|
-
end
|
189
|
-
obj = obj_class.new
|
190
|
-
node.each do |key, value|
|
191
|
-
obj[key] = value.data
|
192
|
-
end
|
193
|
-
obj.instance_variable_set('@new_record', false)
|
194
|
-
return true, obj
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
class SoapTypedArrayFactory < SOAP::Mapping::Factory
|
199
|
-
def obj2soap(soap_class, obj, info, map)
|
200
|
-
unless obj.respond_to?(:arytype)
|
201
|
-
return nil
|
202
|
-
end
|
203
|
-
soap_obj = soap_class.new(SOAP::ValueArrayName, 1, obj.arytype)
|
204
|
-
mark_marshalled_obj(obj, soap_obj)
|
205
|
-
obj.each do |item|
|
206
|
-
child = SOAP::Mapping._obj2soap(item, map)
|
207
|
-
soap_obj.add(child)
|
208
|
-
end
|
209
|
-
soap_obj
|
210
|
-
end
|
211
|
-
|
212
|
-
def soap2obj(obj_class, node, info, map)
|
213
|
-
return false
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
class SoapBase64Factory < SOAP::Mapping::Factory
|
218
|
-
def obj2soap(soap_class, obj, info, map)
|
219
|
-
unless obj.is_a?(ActionWebService::Base64)
|
220
|
-
return nil
|
221
|
-
end
|
222
|
-
return soap_class.new(obj)
|
223
|
-
end
|
224
|
-
|
225
|
-
def soap2obj(obj_class, node, info, map)
|
226
|
-
unless node.type == SOAP::SOAPBase64::Type
|
227
|
-
return false
|
228
|
-
end
|
229
|
-
return true, obj_class.new(node.string)
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
@@ -1,122 +0,0 @@
|
|
1
|
-
require 'xmlrpc/marshal'
|
2
|
-
require 'action_web_service/client/xmlrpc_client'
|
3
|
-
|
4
|
-
module XMLRPC # :nodoc:
|
5
|
-
class FaultException # :nodoc:
|
6
|
-
alias :message :faultString
|
7
|
-
end
|
8
|
-
|
9
|
-
class Create
|
10
|
-
def wrong_type(value)
|
11
|
-
if BigDecimal === value
|
12
|
-
[true, value.to_f]
|
13
|
-
else
|
14
|
-
false
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
module ActionWebService # :nodoc:
|
21
|
-
module API # :nodoc:
|
22
|
-
class Base # :nodoc:
|
23
|
-
def self.xmlrpc_client(endpoint_uri, options={})
|
24
|
-
ActionWebService::Client::XmlRpc.new self, endpoint_uri, options
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
module Protocol # :nodoc:
|
30
|
-
module XmlRpc # :nodoc:
|
31
|
-
def self.included(base)
|
32
|
-
base.register_protocol(XmlRpcProtocol)
|
33
|
-
end
|
34
|
-
|
35
|
-
class XmlRpcProtocol < AbstractProtocol # :nodoc:
|
36
|
-
def self.create(controller)
|
37
|
-
XmlRpcProtocol.new
|
38
|
-
end
|
39
|
-
|
40
|
-
def decode_action_pack_request(action_pack_request)
|
41
|
-
service_name = action_pack_request.parameters['action']
|
42
|
-
decode_request(action_pack_request.raw_post, service_name)
|
43
|
-
end
|
44
|
-
|
45
|
-
def decode_request(raw_request, service_name)
|
46
|
-
method_name, params = XMLRPC::Marshal.load_call(raw_request)
|
47
|
-
Request.new(self, method_name, params, service_name)
|
48
|
-
rescue
|
49
|
-
return nil
|
50
|
-
end
|
51
|
-
|
52
|
-
def encode_request(method_name, params, param_types)
|
53
|
-
if param_types
|
54
|
-
params = params.dup
|
55
|
-
param_types.each_with_index{ |type, i| params[i] = value_to_xmlrpc_wire_format(params[i], type) }
|
56
|
-
end
|
57
|
-
XMLRPC::Marshal.dump_call(method_name, *params)
|
58
|
-
end
|
59
|
-
|
60
|
-
def decode_response(raw_response)
|
61
|
-
[nil, XMLRPC::Marshal.load_response(raw_response)]
|
62
|
-
end
|
63
|
-
|
64
|
-
def encode_response(method_name, return_value, return_type, protocol_options={})
|
65
|
-
if return_value && return_type
|
66
|
-
return_value = value_to_xmlrpc_wire_format(return_value, return_type)
|
67
|
-
end
|
68
|
-
return_value = false if return_value.nil?
|
69
|
-
raw_response = XMLRPC::Marshal.dump_response(return_value)
|
70
|
-
Response.new(raw_response, 'text/xml', return_value)
|
71
|
-
end
|
72
|
-
|
73
|
-
def encode_multicall_response(responses, protocol_options={})
|
74
|
-
result = responses.map do |return_value, return_type|
|
75
|
-
if return_value && return_type
|
76
|
-
return_value = value_to_xmlrpc_wire_format(return_value, return_type)
|
77
|
-
return_value = [return_value] unless return_value.nil?
|
78
|
-
end
|
79
|
-
return_value = false if return_value.nil?
|
80
|
-
return_value
|
81
|
-
end
|
82
|
-
raw_response = XMLRPC::Marshal.dump_response(result)
|
83
|
-
Response.new(raw_response, 'text/xml', result)
|
84
|
-
end
|
85
|
-
|
86
|
-
def protocol_client(api, protocol_name, endpoint_uri, options={})
|
87
|
-
return nil unless protocol_name == :xmlrpc
|
88
|
-
ActionWebService::Client::XmlRpc.new(api, endpoint_uri, options)
|
89
|
-
end
|
90
|
-
|
91
|
-
def value_to_xmlrpc_wire_format(value, value_type)
|
92
|
-
if value_type.array?
|
93
|
-
value.map{ |val| value_to_xmlrpc_wire_format(val, value_type.element_type) }
|
94
|
-
else
|
95
|
-
if value.is_a?(ActionWebService::Struct)
|
96
|
-
struct = {}
|
97
|
-
value.class.members.each do |name, type|
|
98
|
-
member_value = value[name]
|
99
|
-
next if member_value.nil?
|
100
|
-
struct[name.to_s] = value_to_xmlrpc_wire_format(member_value, type)
|
101
|
-
end
|
102
|
-
struct
|
103
|
-
elsif value.is_a?(ActiveRecord::Base)
|
104
|
-
struct = {}
|
105
|
-
value.attributes.each do |key, member_value|
|
106
|
-
next if member_value.nil?
|
107
|
-
struct[key.to_s] = member_value
|
108
|
-
end
|
109
|
-
struct
|
110
|
-
elsif value.is_a?(ActionWebService::Base64)
|
111
|
-
XMLRPC::Base64.new(value)
|
112
|
-
elsif value.is_a?(Exception) && !value.is_a?(XMLRPC::FaultException)
|
113
|
-
XMLRPC::FaultException.new(2, value.message)
|
114
|
-
else
|
115
|
-
value
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
@@ -1,283 +0,0 @@
|
|
1
|
-
require 'benchmark'
|
2
|
-
require 'pathname'
|
3
|
-
|
4
|
-
module ActionWebService
|
5
|
-
module Scaffolding # :nodoc:
|
6
|
-
class ScaffoldingError < ActionWebServiceError # :nodoc:
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.included(base)
|
10
|
-
base.extend(ClassMethods)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Web service invocation scaffolding provides a way to quickly invoke web service methods in a controller. The
|
14
|
-
# generated scaffold actions have default views to let you enter the method parameters and view the
|
15
|
-
# results.
|
16
|
-
#
|
17
|
-
# Example:
|
18
|
-
#
|
19
|
-
# class ApiController < ActionController
|
20
|
-
# web_service_scaffold :invoke
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# This example generates an +invoke+ action in the +ApiController+ that you can navigate to from
|
24
|
-
# your browser, select the API method, enter its parameters, and perform the invocation.
|
25
|
-
#
|
26
|
-
# If you want to customize the default views, create the following views in "app/views":
|
27
|
-
#
|
28
|
-
# * <tt>action_name/methods.erb</tt>
|
29
|
-
# * <tt>action_name/parameters.erb</tt>
|
30
|
-
# * <tt>action_name/result.erb</tt>
|
31
|
-
# * <tt>action_name/layout.erb</tt>
|
32
|
-
#
|
33
|
-
# Where <tt>action_name</tt> is the name of the action you gave to ClassMethods#web_service_scaffold.
|
34
|
-
#
|
35
|
-
# You can use the default views in <tt>RAILS_DIR/lib/action_web_service/templates/scaffolds</tt> as
|
36
|
-
# a guide.
|
37
|
-
module ClassMethods
|
38
|
-
# Generates web service invocation scaffolding for the current controller. The given action name
|
39
|
-
# can then be used as the entry point for invoking API methods from a web browser.
|
40
|
-
def web_service_scaffold(action_name)
|
41
|
-
add_template_helper(Helpers)
|
42
|
-
module_eval <<-"end_eval", __FILE__, __LINE__ + 1
|
43
|
-
def #{action_name}
|
44
|
-
if request.method == :get
|
45
|
-
setup_invocation_assigns
|
46
|
-
render_invocation_scaffold 'methods'
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def #{action_name}_method_params
|
51
|
-
if request.method == :get
|
52
|
-
setup_invocation_assigns
|
53
|
-
render_invocation_scaffold 'parameters'
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def #{action_name}_submit
|
58
|
-
if request.method == :post
|
59
|
-
setup_invocation_assigns
|
60
|
-
protocol_name = params['protocol'] ? params['protocol'].to_sym : :soap
|
61
|
-
case protocol_name
|
62
|
-
when :soap
|
63
|
-
@protocol = Protocol::Soap::SoapProtocol.create(self)
|
64
|
-
when :xmlrpc
|
65
|
-
@protocol = Protocol::XmlRpc::XmlRpcProtocol.create(self)
|
66
|
-
end
|
67
|
-
bm = Benchmark.measure do
|
68
|
-
@protocol.register_api(@scaffold_service.api)
|
69
|
-
post_params = params['method_params'] ? params['method_params'].dup : nil
|
70
|
-
params = []
|
71
|
-
@scaffold_method.expects.each_with_index do |spec, i|
|
72
|
-
params << post_params[i.to_s]
|
73
|
-
end if @scaffold_method.expects
|
74
|
-
params = @scaffold_method.cast_expects(params)
|
75
|
-
method_name = public_method_name(@scaffold_service.name, @scaffold_method.public_name)
|
76
|
-
@method_request_xml = @protocol.encode_request(method_name, params, @scaffold_method.expects)
|
77
|
-
new_request = @protocol.encode_action_pack_request(@scaffold_service.name, @scaffold_method.public_name, @method_request_xml)
|
78
|
-
prepare_request(new_request, @scaffold_service.name, @scaffold_method.public_name)
|
79
|
-
self.request = new_request
|
80
|
-
if @scaffold_container.dispatching_mode != :direct
|
81
|
-
request.parameters['action'] = @scaffold_service.name
|
82
|
-
end
|
83
|
-
dispatch_web_service_request
|
84
|
-
@method_response_xml = response.body
|
85
|
-
method_name, obj = @protocol.decode_response(@method_response_xml)
|
86
|
-
return if handle_invocation_exception(obj)
|
87
|
-
@method_return_value = @scaffold_method.cast_returns(obj)
|
88
|
-
end
|
89
|
-
@method_elapsed = bm.real
|
90
|
-
add_instance_variables_to_assigns
|
91
|
-
reset_invocation_response
|
92
|
-
render_invocation_scaffold 'result'
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
private
|
97
|
-
def setup_invocation_assigns
|
98
|
-
@scaffold_class = self.class
|
99
|
-
@scaffold_action_name = "#{action_name}"
|
100
|
-
@scaffold_container = WebServiceModel::Container.new(self)
|
101
|
-
if params['service'] && params['method']
|
102
|
-
@scaffold_service = @scaffold_container.services.find{ |x| x.name == params['service'] }
|
103
|
-
@scaffold_method = @scaffold_service.api_methods[params['method']]
|
104
|
-
end
|
105
|
-
add_instance_variables_to_assigns
|
106
|
-
end
|
107
|
-
|
108
|
-
def render_invocation_scaffold(action)
|
109
|
-
customized_template = "\#{self.class.controller_path}/#{action_name}/\#{action}"
|
110
|
-
default_template = scaffold_path(action)
|
111
|
-
if template_exists?(customized_template)
|
112
|
-
content = @template.render_file(customized_template)
|
113
|
-
else
|
114
|
-
content = @template.render_file(default_template, false)
|
115
|
-
end
|
116
|
-
@template.instance_variable_set("@content_for_layout", content)
|
117
|
-
if self.active_layout.nil?
|
118
|
-
render_file(scaffold_path("layout"))
|
119
|
-
else
|
120
|
-
render_file(self.active_layout, "200 OK", true)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def scaffold_path(template_name)
|
125
|
-
File.dirname(__FILE__) + "/templates/scaffolds/" + template_name + ".erb"
|
126
|
-
end
|
127
|
-
|
128
|
-
def reset_invocation_response
|
129
|
-
erase_render_results
|
130
|
-
response.headers = ::ActionController::AbstractResponse::DEFAULT_HEADERS.merge("cookie" => [])
|
131
|
-
end
|
132
|
-
|
133
|
-
def public_method_name(service_name, method_name)
|
134
|
-
if web_service_dispatching_mode == :layered && @protocol.is_a?(ActionWebService::Protocol::XmlRpc::XmlRpcProtocol)
|
135
|
-
service_name + '.' + method_name
|
136
|
-
else
|
137
|
-
method_name
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def prepare_request(new_request, service_name, method_name)
|
142
|
-
new_request.parameters.update(request.parameters)
|
143
|
-
request.env.each{ |k, v| new_request.env[k] = v unless new_request.env.has_key?(k) }
|
144
|
-
if web_service_dispatching_mode == :layered && @protocol.is_a?(ActionWebService::Protocol::Soap::SoapProtocol)
|
145
|
-
new_request.env['HTTP_SOAPACTION'] = "/\#{controller_name()}/\#{service_name}/\#{method_name}"
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def handle_invocation_exception(obj)
|
150
|
-
exception = nil
|
151
|
-
if obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && obj.detail.cause.is_a?(Exception)
|
152
|
-
exception = obj.detail.cause
|
153
|
-
elsif obj.is_a?(XMLRPC::FaultException)
|
154
|
-
exception = obj
|
155
|
-
end
|
156
|
-
return unless exception
|
157
|
-
reset_invocation_response
|
158
|
-
rescue_action(exception)
|
159
|
-
true
|
160
|
-
end
|
161
|
-
end_eval
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
module Helpers # :nodoc:
|
166
|
-
def method_parameter_input_fields(method, type, field_name_base, idx, was_structured=false)
|
167
|
-
if type.array?
|
168
|
-
return content_tag('em', "Typed array input fields not supported yet (#{type.name})")
|
169
|
-
end
|
170
|
-
if type.structured?
|
171
|
-
return content_tag('em', "Nested structural types not supported yet (#{type.name})") if was_structured
|
172
|
-
parameters = ""
|
173
|
-
type.each_member do |member_name, member_type|
|
174
|
-
label = method_parameter_label(member_name, member_type)
|
175
|
-
nested_content = method_parameter_input_fields(
|
176
|
-
method,
|
177
|
-
member_type,
|
178
|
-
"#{field_name_base}[#{idx}][#{member_name}]",
|
179
|
-
idx,
|
180
|
-
true)
|
181
|
-
if member_type.custom?
|
182
|
-
parameters << content_tag('li', label)
|
183
|
-
parameters << content_tag('ul', nested_content)
|
184
|
-
else
|
185
|
-
parameters << content_tag('li', label + ' ' + nested_content)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
content_tag('ul', parameters)
|
189
|
-
else
|
190
|
-
# If the data source was structured previously we already have the index set
|
191
|
-
field_name_base = "#{field_name_base}[#{idx}]" unless was_structured
|
192
|
-
|
193
|
-
case type.type
|
194
|
-
when :int
|
195
|
-
text_field_tag "#{field_name_base}"
|
196
|
-
when :string
|
197
|
-
text_field_tag "#{field_name_base}"
|
198
|
-
when :base64
|
199
|
-
text_area_tag "#{field_name_base}", nil, :size => "40x5"
|
200
|
-
when :bool
|
201
|
-
radio_button_tag("#{field_name_base}", "true") + " True" +
|
202
|
-
radio_button_tag("#{field_name_base}", "false") + "False"
|
203
|
-
when :float
|
204
|
-
text_field_tag "#{field_name_base}"
|
205
|
-
when :time, :datetime
|
206
|
-
time = Time.now
|
207
|
-
i = 0
|
208
|
-
%w|year month day hour minute second|.map do |name|
|
209
|
-
i += 1
|
210
|
-
send("select_#{name}", time, :prefix => "#{field_name_base}[#{i}]", :discard_type => true)
|
211
|
-
end.join
|
212
|
-
when :date
|
213
|
-
date = Date.today
|
214
|
-
i = 0
|
215
|
-
%w|year month day|.map do |name|
|
216
|
-
i += 1
|
217
|
-
send("select_#{name}", date, :prefix => "#{field_name_base}[#{i}]", :discard_type => true)
|
218
|
-
end.join
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
def method_parameter_label(name, type)
|
224
|
-
name.to_s.capitalize + ' (' + type.human_name(false) + ')'
|
225
|
-
end
|
226
|
-
|
227
|
-
def service_method_list(service)
|
228
|
-
action = @scaffold_action_name + '_method_params'
|
229
|
-
methods = service.api_methods_full.map do |desc, name|
|
230
|
-
content_tag("li", link_to(desc, :action => action, :service => service.name, :method => name))
|
231
|
-
end
|
232
|
-
content_tag("ul", methods.join("\n"))
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
module WebServiceModel # :nodoc:
|
237
|
-
class Container # :nodoc:
|
238
|
-
attr :services
|
239
|
-
attr :dispatching_mode
|
240
|
-
|
241
|
-
def initialize(real_container)
|
242
|
-
@real_container = real_container
|
243
|
-
@dispatching_mode = @real_container.class.web_service_dispatching_mode
|
244
|
-
@services = []
|
245
|
-
if @dispatching_mode == :direct
|
246
|
-
@services << Service.new(@real_container.controller_name, @real_container)
|
247
|
-
else
|
248
|
-
@real_container.class.web_services.each do |name, obj|
|
249
|
-
@services << Service.new(name, @real_container.instance_eval{ web_service_object(name) })
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
class Service # :nodoc:
|
256
|
-
attr :name
|
257
|
-
attr :object
|
258
|
-
attr :api
|
259
|
-
attr :api_methods
|
260
|
-
attr :api_methods_full
|
261
|
-
|
262
|
-
def initialize(name, real_service)
|
263
|
-
@name = name.to_s
|
264
|
-
@object = real_service
|
265
|
-
@api = @object.class.web_service_api
|
266
|
-
if @api.nil?
|
267
|
-
raise ScaffoldingError, "No web service API attached to #{object.class}"
|
268
|
-
end
|
269
|
-
@api_methods = {}
|
270
|
-
@api_methods_full = []
|
271
|
-
@api.api_methods.each do |name, method|
|
272
|
-
@api_methods[method.public_name.to_s] = method
|
273
|
-
@api_methods_full << [method.to_s, method.public_name.to_s]
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
def to_s
|
278
|
-
self.name.camelize
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|
283
|
-
end
|