Module: RubyAMF::Model
- Included in:
- Rails::Model
- Defined in:
- lib/rubyamf/model.rb
Overview
Simply include in your ruby object to enable advanced serialization features like an in-model mapping API, customizable initialization after deserialization, scoped property configuration for serialization, and several other things. See RubyAMF::Model::ClassMethods for details of in-model mapping API.
Example:
class SerializableObject
include RubyAMF::Model
as_class "com.rubyamf.ASObject"
map_amf :only => "prop_a"
attr_accessor :prop_a, :prop_b
end
Integration
If the object you include RubyAMF::Model into implements attributes
and attributes=
, those two methods will be automatically used to determine serializable properties and to set them after deserialization. If you do not implement those methods, attributes will be guessed by going through all methods that don’t take arguments, and attribute setters will be used rather than attributes=
.
For most ORMs, the provided rubyamf_init
, rubyamf_hash
, and rubyamf_retrieve_association
should work correctly. However, they can be overridden to provide custom behavior if the default has issues with the ORM you are using. See RubyAMF::Rails::Model for an example of ORM-specific customization.
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
-
.included(base) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#rubyamf_hash(options = nil) ⇒ Object
Like serializable_hash, rubyamf_hash returns a hash for serialization calculated from the given options.
-
#rubyamf_init(props, dynamic_props = nil) ⇒ Object
Populates the object after deserialization.
-
#rubyamf_retrieve_association(association) ⇒ Object
Override if necessary to support your ORM’s system of retrieving objects in an association.
-
#rubyamf_set_non_attributes(attrs, base_attrs) ⇒ Object
Calls setters for all keys in the given hash not found in the base attributes hash and deletes those keys from the hash.
-
#to_amf(options = nil) ⇒ Object
Stores the given options and object in an IntermediateObject so that the default serialization mapping options can be overriden if necessary.
Class Method Details
.included(base) ⇒ Object
:nodoc:
34 35 36 |
# File 'lib/rubyamf/model.rb', line 34 def self.included base #:nodoc: base.send :extend, ClassMethods end |
Instance Method Details
#rubyamf_hash(options = nil) ⇒ Object
Like serializable_hash, rubyamf_hash returns a hash for serialization calculated from the given options. Supported options are :only
, :except
, :methods
, and :include
. This method is automatically called by RubyAMF::ClassMapping on serialization with the pre-configured options for whatever the current scope is.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/rubyamf/model.rb', line 132 def rubyamf_hash =nil # Process options ||= {} only = Array.wrap([:only]).map(&:to_s) except = Array.wrap([:except]).map(&:to_s) method_names = [] Array.wrap([:methods]).each do |name| method_names << name.to_s if respond_to?(name) end # Get list of attributes if respond_to?(:attributes) attrs = send(:attributes) else attrs = {} ignored_props = Object.new.public_methods (self.public_methods - ignored_props).each do |method_name| # Add them to the attrs hash if they take no arguments method_def = self.method(method_name) attrs[method_name.to_s] = send(method_name) if method_def.arity == 0 end end attribute_names = attrs.keys.sort if only.any? attribute_names &= only elsif except.any? attribute_names -= except end # Build hash from attributes and methods hash = {} attribute_names.each {|name| hash[name] = attrs[name]} method_names.each {|name| hash[name] = send(name)} # Add associations using ActiveRecord::Serialization style options # processing if include_associations = .delete(:include) # Process options base_only_or_except = {:except => [:except], :only => [:only]} = include_associations.is_a?(Hash) associations = ? include_associations.keys : Array.wrap(include_associations) # Call to_amf on each object in the association, passing processed options associations.each do |association| records = rubyamf_retrieve_association(association) if records opts = ? include_associations[association] : nil if records.is_a?(Enumerable) hash[association.to_s] = records.map {|r| opts.nil? ? r : r.to_amf(opts)} else hash[association.to_s] = opts.nil? ? records : records.to_amf(opts) end end end [:include] = include_associations end hash end |
#rubyamf_init(props, dynamic_props = nil) ⇒ Object
Populates the object after deserialization. By default it calls initialize, calls setters for keys not in attributes, and calls attributes=
for the remaining properties if it’s implemented. Override if necessary to support your ORM.
98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/rubyamf/model.rb', line 98 def rubyamf_init props, dynamic_props = nil initialize # warhammerkid: Call initialize by default - good decision? props.merge!(dynamic_props) if dynamic_props if respond_to?(:attributes=) attrs = self.attributes rubyamf_set_non_attributes props, attrs self.attributes = props # Populate using attributes setter else rubyamf_set_non_attributes props, {} # Calls setters for all props it finds setters for end end |
#rubyamf_retrieve_association(association) ⇒ Object
Override if necessary to support your ORM’s system of retrieving objects in an association.
195 196 197 198 199 |
# File 'lib/rubyamf/model.rb', line 195 def rubyamf_retrieve_association association # Naive implementation that should work for most cases without # need for overriding send(association) end |
#rubyamf_set_non_attributes(attrs, base_attrs) ⇒ Object
Calls setters for all keys in the given hash not found in the base attributes hash and deletes those keys from the hash. Performs some simple checks on the keys to hopefully prevent more private setters from being called.
114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/rubyamf/model.rb', line 114 def rubyamf_set_non_attributes attrs, base_attrs not_attributes = attrs.keys.select {|k| !base_attrs.include?(k)} not_attributes.each do |k| setter = "#{k}=" next if setter !~ /^[a-z][A-Za-z0-9_]+=/ # Make sure setter doesn't start with capital, dollar, or underscore to make this safer if respond_to?(setter) send(setter, attrs.delete(k)) else RubyAMF.logger.warn("RubyAMF: Cannot call setter for non-attribute on #{self.class.name}: #{k}") end end end |
#to_amf(options = nil) ⇒ Object
Stores the given options and object in an IntermediateObject so that the default serialization mapping options can be overriden if necessary.
203 204 205 |
# File 'lib/rubyamf/model.rb', line 203 def to_amf =nil RubyAMF::IntermediateObject.new(self, ) end |