Class: RocketAMF::ClassMapping
- Inherits:
-
Object
- Object
- RocketAMF::ClassMapping
- Defined in:
- lib/rocketamf/class_mapping.rb
Overview
Handles class name mapping between actionscript and ruby and assists in serializing and deserializing data between them. Simply map an AS class to a ruby class and when the object is (de)serialized it will end up as the appropriate class.
Example:
RocketAMF::ClassMapper.define do |m|
m.map :as => 'AsClass', :ruby => 'RubyClass'
m.map :as => 'vo.User', :ruby => 'Model::User'
end
Object Population/Serialization
In addition to handling class name mapping, it also provides helper methods for populating ruby objects from AMF and extracting properties from ruby objects for serialization. Support for hash-like objects and objects using attr_accessor
for properties is currently built in, but custom classes may need custom support. As such, it is possible to create a custom populator or serializer.
Populators are processed in insert order and must respond to the can_handle?
and populate
methods.
class CustomPopulator
def can_handle? obj
true
end
def populate obj, props, dynamic_props
obj.merge! props
obj.merge!(dynamic_props) if dynamic_props
end
end
RocketAMF::ClassMapper.object_populators << CustomPopulator.new
Serializers are also processed in insert order and must respond to the can_handle?
and serialize
methods.
class CustomSerializer
def can_handle? obj
true
end
def serialize obj
{}
end
end
RocketAMF::ClassMapper.object_serializers << CustomSerializer.new
Complete Replacement
In some cases, it may be beneficial to replace the default provider of class mapping completely. In this case, simply assign an instance of your own class mapper to RocketAMF::ClassMapper
after loading RocketAMF. Through the magic of const_missing
, ClassMapper
is only defined after the first access by default, so you get no annoying warning messages. Custom class mappers must implement the following methods: get_as_class_name
, get_ruby_obj
, populate_ruby_obj
, props_for_serialization
.
Example:
require 'rubygems'
require 'rocketamf'
RocketAMF::ClassMapper = MyCustomClassMapper.new
# No warning about already initialized constant ClassMapper
RocketAMF::ClassMapper.class # MyCustomClassMapper
Defined Under Namespace
Classes: MappingSet
Instance Attribute Summary collapse
-
#object_populators ⇒ Object
readonly
Array of custom object populators.
-
#object_serializers ⇒ Object
readonly
Array of custom object serializers.
Instance Method Summary collapse
-
#define {|mappings| ... } ⇒ Object
Define class mappings in the block.
-
#get_as_class_name(obj) ⇒ Object
Returns the AS class name for the given ruby object.
-
#get_ruby_obj(as_class_name) ⇒ Object
Instantiates a ruby object using the mapping configuration based on the source AS class name.
-
#initialize ⇒ ClassMapping
constructor
:nodoc:.
-
#populate_ruby_obj(obj, props, dynamic_props = nil) ⇒ Object
Populates the ruby object using the given properties.
-
#props_for_serialization(ruby_obj) ⇒ Object
Extracts all exportable properties from the given ruby object and returns them in a hash.
-
#reset ⇒ Object
Reset all class mappings except the defaults.
Constructor Details
#initialize ⇒ ClassMapping
:nodoc:
124 125 126 127 |
# File 'lib/rocketamf/class_mapping.rb', line 124 def initialize #:nodoc: @object_populators = [] @object_serializers = [] end |
Instance Attribute Details
#object_populators ⇒ Object (readonly)
Array of custom object populators.
119 120 121 |
# File 'lib/rocketamf/class_mapping.rb', line 119 def object_populators @object_populators end |
#object_serializers ⇒ Object (readonly)
Array of custom object serializers.
122 123 124 |
# File 'lib/rocketamf/class_mapping.rb', line 122 def object_serializers @object_serializers end |
Instance Method Details
#define {|mappings| ... } ⇒ Object
Define class mappings in the block. Block is passed a MappingSet object as the first parameter.
Example:
RocketAMF::ClassMapper.define do |m|
m.map :as => 'AsClass', :ruby => 'RubyClass'
end
137 138 139 |
# File 'lib/rocketamf/class_mapping.rb', line 137 def define #:yields: mapping_set yield mappings end |
#get_as_class_name(obj) ⇒ Object
Returns the AS class name for the given ruby object. Will also take a string containing the ruby class name.
148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/rocketamf/class_mapping.rb', line 148 def get_as_class_name obj # Get class name if obj.is_a?(String) ruby_class_name = obj elsif obj.is_a?(Values::TypedHash) ruby_class_name = obj.type else ruby_class_name = obj.class.name end # Get mapped AS class name mappings.get_as_class_name ruby_class_name end |
#get_ruby_obj(as_class_name) ⇒ Object
Instantiates a ruby object using the mapping configuration based on the source AS class name. If there is no mapping defined, it returns a RocketAMF::Values::TypedHash
with the serialized class name.
165 166 167 168 169 170 171 172 173 174 |
# File 'lib/rocketamf/class_mapping.rb', line 165 def get_ruby_obj as_class_name ruby_class_name = mappings.get_ruby_class_name as_class_name if ruby_class_name.nil? # Populate a simple hash, since no mapping return Values::TypedHash.new(as_class_name) else ruby_class = ruby_class_name.split('::').inject(Kernel) {|scope, const_name| scope.const_get(const_name)} return ruby_class.new end end |
#populate_ruby_obj(obj, props, dynamic_props = nil) ⇒ Object
Populates the ruby object using the given properties
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/rocketamf/class_mapping.rb', line 177 def populate_ruby_obj obj, props, dynamic_props=nil # Process custom populators @object_populators.each do |p| next unless p.can_handle?(obj) p.populate obj, props, dynamic_props return obj end # Fallback populator props.merge! dynamic_props if dynamic_props hash_like = obj.respond_to?("[]=") props.each do |key, value| if obj.respond_to?("#{key}=") obj.send("#{key}=", value) elsif hash_like obj[key.to_sym] = value end end obj end |
#props_for_serialization(ruby_obj) ⇒ Object
Extracts all exportable properties from the given ruby object and returns them in a hash
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/rocketamf/class_mapping.rb', line 200 def props_for_serialization ruby_obj # Proccess custom serializers @object_serializers.each do |s| next unless s.can_handle?(ruby_obj) return s.serialize(ruby_obj) end # Handle hashes if ruby_obj.is_a?(Hash) # Stringify keys to make it easier later on and allow sorting h = {} ruby_obj.each {|k,v| h[k.to_s] = v} return h end # Fallback serializer props = {} @ignored_props ||= Object.new.public_methods (ruby_obj.public_methods - @ignored_props).each do |method_name| # Add them to the prop hash if they take no arguments method_def = ruby_obj.method(method_name) props[method_name.to_s] = ruby_obj.send(method_name) if method_def.arity == 0 end props end |
#reset ⇒ Object
Reset all class mappings except the defaults
142 143 144 |
# File 'lib/rocketamf/class_mapping.rb', line 142 def reset @mappings = nil end |