rubyamf-ouvrages 2.0.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/.gitignore +6 -0
- data/Gemfile +22 -0
- data/README.rdoc +105 -0
- data/Rakefile +21 -0
- data/lib/rubyamf.rb +64 -0
- data/lib/rubyamf/class_mapping.rb +239 -0
- data/lib/rubyamf/configuration.rb +272 -0
- data/lib/rubyamf/envelope.rb +102 -0
- data/lib/rubyamf/fault.rb +31 -0
- data/lib/rubyamf/gateway.png +0 -0
- data/lib/rubyamf/intermediate_object.rb +18 -0
- data/lib/rubyamf/logger.rb +39 -0
- data/lib/rubyamf/model.rb +215 -0
- data/lib/rubyamf/rails/controller.rb +23 -0
- data/lib/rubyamf/rails/model.rb +151 -0
- data/lib/rubyamf/rails/rails2_bootstrap.rb +73 -0
- data/lib/rubyamf/rails/rails3_bootstrap.rb +53 -0
- data/lib/rubyamf/rails/request_processor.rb +90 -0
- data/lib/rubyamf/rails/routing.rb +97 -0
- data/lib/rubyamf/rails/time.rb +6 -0
- data/lib/rubyamf/request_parser.rb +99 -0
- data/lib/rubyamf/test.rb +61 -0
- data/lib/rubyamf/version.rb +3 -0
- data/rubyamf.gemspec +26 -0
- data/spec/class_mapping_spec.rb +147 -0
- data/spec/configuration_spec.rb +90 -0
- data/spec/envelope_spec.rb +106 -0
- data/spec/fixtures/remotingMessage.bin +0 -0
- data/spec/fixtures/requestWithNewCredentials.bin +0 -0
- data/spec/fixtures/requestWithOldCredentials.bin +0 -0
- data/spec/fixtures/rubyamf_config.rb +24 -0
- data/spec/model_spec.rb +281 -0
- data/spec/rails_integration_spec.rb +22 -0
- data/spec/rails_routing_spec.rb +75 -0
- data/spec/request_parser_spec.rb +52 -0
- data/spec/request_processor_spec.rb +119 -0
- data/spec/spec_helper.rb +58 -0
- metadata +103 -0
@@ -0,0 +1,272 @@
|
|
1
|
+
module RubyAMF
|
2
|
+
# RubyAMF configuration container. It can be accessed by calling
|
3
|
+
# <tt>RubyAMF.configuration</tt>, or modified in a block like so:
|
4
|
+
#
|
5
|
+
# RubyAMF.configure do |config|
|
6
|
+
# config.gateway_path = "/amf"
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# === Gateway configuration
|
10
|
+
#
|
11
|
+
# Gateway configuration includes the gateway path and details about parameter
|
12
|
+
# mapping.
|
13
|
+
#
|
14
|
+
# +gateway_path+::
|
15
|
+
# Default: <tt>"/rubyamf/gateway"</tt>. The URL that responds to AMF requests.
|
16
|
+
# The URL should start with a "/" and not end with a "/".
|
17
|
+
#
|
18
|
+
# +populate_params_hash+::
|
19
|
+
# Default: <tt>true</tt>. For Rails users, all amf parameters can be accessed
|
20
|
+
# in the controller by calling <tt>rubyamf_params</tt>. If enabled, the amf
|
21
|
+
# parameters are merged into the <tt>params</tt> hash as well.
|
22
|
+
#
|
23
|
+
# +show_html_gateway+::
|
24
|
+
# Default: <tt>true</tt>. If enabled, non-AMF requests to the gateway url
|
25
|
+
# will result in a simple HTML page being returned.
|
26
|
+
#
|
27
|
+
# +param_mappings+::
|
28
|
+
# A hash that stores parameter mappings. Should only be modified through
|
29
|
+
# calls to <tt>map_params</tt>
|
30
|
+
#
|
31
|
+
# === Serialization options
|
32
|
+
#
|
33
|
+
# RubyAMF provides a wide variety of customization options for serialization
|
34
|
+
# to simplify integration.
|
35
|
+
#
|
36
|
+
# +translate_case+::
|
37
|
+
# Default: <tt>false</tt>. If enabled, properties will be converted to
|
38
|
+
# underscore style on deserialization from actionscript and will be converted
|
39
|
+
# to camelcase on serialization. This allows you to use language appropriate
|
40
|
+
# case style and have RubyAMF automatically care of translation.
|
41
|
+
#
|
42
|
+
# +auto_class_mapping+::
|
43
|
+
# Default: <tt>false</tt>. If a class mapping for a given ruby or actionscript
|
44
|
+
# class has not been defined, automatically maps it during serialization or
|
45
|
+
# deserialization. Nested ruby or actionscript classes will be automatically
|
46
|
+
# mapped to the class name without the namespace. Example:
|
47
|
+
# <tt>com.rubyamf.User => User</tt> or <tt>RubyAMF::User => User</tt>.
|
48
|
+
#
|
49
|
+
# +use_array_collection+::
|
50
|
+
# Default: <tt>false</tt>. If enabled, all arrays will be serialized as
|
51
|
+
# <tt>ArrayCollection</tt> objects. You can override this on a per-array
|
52
|
+
# basis by setting <tt>is_array_collection</tt> on the array to <tt>true</tt>
|
53
|
+
# or <tt>false</tt>. (Implementation in RocketAMF)
|
54
|
+
#
|
55
|
+
# +hash_key_access+::
|
56
|
+
# Default: <tt>:string</tt>. If set to <tt>:symbol</tt>, all deserialized
|
57
|
+
# hashes have the keys as symbols. RocketAMF defaults to strings, so setting
|
58
|
+
# to <tt>:symbol</tt> will reduce performance and possibly open you up to
|
59
|
+
# memory usage attacks.
|
60
|
+
#
|
61
|
+
# +preload_models+::
|
62
|
+
# If you are using in-model mapping and don't have <tt>auto_class_mapping</tt>
|
63
|
+
# enabled, you may need to force classes to be loaded before mapping takes
|
64
|
+
# effect. Simply include all necessary classes as strings to have RubyAMF
|
65
|
+
# force them to be loaded on initialization.
|
66
|
+
# Example: <tt>config.preload_models = ["User", "Course"]</tt>
|
67
|
+
#
|
68
|
+
# +check_for_associations+::
|
69
|
+
# Default: <tt>true</tt>. If enabled, associations that have been pre-loaded,
|
70
|
+
# either through :include or simply by being accessed, will be automatically
|
71
|
+
# included during serialization without any additional configuration.
|
72
|
+
#
|
73
|
+
# +ignore_fields+::
|
74
|
+
# Default: <tt>['created_at', 'created_on', 'updated_at', 'updated_on']</tt>.
|
75
|
+
# A list of all properties that should not be deserialized by default. The
|
76
|
+
# class-level <tt>:ignore_fields</tt> config overrides this.
|
77
|
+
class Configuration
|
78
|
+
# Gateway options
|
79
|
+
attr_accessor :gateway_path, :populate_params_hash, :show_html_gateway
|
80
|
+
attr_reader :param_mappings
|
81
|
+
|
82
|
+
# Serialization options
|
83
|
+
attr_accessor :translate_case, :auto_class_mapping, :use_array_collection,
|
84
|
+
:hash_key_access, :preload_models, :check_for_associations,
|
85
|
+
:ignore_fields
|
86
|
+
|
87
|
+
def initialize
|
88
|
+
@gateway_path = "/rubyamf/gateway"
|
89
|
+
@param_mappings = {}
|
90
|
+
@populate_params_hash = true
|
91
|
+
@show_html_gateway = true
|
92
|
+
|
93
|
+
@translate_case = false
|
94
|
+
@auto_class_mapping = false
|
95
|
+
@use_array_collection = false
|
96
|
+
@hash_key_access = :string
|
97
|
+
@preload_models = []
|
98
|
+
@check_for_associations = true
|
99
|
+
@ignore_fields = ['created_at', 'created_on', 'updated_at', 'updated_on']
|
100
|
+
end
|
101
|
+
|
102
|
+
# Maps the given array of named parameters to the arguments for calls to the
|
103
|
+
# given controller and action. For Rails users, the prefered method of
|
104
|
+
# parameter mapping is through routing (see RubyAMF::Rails::Routing).
|
105
|
+
#
|
106
|
+
# Example:
|
107
|
+
#
|
108
|
+
# config.map_params "UserController", "login", [:session_token, :username, :password]
|
109
|
+
# # params hash => {
|
110
|
+
# # 0 => "asdf", 1 => "user", 2 => "pass",
|
111
|
+
# # :session_token => "asdf", :username => "user", :password => "pass"
|
112
|
+
# # }
|
113
|
+
def map_params controller, action, params
|
114
|
+
@param_mappings[controller.to_s+"#"+action.to_s] = params
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns the class mapper class being used
|
118
|
+
def class_mapper
|
119
|
+
if @class_mapper.nil?
|
120
|
+
@class_mapper = RubyAMF::ClassMapping
|
121
|
+
end
|
122
|
+
@class_mapper
|
123
|
+
end
|
124
|
+
|
125
|
+
# Set to the class of any conforming class mapper to use it instead of
|
126
|
+
# <tt>RubyAMF::ClassMapping</tt>. If you don't need any of the advanced
|
127
|
+
# features offered by the RubyAMF class mapper, you can gain some substantial
|
128
|
+
# performance improvements by settings this to
|
129
|
+
# <tt>RocketAMF::Ext::FastClassMapping</tt> or <tt>RocketAMF::ClassMapping</tt>
|
130
|
+
# for the slower pure-ruby version.
|
131
|
+
def class_mapper= klass
|
132
|
+
@class_mapper = klass
|
133
|
+
end
|
134
|
+
|
135
|
+
# Loads the legacy config file at the given path or tries to locate it by
|
136
|
+
# looking for a <tt>rubyamf_config.rb</tt> file in several possible locations.
|
137
|
+
# Automatically run by RubyAMF if you are using Rails 2, it should be run
|
138
|
+
# before any additional configuration if you are not using Rails 2, as it
|
139
|
+
# overrides all previous configuration.
|
140
|
+
def load_legacy path=nil
|
141
|
+
# Locate legacy config
|
142
|
+
unless path
|
143
|
+
possible = []
|
144
|
+
possible << File.join(RAILS_ROOT, 'config', 'rubyamf_config.rb') if defined?(RAILS_ROOT)
|
145
|
+
possible << File.join('config', 'rubyamf_config.rb')
|
146
|
+
possible << 'rubyamf_config.rb'
|
147
|
+
unless path = possible.find {|p| File.exists?(p)}
|
148
|
+
raise "rubyamf_config.rb not found"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Load legacy config
|
153
|
+
$" << "app/configuration" # prevent legacy code require from doing anything
|
154
|
+
LegacySandbox.module_eval(File.read(path))
|
155
|
+
$".pop
|
156
|
+
cm = LegacySandbox::RubyAMF::ClassMappings
|
157
|
+
pm = LegacySandbox::RubyAMF::ParameterMappings
|
158
|
+
|
159
|
+
# Raise exceptions for disabled settings
|
160
|
+
if cm.force_active_record_ids != nil; raise "CONFIG PARSE ERROR: force_active_record_ids is no longer supported. Use <tt>:except</tt> if you want to prevent the id from being serialized."; end
|
161
|
+
if cm.hash_key_access == :indifferent; raise "CONFIG PARSE ERROR: indifferent hash_key_access is not supported for performance reasons. Use either :string or :symbol, the default."; end
|
162
|
+
if cm.default_mapping_scope != nil; raise "CONFIG PARSE ERROR: default_mapping_scope is not supported globally. Please log a feature request if you need it, or use switch to the new config syntax which supports per-model defaults."; end
|
163
|
+
if cm.use_ruby_date_time == true; raise "CONFIG PARSE ERROR: use_ruby_date_time is not supported by RocketAMF. Please log a feature request if you need it."; end
|
164
|
+
if pm.scaffolding == true; raise "CONFIG PARSE ERROR: scaffolding is not supported. Please log a feature request if you need it."; end
|
165
|
+
|
166
|
+
# Populate ClassMappings configs from legacy config
|
167
|
+
@ignore_fields = cm.ignore_fields unless cm.ignore_fields.nil?
|
168
|
+
@translate_case = cm.translate_case if cm.translate_case == true
|
169
|
+
@hash_key_access = cm.hash_key_access unless cm.hash_key_access.nil?
|
170
|
+
@use_array_collection = cm.use_array_collection if cm.use_array_collection == true
|
171
|
+
@check_for_associations = cm.check_for_associations if cm.check_for_associations == false
|
172
|
+
mapset = class_mapper.mappings
|
173
|
+
(cm.mappings || []).each do |legacy_mapping|
|
174
|
+
mapping = {}
|
175
|
+
if legacy_mapping[:type] == 'active_resource'
|
176
|
+
raise "CONFIG PARSE ERROR: active_resource mapping type is not supported. Please log a feature request or stop using it."
|
177
|
+
end
|
178
|
+
|
179
|
+
# Extract unscoped settings
|
180
|
+
mapping[:as] = legacy_mapping[:actionscript]
|
181
|
+
mapping[:ruby] = legacy_mapping[:ruby]
|
182
|
+
mapping[:methods] = legacy_mapping[:methods] unless legacy_mapping[:methods].nil?
|
183
|
+
mapping[:ignore_fields] = legacy_mapping[:ignore_fields] unless legacy_mapping[:ignore_fields].nil?
|
184
|
+
|
185
|
+
# Process possibly scoped settings
|
186
|
+
attrs = legacy_mapping[:attributes]
|
187
|
+
assoc = legacy_mapping[:associations]
|
188
|
+
if attrs.is_a?(Hash) || assoc.is_a?(Hash)
|
189
|
+
# Extract scopes
|
190
|
+
scopes = []
|
191
|
+
scopes += attrs.keys if attrs.is_a?(Hash)
|
192
|
+
scopes += assoc.keys if assoc.is_a?(Hash)
|
193
|
+
|
194
|
+
# Build settings for scopes
|
195
|
+
scopes.each do |scope|
|
196
|
+
scoped = mapping.dup
|
197
|
+
scoped[:scope] = scope.to_sym
|
198
|
+
scoped[:only] = attrs.is_a?(Hash) ? attrs[scope] : attrs
|
199
|
+
scoped.delete(:only) if scoped[:only].nil?
|
200
|
+
scoped[:include] = assoc.is_a?(Hash) ? assoc[scope] : assoc
|
201
|
+
scoped.delete(:include) if scoped[:include].nil?
|
202
|
+
mapset.map scoped
|
203
|
+
end
|
204
|
+
else
|
205
|
+
# No scoping
|
206
|
+
mapping[:only] = attrs unless attrs.nil?
|
207
|
+
mapping[:include] = assoc unless assoc.nil?
|
208
|
+
mapset.map mapping
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Populate ParameterMapping configs from legacy config
|
213
|
+
@populate_params_hash = pm.always_add_to_params if pm.always_add_to_params == false
|
214
|
+
(pm.mappings || []).each do |m|
|
215
|
+
params = []
|
216
|
+
m[:params].each do |k, v|
|
217
|
+
unless v =~ /\[(\d+)\]/
|
218
|
+
raise "CONFIG PARSE ERROR: parameter mappings are no longer evalled - '#{v}' must match [DIGITS]. Please log a feature request if you need this."
|
219
|
+
end
|
220
|
+
params[$1.to_i] = k
|
221
|
+
end
|
222
|
+
self.map_params m[:controller], m[:action], params
|
223
|
+
end
|
224
|
+
|
225
|
+
# Reset sandbox
|
226
|
+
cm.reset
|
227
|
+
pm.reset
|
228
|
+
|
229
|
+
self
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
module LegacySandbox #:nodoc:
|
234
|
+
module RubyAMF #:nodoc:
|
235
|
+
module ClassMappings #:nodoc:
|
236
|
+
class << self
|
237
|
+
attr_accessor :ignore_fields, :translate_case, :force_active_record_ids, :hash_key_access,
|
238
|
+
:assume_types, :default_mapping_scope, :use_ruby_date_time, :use_array_collection,
|
239
|
+
:check_for_associations, :mappings
|
240
|
+
|
241
|
+
def register mapping
|
242
|
+
@mappings ||= []
|
243
|
+
@mappings << mapping
|
244
|
+
end
|
245
|
+
|
246
|
+
def reset
|
247
|
+
methods.each do |m|
|
248
|
+
send(m, nil) if m =~ /[\w_]+=/
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
module ParameterMappings #:nodoc:
|
255
|
+
class << self
|
256
|
+
attr_accessor :always_add_to_params, :scaffolding, :mappings
|
257
|
+
|
258
|
+
def register mapping
|
259
|
+
@mappings ||= []
|
260
|
+
@mappings << mapping
|
261
|
+
end
|
262
|
+
|
263
|
+
def reset
|
264
|
+
methods.each do |m|
|
265
|
+
send(m, nil) if m =~ /[\w_]+=/
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module RubyAMF
|
4
|
+
# Adds several important features to RocketAMF::Envelope. None of these features
|
5
|
+
# are dependent on Rails, and as such can be used by any Rack compliant framework.
|
6
|
+
# Features are credentials support, easy parameter mapping based on configured
|
7
|
+
# parameter mappings, mapping scope support for serialization, and error handling
|
8
|
+
# for method dispatch using <tt>each_method_call</tt>.
|
9
|
+
class Envelope < RocketAMF::Envelope
|
10
|
+
attr_accessor :mapping_scope
|
11
|
+
|
12
|
+
# Finds and returns credentials set on the request as a hash with keys
|
13
|
+
# <tt>username</tt> and <tt>password</tt>, with the type dependent on the
|
14
|
+
# <tt>hash_key_access</tt> setting. <tt>setHeader('Credentials')</tt>
|
15
|
+
# credentials are used first, followed by new-style <tt>DSRemoteCredentials</tt>.
|
16
|
+
# If no credentials are found, a hash is returned with a username and password
|
17
|
+
# of <tt>nil</tt>.
|
18
|
+
def credentials
|
19
|
+
ds_cred_key = RubyAMF.configuration.translate_case ? "ds_remote_credentials" : "DSRemoteCredentials"
|
20
|
+
if RubyAMF.configuration.hash_key_access == :symbol
|
21
|
+
userid_key = :userid
|
22
|
+
username_key = :username
|
23
|
+
password_key = :password
|
24
|
+
ds_cred_key = ds_cred_key.to_sym
|
25
|
+
else
|
26
|
+
userid_key = "userid"
|
27
|
+
username_key = "username"
|
28
|
+
password_key = "password"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Old style setHeader('Credentials', CREDENTIALS_HASH)
|
32
|
+
if @headers['Credentials']
|
33
|
+
h = @headers['Credentials']
|
34
|
+
return {username_key => h.data[userid_key], password_key => h.data[password_key]}
|
35
|
+
end
|
36
|
+
|
37
|
+
# New style DSRemoteCredentials
|
38
|
+
messages.each do |m|
|
39
|
+
if m.data.is_a?(RocketAMF::Values::RemotingMessage)
|
40
|
+
if m.data.headers && m.data.headers[ds_cred_key]
|
41
|
+
username,password = Base64.decode64(m.data.headers[ds_cred_key]).split(':')
|
42
|
+
return {username_key => username, password_key => password}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Failure case sends empty credentials, because rubyamf_plugin does it
|
48
|
+
{username_key => nil, password_key => nil}
|
49
|
+
end
|
50
|
+
|
51
|
+
# Given a controller, action, and the flash arguments array, returns a hash
|
52
|
+
# containing the arguments indexed by number as well as named key if a named
|
53
|
+
# mapping has been configured. Returned hash respects <tt>hash_key_access</tt>
|
54
|
+
# setting for named keys.
|
55
|
+
#
|
56
|
+
# Example:
|
57
|
+
#
|
58
|
+
# RubyAMF.configuration.map_params "c", "a", ["param1", "param2"]
|
59
|
+
# params = envelope.params_hash "c", "a", ["asdf", "fdsa"]
|
60
|
+
# params.should == {:param1 => "asdf", :param2 => "fdsa", 0 => "asdf", 1 => "fdsa"}
|
61
|
+
def params_hash controller, action, arguments
|
62
|
+
conf = RubyAMF.configuration
|
63
|
+
mapped = {}
|
64
|
+
mapping = conf.param_mappings[controller+"#"+action]
|
65
|
+
arguments.each_with_index do |arg, i|
|
66
|
+
mapped[i] = arg
|
67
|
+
if mapping && mapping[i]
|
68
|
+
mapping_key = conf.hash_key_access == :symbol ? mapping[i].to_sym : mapping[i].to_s
|
69
|
+
mapped[mapping_key] = arg
|
70
|
+
end
|
71
|
+
end
|
72
|
+
mapped
|
73
|
+
end
|
74
|
+
|
75
|
+
# Extends default RocketAMF implementation to log caught exceptions and
|
76
|
+
# translate them into a RocketAMF::Values::ErrorMessage for return to flash
|
77
|
+
# after removing the backtrace (for safety).
|
78
|
+
def dispatch_call p
|
79
|
+
begin
|
80
|
+
ret = p[:block].call(p[:method], p[:args])
|
81
|
+
raise ret if ret.is_a?(Exception) # If they return FaultObject like you could in rubyamf_plugin
|
82
|
+
ret
|
83
|
+
rescue Exception => e
|
84
|
+
# Log exception
|
85
|
+
RubyAMF.logger.log_error(e)
|
86
|
+
|
87
|
+
# Clear backtrace so that RocketAMF doesn't send back the full backtrace
|
88
|
+
e.set_backtrace([])
|
89
|
+
|
90
|
+
# Create ErrorMessage object using the source message as the base
|
91
|
+
RocketAMF::Values::ErrorMessage.new(p[:source], e)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def serialize class_mapper=nil #:nodoc:
|
96
|
+
# Create a ClassMapper and set the mapping scope to pass to super implementation.
|
97
|
+
cm = class_mapper || RubyAMF::ClassMapper.new
|
98
|
+
cm.mapping_scope = mapping_scope if cm.respond_to?(:mapping_scope=)
|
99
|
+
super cm
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module RubyAMF
|
2
|
+
class Fault < ::Exception #:nodoc:
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
# Convenience object carried over from rubyamf_plugin, it can be returned for
|
7
|
+
# AMF instead of raising an exception.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
#
|
11
|
+
# render :amf => FaultObject.new("No users to get")
|
12
|
+
class FaultObject
|
13
|
+
def self.new *args, &block
|
14
|
+
if args.length == 2
|
15
|
+
raise "payload for FaultObject is no longer available - if you need it you will need to create a custom class to contain your payload"
|
16
|
+
end
|
17
|
+
message = args.length > 0 ? args[0] : ''
|
18
|
+
|
19
|
+
begin
|
20
|
+
raise RubyAMF::Fault.new(message)
|
21
|
+
rescue Exception => e
|
22
|
+
# Fix backtrace
|
23
|
+
b = e.backtrace
|
24
|
+
b.shift
|
25
|
+
e.set_backtrace(b)
|
26
|
+
|
27
|
+
# Return new fault object
|
28
|
+
return e
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
Binary file
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module RubyAMF
|
2
|
+
# IntermediateObject packages an object with its requested serialization options.
|
3
|
+
# This allows the pre-configured serialization configuration to be overridden
|
4
|
+
# as needed. They are automatically created by <tt>to_amf</tt> and should not
|
5
|
+
# be generated manually.
|
6
|
+
class IntermediateObject
|
7
|
+
attr_accessor :object, :options
|
8
|
+
|
9
|
+
def initialize object, options
|
10
|
+
@object = object
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def rubyamf_hash
|
15
|
+
@object.rubyamf_hash @options
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module RubyAMF
|
4
|
+
class Logger #:nodoc:
|
5
|
+
# Log exceptions in rails-style, with cleaned backtrace if available
|
6
|
+
def log_error e
|
7
|
+
msg = "#{e.class} (#{e.message}):\n "
|
8
|
+
msg += clean_backtrace(e).join("\n ")
|
9
|
+
logger.fatal(msg)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Send every other method call to internally wrapped logger
|
13
|
+
def method_missing name, *args
|
14
|
+
logger.send(name, args)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
# Use rails logger if available or create standard ruby logger to STDERR
|
19
|
+
def logger
|
20
|
+
unless @logger
|
21
|
+
if defined?(Rails) && ::Rails.logger
|
22
|
+
@logger = ::Rails.logger
|
23
|
+
else
|
24
|
+
@logger = ::Logger.new(STDERR)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
@logger
|
28
|
+
end
|
29
|
+
|
30
|
+
# Use Rails backtrace cleaner if it exists to clean
|
31
|
+
def clean_backtrace e
|
32
|
+
if defined?(Rails) && ::Rails.respond_to?(:backtrace_cleaner)
|
33
|
+
::Rails.backtrace_cleaner.clean(e.backtrace)
|
34
|
+
else
|
35
|
+
e.backtrace
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|