Permalink
Browse files

More documentation!

  • Loading branch information...
1 parent 7bd6d8e commit f20a6c872884849a1e66319a86e530189b8e58ce @warhammerkid warhammerkid committed Jun 28, 2011
Showing with 181 additions and 29 deletions.
  1. +29 −26 README.rdoc
  2. +49 −1 lib/rubyamf/class_mapping.rb
  3. +101 −2 lib/rubyamf/configuration.rb
  4. +2 −0 lib/rubyamf/logger.rb
View
@@ -3,28 +3,30 @@
RubyAMF is a full-featured AMF gateway based off of Rack and supporting advanced
integration with Rails and other Rack-based frameworks. It includes advanced
class mapping functionality, like camel to underscore case translation,
-parameter mapping to convert function calls to parameter hashes, hooks for
-processing AMF authentication credentials, and many more features.
+parameter mapping to convert function calls to parameter hashes for actions,
+hooks for processing AMF authentication credentials, and many more features.
== UPGRADE FROM rubyamf_plugin:
-1. Delete <tt>RAILS_ROOT/vendor/plugins/rubyamf</tt> or comment out every line in <tt>RAILS_ROOT/vendor/plugins/rubyamf/init.rb</tt>.
+1. Delete <tt>RAILS_ROOT/vendor/plugins/rubyamf</tt> or comment out every line
+ in <tt>RAILS_ROOT/vendor/plugins/rubyamf/init.rb</tt>.
2. Add gems to application:
- Bundler:
- gem "RocketAMF", :git => "git://github.com/rubyamf/rocketamf.git"
- gem 'rubyamf', :git => 'git://github.com/warhammerkid/rubyamf-experiment.git'
+ <b>Bundler:</b>
+ gem "RocketAMF", :git => "git://github.com/rubyamf/rocketamf.git"
+ gem 'rubyamf', :git => 'git://github.com/warhammerkid/rubyamf-experiment.git'
- environment.rb:
- config.gem "RocketAMF"
- config.gem "rubyamf"
+ <b>environment.rb:</b>
+ config.gem "RocketAMF"
+ config.gem "rubyamf"
-3. Configure the endpoint path by adding the following to the end of your <tt>environment.rb</tt> file:
+3. Configure the endpoint path by adding the following to the end of your
+ <tt>environment.rb</tt> file:
- RubyAMF.configure do |config|
- config.gateway_path = "/rubyamf/gateway"
- end
+ RubyAMF.configure do |config|
+ config.gateway_path = "/rubyamf/gateway"
+ end
The gateway path is no longer specified in <tt>routes.rb</tt>, so you can
remove it and <tt>rubyamf_controller.rb</tt> if you want.
@@ -41,19 +43,20 @@ at (SOMEWHERE) or the RDoc at (SOMEWHERE).
1. Add gems to application:
- Bundler:
- gem "RocketAMF", :git => "git://github.com/rubyamf/rocketamf.git"
- gem 'rubyamf', :git => 'git://github.com/warhammerkid/rubyamf-experiment.git'
+ <b>Bundler:</b>
+ gem "RocketAMF", :git => "git://github.com/rubyamf/rocketamf.git"
+ gem 'rubyamf', :git => 'git://github.com/warhammerkid/rubyamf-experiment.git'
- environment.rb:
- config.gem "RocketAMF"
- config.gem "rubyamf"
+ <b>environment.rb:</b>
+ config.gem "RocketAMF"
+ config.gem "rubyamf"
-2. Configure the endpoint path by adding the following to the end of your <tt>environment.rb</tt> file:
+2. Configure the endpoint path by adding the following to the end of your
+ <tt>environment.rb</tt> file:
- RubyAMF.configure do |config|
- config.gateway_path = "/rubyamf/gateway"
- end
+ RubyAMF.configure do |config|
+ config.gateway_path = "/rubyamf/gateway"
+ end
Check out the demo app at (SOMEWHERE) or the RDoc at (SOMEWHERE) for information
about configuration and use.
@@ -62,12 +65,12 @@ about configuration and use.
1. Add the gems to your Gemfile:
- gem "RocketAMF", :git => "git://github.com/rubyamf/rocketamf.git"
- gem 'rubyamf', :git => 'git://github.com/warhammerkid/rubyamf-experiment.git'
+ gem "RocketAMF", :git => "git://github.com/rubyamf/rocketamf.git"
+ gem 'rubyamf', :git => 'git://github.com/warhammerkid/rubyamf-experiment.git'
2. Configure the endpoint path by adding the following to your <tt>application.rb</tt>:
- config.rubyamf.gateway_path = "/amf"
+ config.rubyamf.gateway_path = "/amf"
Check out the demo app at (SOMEWHERE) or the RDoc at (SOMEWHERE) for information
about configuration and use.
@@ -1,5 +1,8 @@
module RubyAMF
+ # Advanced mapping container to support various serialization customization
+ # settings. Used by RubyAMF class mapper to store advanced mappings.
class MappingSet < ::RocketAMF::MappingSet
+ # Store all property mapping configuration by scope
class Mapping
attr_accessor :ruby, :as, :default_scope, :scopes
def initialize
@@ -16,6 +19,18 @@ def initialize
map_defaults
end
+ # Map a given actionscript class to a ruby class. You can also control which
+ # properties are serialized using <tt>:except</tt>, <tt>:only</tt>,
+ # <tt>:methods</tt>, <tt>:include</tt> for relations, and <tt>:ignore_fields</tt>
+ # for skipping certain fields during deserialization.
+ #
+ # Use fully qualified names for both.
+ #
+ # Examples:
+ #
+ # m.map :as => 'com.example.Date', :ruby => 'Example::Date'
+ # m.map :flash => 'User', :ruby => 'User', :only => 'username'
+ # m.map :flash => 'User', :ruby => 'User', :scope => :other, :include => [:courses, :teacher]
def map params
# Extract and validate ruby and AS class names
ruby_class = params[:ruby]
@@ -49,16 +64,22 @@ def map params
end
end
+ # Returns the actionscript class name mapped to the given ruby class name.
+ # Returns <tt>nil</tt> if not found.
def get_as_class_name ruby_class_name
mapping = @ruby_mappings[ruby_class_name]
return mapping.nil? ? nil : mapping.as
end
+ # Returns the ruby class name mapped to the given actionscript class name.
+ # Returns <tt>nil</tt> if not found.
def get_ruby_class_name as_class_name
mapping = @as_mappings[as_class_name]
return mapping.nil? ? nil : mapping.ruby
end
+ # Returns the property serialization config for the given ruby class name
+ # and scope. If scope is <tt>nil</tt>, it uses the default scope.
def serialization_config ruby_class_name, scope = nil
mapping = @ruby_mappings[ruby_class_name]
if mapping.nil?
@@ -70,13 +91,24 @@ def serialization_config ruby_class_name, scope = nil
end
end
+ # Advanced class mapper based off of RocketAMF class mapper. Adds support for
+ # advanced serialization and deserialization.
class ClassMapping < ::RocketAMF::ClassMapping
+ # Override RocketAMF#mappings to return new RubyAMF::MappingSet object rather
+ # than RocketAMF::MappingSet
def self.mappings
@mappings ||= RubyAMF::MappingSet.new
end
- attr_accessor :mapping_scope # nil uses proper default calculations
+ # The mapping scope to use during serialization. This is populated during
+ # response serialization automatically by RubyAMF::Envelope.
+ attr_accessor :mapping_scope
+ # Return the actionscript class name for the given ruby object. If the object
+ # is a string, that is assumed to be the ruby class name. Otherwise it extracts
+ # the ruby class name from the object based on its type. As RocketAMF calls
+ # this for all objects on serialization, auto-mapping takes place here if
+ # enabled.
def get_as_class_name obj
# Get class name
if obj.is_a?(String)
@@ -103,6 +135,15 @@ def get_as_class_name obj
as_class_name
end
+ # Creates a ruby object to populate during deserialization for the given
+ # actionscript class name. If that actionscript class name is mapped to a
+ # ruby class, an object of that class is created using
+ # <tt>obj = ruby_class_name.constantize.allocate</tt> and then
+ # <tt>:initialize</tt> is sent to the new instance unless it implements
+ # <tt>rubyamf_init</tt>. If no ruby class name is defined, a
+ # <tt>RocketAMF::Values::TypedHash</tt> object is created and its type
+ # attribute is set to the actionscript class name. As RocketAMF calls this
+ # for all objects on deserialization, auto-mapping takes place here if enabled.
def get_ruby_obj as_class_name
# Get ruby class name
ruby_class_name = @mappings.get_ruby_class_name as_class_name
@@ -124,6 +165,9 @@ def get_ruby_obj as_class_name
end
end
+ # Performs all enabled property translations (case, key type, ignore_fields)
+ # before passing to <tt>rubyamf_init</tt> if implemented, or to the RocketAMF
+ # class mapper implementation.
def populate_ruby_obj obj, props, dynamic_props=nil
# Translate case of properties before passing down to super
if RubyAMF.configuration.translate_case && !obj.is_a?(RocketAMF::Values::AbstractMessage)
@@ -159,6 +203,10 @@ def populate_ruby_obj obj, props, dynamic_props=nil
end
end
+ # Extracts a hash of all object properties for serialization from the object,
+ # using <tt>rubyamf_hash</tt> if implemented with the proper mapping configs
+ # for the scope, or the RocketAMF implementation. Before being returned to
+ # the serializer, case translation is performed if enabled.
def props_for_serialization ruby_obj
props = nil
@@ -1,8 +1,84 @@
module RubyAMF
+ # RubyAMF configuration container. It can be accessed by calling
+ # <tt>RubyAMF.configuration</tt>, or modified in a block like so:
+ #
+ # RubyAMF.configure do |config|
+ # config.gateway_path = "/amf"
+ # end
+ #
+ # === Gateway configuration
+ #
+ # Gateway configuration includes the gateway path and details about parameter
+ # mapping.
+ #
+ # +gateway_path+::
+ # Default: <tt>"/rubyamf/gateway"</tt>. The URL that responds to AMF requests.
+ # The URL should start with a "/" and not end with a "/".
+ #
+ # +populate_params_hash+::
+ # Default: <tt>true</tt>. For Rails users, all amf parameters can be accessed
+ # in the controller by calling <tt>rubyamf_params</tt>. If enabled, the amf
+ # parameters are merged into the <tt>params</tt> hash as well.
+ #
+ # +show_html_gateway+::
+ # Default: <tt>true</tt>. If enabled, non-AMF requests to the gateway url
+ # will result in a simple HTML page being returned.
+ #
+ # +param_mappings+::
+ # A hash that stores parameter mappings. Should only be modified through
+ # calls to <tt>map_params</tt>
+ #
+ # === Serialization options
+ #
+ # RubyAMF provides a wide variety of customization options for serialization
+ # to simplify integration.
+ #
+ # +translate_case+::
+ # Default: <tt>false</tt>. If enabled, properties will be converted to
+ # underscore style on deserialization from actionscript and will be converted
+ # to camelcase on serialization. This allows you to use language appropriate
+ # case style and have RubyAMF automatically care of translation.
+ #
+ # +auto_class_mapping+::
+ # Default: <tt>false</tt>. If a class mapping for a given ruby or actionscript
+ # class has not been defined, automatically maps it during serialization or
+ # deserialization. Nested ruby or actionscript classes will be automatically
+ # mapped to the class name without the namespace. Example:
+ # <tt>com.rubyamf.User => User</tt> or <tt>RubyAMF::User => User</tt>.
+ #
+ # +use_array_collection+::
+ # Default: <tt>false</tt>. If enabled, all arrays will be serialized as
+ # <tt>ArrayCollection</tt> objects. You can override this on a per-array
+ # basis by setting <tt>is_array_collection</tt> on the array to <tt>true</tt>
+ # or <tt>false</tt>. (Implementation in RocketAMF)
+ #
+ # +hash_key_access+::
+ # Default: <tt>:symbol</tt>. If set to <tt>:string</tt>, all deserialized
+ # hashes have the keys as strings. RocketAMF defaults to symbols, so setting
+ # to <tt>:string</tt> will reduce performance and increase memory usage.
+ #
+ # +preload_models+::
+ # If you are using in-model mapping and don't have <tt>auto_class_mapping</tt>
+ # enabled, you may need to force classes to be loaded before mapping takes
+ # effect. Simply include all necessary classes as strings to have RubyAMF
+ # force them to be loaded on initialization.
+ # Example: <tt>config.preload_models = ["User", "Course"]</tt>
+ #
+ # +check_for_associations+::
+ # Default: <tt>true</tt>. If enabled, associations that have been pre-loaded,
+ # either through :include or simply by being accessed, will be automatically
+ # included during serialization without any additional configuration.
+ #
+ # +ignore_fields+::
+ # Default: <tt>['created_at', 'created_on', 'updated_at', 'updated_on']</tt>.
+ # A list of all properties that should not be serialized unless they show
+ # up in the <tt>:only => [:prop]</tt> class mapping config for that object.
+ # Completely separate from the <tt>:ignore_fields</tt> config for class
+ # mapping, which affects deserialization.
class Configuration
# Gateway options
- attr_accessor :gateway_path, :param_mappings, :populate_params_hash,
- :show_html_gateway
+ attr_accessor :gateway_path, :populate_params_hash, :show_html_gateway
+ attr_reader :param_mappings
# Serialization options
attr_accessor :translate_case, :auto_class_mapping, :use_array_collection,
@@ -24,21 +100,44 @@ def initialize
@ignore_fields = ['created_at', 'created_on', 'updated_at', 'updated_on']
end
+ # Maps the given array of named parameters to the arguments for calls to the
+ # given controller and action. For Rails users, the prefered method of
+ # parameter mapping is through routing (see RubyAMF::Rails::Routing).
+ #
+ # Example:
+ #
+ # config.map_params "UserController", "login", [:session_token, :username, :password]
+ # # params hash => {
+ # # 0 => "asdf", 1 => "user", 2 => "pass",
+ # # :session_token => "asdf", :username => "user", :password => "pass"
+ # # }
def map_params controller, action, params
@param_mappings[controller.to_s+"#"+action.to_s] = params
end
+ # Returns the class mapper class being used
def class_mapper
if @class_mapper.nil?
@class_mapper = RubyAMF::ClassMapping
end
@class_mapper
end
+ # Set to the class of any conforming class mapper to use it instead of
+ # <tt>RubyAMF::ClassMapping</tt>. If you don't need any of the advanced
+ # features offered by the RubyAMF class mapper, you can gain some substantial
+ # performance improvements by settings this to
+ # <tt>RocketAMF::Ext::FastClassMapping</tt> or <tt>RocketAMF::ClassMapping</tt>
+ # for the slower pure-ruby version.
def class_mapper= klass
@class_mapper = klass
end
+ # Loads the legacy config file at the given path or tries to locate it by
+ # looking for a <tt>rubyamf_config.rb</tt> file in several possible locations.
+ # Automatically run by RubyAMF if you are using Rails 2, it should be run
+ # before any additional configuration if you are not using Rails 2, as it
+ # overrides all previous configuration.
def load_legacy path=nil
# Locate legacy config
unless path
View
@@ -15,6 +15,7 @@ def method_missing name, *args
end
private
+ # Use rails logger if available or create standard ruby logger to STDERR
def logger
unless @logger
if defined?(Rails)
@@ -26,6 +27,7 @@ def logger
@logger
end
+ # Use Rails backtrace cleaner if it exists to clean
def clean_backtrace e
if defined?(Rails) && ::Rails.respond_to?(:backtrace_cleaner)
::Rails.backtrace_cleaner.clean(e.backtrace)

0 comments on commit f20a6c8

Please sign in to comment.