Permalink
Browse files

Initial import

  • Loading branch information...
0 parents commit fc8432bc2106d0f3a17239bf5dff74e1ed0725f4 @pillowfactory committed Jul 30, 2008
Showing with 1,264 additions and 0 deletions.
  1. +17 −0 .project
  2. +20 −0 MIT-LICENSE
  3. +62 −0 README
  4. +22 −0 Rakefile
  5. BIN generators/.DS_Store
  6. +11 −0 generators/action_script_models/.svn/all-wcprops
  7. +44 −0 generators/action_script_models/.svn/entries
  8. +1 −0 generators/action_script_models/.svn/format
  9. +5 −0 generators/action_script_models/.svn/prop-base/action_script_models_generator.rb.svn-base
  10. +135 −0 generators/action_script_models/.svn/text-base/action_script_models_generator.rb.svn-base
  11. +135 −0 generators/action_script_models/action_script_models_generator.rb
  12. +41 −0 generators/action_script_models/templates/.svn/all-wcprops
  13. +102 −0 generators/action_script_models/templates/.svn/entries
  14. +1 −0 generators/action_script_models/templates/.svn/format
  15. +5 −0 generators/action_script_models/templates/.svn/prop-base/as3_model.erb.svn-base
  16. +5 −0 generators/action_script_models/templates/.svn/prop-base/as3_model_base.erb.svn-base
  17. +6 −0 generators/action_script_models/templates/.svn/text-base/as3_base.erb.svn-base
  18. +124 −0 generators/action_script_models/templates/.svn/text-base/as3_helper_errors.erb.svn-base
  19. +35 −0 generators/action_script_models/templates/.svn/text-base/as3_helper_hash.erb.svn-base
  20. +38 −0 generators/action_script_models/templates/.svn/text-base/as3_helper_rubyamf.erb.svn-base
  21. +11 −0 generators/action_script_models/templates/.svn/text-base/as3_model.erb.svn-base
  22. +41 −0 generators/action_script_models/templates/.svn/text-base/as3_model_base.erb.svn-base
  23. +6 −0 generators/action_script_models/templates/as3_base.erb
  24. +124 −0 generators/action_script_models/templates/as3_helper_errors.erb
  25. +35 −0 generators/action_script_models/templates/as3_helper_hash.erb
  26. +38 −0 generators/action_script_models/templates/as3_helper_rubyamf.erb
  27. +11 −0 generators/action_script_models/templates/as3_model.erb
  28. +41 −0 generators/action_script_models/templates/as3_model_base.erb
  29. +9 −0 init.rb
  30. +85 −0 install.rb
  31. +41 −0 lib/rubyamf_quickly.rb
  32. +4 −0 tasks/rubyamf_quickly_tasks.rake
  33. +8 −0 test/rubyamf_quickly_test.rb
  34. +1 −0 uninstall.rb
17 .project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>rubyamf_quickly</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.rubypeople.rdt.core.rubybuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.rubypeople.rdt.core.rubynature</nature>
+ </natures>
+</projectDescription>
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2008 Luke Pillow
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
62 README
@@ -0,0 +1,62 @@
+RubyAMF::Quickly
+================
+
+The RubyAMF::Quickly plugin is intended to jump start any Flex on Rails project using RubyAMF.
+
+NOTE: The RubyAMF::Quickly plugin installation appends it's own configuration settings to the config/rubyamf_config.rb file.
+ The plugin's configuration defaults it's settings for the most natural Rails and Flex development as well as overrides some of the
+ default RubyAMF settings. All examples and following explanation are given using the RubyAMF::Quickly default configuration.
+
+RubyAMF::Quickly provides the following:
+
+ 1. ActionScript Model Generator
+ ============================
+ The action_script_models generator creates ActionScript models from the project's ActiveRecord models.
+
+ Given a Rails project with a single ActiveRecord model, Person.rb the following will be created from running
+ ./script/generate action_script_models com.example.models
+
+ RAILS_ROOT/app/flex/com/example/models/Person.as => Generated once. Add custom ActionScript model behavior here. Subclasses PersonBase.as
+ RAILS_ROOT/app/flex/com/example/models/base/PersonBase.as => Generated every time. Contains properties and toParams() method
+ RAILS_ROOT/app/flex/com/example/models/helpers/Errors.as => ActionScript implementation of the ActiveRecord Errors class
+ RAILS_ROOT/app/flex/com/example/models/helpers/Hash.as => ActionScript dynamic class with some Ruby Hash-like methods
+ RAILS_ROOT/app/flex/com/example/models/helpers/RubyAMF.as => Simple remoting helper for Rails controller/action invocation
+
+ 2. Runtime Assistance
+ ==================
+ By default, RubyAMF::Quickly adds a couple of helpers to the RubyAMF request cycle.
+
+ - Parameter Filtering - This before_filter merges any remoting request parameters into the standard controller params hash.
+ - Default Exception Handling - Using the Rails 2 rescue_from method, any unhandled Exceptions will be converted to a RubyAMF
+ FaultObject that will trigger an ActionScript FaultEvent.
+
+
+Quickly Concepts
+================
+
+The main idea behind RubyAMF::Quickly is to keep with the simplicity of Rails RESTful theme while maintaining a natural Flex development environment. The core RubyAMF project allows bidirectional object graph messaging. This method works, but is not conducive to reuse of existing Rails controller logic without "cluttering" things up with is_amf conditional logic. Again... this works, but is not the Rails way.
+
+RubyAMF::Quickly encourages a slightly different approach: Send HTTP hash-like requests from Flex. Let Rails respond to AMF requests with ActiveRecord object graphs.
+
+
+Example
+=======
+
+Given a Person.rb ActiveRecord class, a PeopleController#create Rails controller/action, and the generated ActionScript classes as described above, the following ActionScript code will save a Person to the database.
+
+ var myPerson:Person = new Person();
+ myPerson.name = 'Foo';
+ myPerson.favoriteNumber = 7;
+
+ RubyAMF.call('PeopleController', 'create', {person: myPerson.toParams()}, myPersonResultHandler, myPersonFaultHandler);
+
+This example uses the generated Person.as ActionScript class that corresponds to the ActiveRecord Person.rb with two database attributes: name and favorite_number. The RubyAMF.call() method streamlines the definition and "caching" of Flex RemoteObjects. The first parameter is the class name of the Rails controller we're targeting. The second parameter is the controller action to invoke. The third parameter is an anonymous object that serves as the hash-like "wrapper" that the parameters will be sent in. This is the equivalent of a standard HTML form input names of person[name] and person[favorite_number]. You'll want to note the use of myPerson.toParams() when constructing the request "hash." toParams() is defined on the generated PersonBase.as class that returns another anonymous object with the corresponding attributes and values. The request "hash" could have also been defined without using the toParams() method as {person: {name: 'foo', favoriteNumber: 7}}, but the toParams() method provides additional functionality. toParams() also accepts an array of properties to exclude. For example, {person: myPerson.toParams('name')} would not include the name property and value in the request.
+
+
+More Documentation
+==================
+
+The RubyAMF::Quickly::Config section that was appended to rubyamf_config.rb file has more documentation for configuration options supported by RubyAMF::Quickly.
+
+
+Copyright (c) 2008 Luke Pillow, released under the MIT license
22 Rakefile
@@ -0,0 +1,22 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the rubyamf_quickly plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the rubyamf_quickly plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'RubyamfQuickly'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
BIN generators/.DS_Store
Binary file not shown.
11 generators/action_script_models/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svn/!svn/ver/111/plugins/rubyamf_quickly/generators/action_script_models
+END
+action_script_models_generator.rb
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/svn/!svn/ver/111/plugins/rubyamf_quickly/generators/action_script_models/action_script_models_generator.rb
+END
44 generators/action_script_models/.svn/entries
@@ -0,0 +1,44 @@
+8
+
+dir
+111
+http://www.treetrunkmedia.com/svn/plugins/rubyamf_quickly/generators/action_script_models
+http://www.treetrunkmedia.com/svn
+
+
+
+2008-07-02T16:04:28.464873Z
+111
+lpillow
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+975abe41-da3c-0410-88f3-9b76e4b188a3
+
+action_script_models_generator.rb
+file
+
+
+
+
+2008-07-30T17:47:08.000000Z
+ff3176acb15c87929d2f65c86ad2883a
+2008-07-02T16:04:28.464873Z
+111
+lpillow
+has-props
+
+templates
+dir
+
1 generators/action_script_models/.svn/format
@@ -0,0 +1 @@
+8
5 generators/action_script_models/.svn/prop-base/action_script_models_generator.rb.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END
135 generators/action_script_models/.svn/text-base/action_script_models_generator.rb.svn-base
@@ -0,0 +1,135 @@
+require 'app/configuration'
+require 'rubyamf_quickly'
+
+class ActionScriptModelsGenerator < Rails::Generator::Base
+ include RubyAMF::Quickly
+
+ default_options :skip_helpers => false, :force_all => false
+
+ # runtime_args[0] = AS3 Package
+ def initialize(*runtime_args)
+ super(*runtime_args)
+ Config.action_script_package = runtime_args[0] unless runtime_args[0].empty?
+ end
+
+ def manifest
+ record do |m|
+
+ helper_package = [Config.action_script_package, 'helpers'].compact.join('.')
+ skip_or_force = options[:force_all] ? :force : :skip
+
+ # HELPERS
+ unless options[:skip_helpers]
+ FileUtils.makedirs(helper_dir = File.join(Config.relative_flex_root, helper_package.split(/\./)))
+
+ ['Hash', 'RubyAMF', 'Errors'].each do |helper_name|
+ m.template( "as3_helper_#{helper_name.downcase}.erb", File.join( helper_dir, "#{helper_name}.as" ), :collision => skip_or_force,
+ :assigns => {:package => helper_package })
+ end
+ end
+
+ # MODELS
+
+ # Base
+ FileUtils.makedirs(base_dir = File.join(Config.relative_flex_root, Config.action_script_package.to_s.split(/\./), 'base'))
+ m.template( 'as3_base.erb', File.join(base_dir, 'Base.as'), :collision => skip_or_force,
+ :assigns => {:package => [Config.action_script_package, 'base'].compact.join('.')} )
+
+ ar_models = []
+ Dir.chdir(File.join(RAILS_ROOT, 'app', 'models')) do
+ Dir["**/*.rb"].each do |entry|
+ unless Config.ignore_classes.include?( model_class_name = entry.sub(/\.rb$/,'').camelize )
+ model_class = model_class_name.constantize
+ ar_models << model_class if model_class < ActiveRecord::Base && !model_class.abstract_class?
+ end
+ end
+ end
+
+ ar_models.each do |ar|
+ as3_class = ActionScriptModel.new( ar, Config.action_script_package )
+
+ FileUtils.makedirs(dest_dir = File.join(Config.relative_flex_root, as3_class.package.to_s.split(/\./)))
+ FileUtils.makedirs(base_dest_dir = File.join( dest_dir, 'base'))
+
+ m.template( 'as3_model_base.erb', File.join(base_dest_dir, "#{as3_class.name}Base.as"), :collision => :force,
+ :assigns => { :as3_class => as3_class,
+ :use_helpers => !options[:skip_helpers],
+ :helper_package => helper_package } )
+ m.template( 'as3_model.erb', File.join(dest_dir, "#{as3_class.name}.as"), :collision => skip_or_force,
+ :assigns => { :as3_class => as3_class } )
+ end
+
+ end
+ end
+
+ protected
+
+ def banner
+ "Usage: #{$0} #{spec.name} actionscript.root.package [options]"
+ end
+
+ def add_options!(opt)
+ opt.separator ''
+ opt.separator 'Options:'
+ opt.on("--skip-helpers",
+ "Skip ActionScript helper classes that add simple remoting and Ruby/Rails style model behavior.") { |v| options[:skip_helpers] = v }
+ opt.on("--force-all",
+ "Force generation of all files. WARNING: This will overwrite any changes made to previously generated files.") { |v| options[:force_all] = v }
+ end
+
+end
+
+module RubyAMF::Quickly
+ class ActionScriptModel
+ attr_accessor :name, :properties, :package, :base_package, :ruby_class
+
+ def initialize( ar_class, root_package=nil )
+ self.name = ar_class.to_s.split(/::/).last
+ self.ruby_class = ar_class
+
+ # Determine this class' package
+ relative_package = ar_class.to_s.split(/::/)[0...-1].join('.').downcase!
+ self.package = [root_package, relative_package].compact.join('.')
+ self.base_package = [self.package, 'base'].compact.join('.')
+
+ # Build properties
+ self.properties = []
+ ar_class.columns.each do |col|
+ unless RubyAMF::Configuration::ClassMappings.ignore_fields.include? col.name
+ self.properties << ActionScriptProperty.new(col)
+ end
+ end
+
+ self.properties.sort! {|a, b| a.name <=> b.name }
+ end
+ end
+
+ class ActionScriptProperty
+ attr_accessor :name, :static_type, :accessor
+
+ def initialize( ar_column )
+ self.name = (RubyAMF::Configuration::ClassMappings.translate_case ? ar_column.name.dup.to_camel! : ar_column.name.dup)
+ self.static_type = TypeConverter.convert(ar_column)
+ self.accessor = (self.static_type == 'Boolean' && RubyAMF::Quickly::Config.prefix_booleans ? "is#{self.name.capitalize}" : self.name)
+ end
+
+ end
+
+ class TypeConverter
+ def self.convert( ar_col )
+ ruby_class, col_type = ar_col.klass, ar_col.type
+ if ruby_class == String or ruby_class < String
+ return 'String'
+ elsif ruby_class < Numeric
+ return 'Number'
+ elsif ruby_class == Object and ar_col.type == :boolean
+ return 'Boolean'
+ elsif ruby_class == Time or ruby_class == Date or ruby_class < Date or ruby_class < Time
+ return 'Date'
+ else
+ return 'Object'
+ end
+ end
+ end
+end
+
135 generators/action_script_models/action_script_models_generator.rb
@@ -0,0 +1,135 @@
+require 'app/configuration'
+require 'rubyamf_quickly'
+
+class ActionScriptModelsGenerator < Rails::Generator::Base
+ include RubyAMF::Quickly
+
+ default_options :skip_helpers => false, :force_all => false
+
+ # runtime_args[0] = AS3 Package
+ def initialize(*runtime_args)
+ super(*runtime_args)
+ Config.action_script_package = runtime_args[0] unless runtime_args[0].empty?
+ end
+
+ def manifest
+ record do |m|
+
+ helper_package = [Config.action_script_package, 'helpers'].compact.join('.')
+ skip_or_force = options[:force_all] ? :force : :skip
+
+ # HELPERS
+ unless options[:skip_helpers]
+ FileUtils.makedirs(helper_dir = File.join(Config.relative_flex_root, helper_package.split(/\./)))
+
+ ['Hash', 'RubyAMF', 'Errors'].each do |helper_name|
+ m.template( "as3_helper_#{helper_name.downcase}.erb", File.join( helper_dir, "#{helper_name}.as" ), :collision => skip_or_force,
+ :assigns => {:package => helper_package })
+ end
+ end
+
+ # MODELS
+
+ # Base
+ FileUtils.makedirs(base_dir = File.join(Config.relative_flex_root, Config.action_script_package.to_s.split(/\./), 'base'))
+ m.template( 'as3_base.erb', File.join(base_dir, 'Base.as'), :collision => skip_or_force,
+ :assigns => {:package => [Config.action_script_package, 'base'].compact.join('.')} )
+
+ ar_models = []
+ Dir.chdir(File.join(RAILS_ROOT, 'app', 'models')) do
+ Dir["**/*.rb"].each do |entry|
+ unless Config.ignore_classes.include?( model_class_name = entry.sub(/\.rb$/,'').camelize )
+ model_class = model_class_name.constantize
+ ar_models << model_class if model_class < ActiveRecord::Base && !model_class.abstract_class?
+ end
+ end
+ end
+
+ ar_models.each do |ar|
+ as3_class = ActionScriptModel.new( ar, Config.action_script_package )
+
+ FileUtils.makedirs(dest_dir = File.join(Config.relative_flex_root, as3_class.package.to_s.split(/\./)))
+ FileUtils.makedirs(base_dest_dir = File.join( dest_dir, 'base'))
+
+ m.template( 'as3_model_base.erb', File.join(base_dest_dir, "#{as3_class.name}Base.as"), :collision => :force,
+ :assigns => { :as3_class => as3_class,
+ :use_helpers => !options[:skip_helpers],
+ :helper_package => helper_package } )
+ m.template( 'as3_model.erb', File.join(dest_dir, "#{as3_class.name}.as"), :collision => skip_or_force,
+ :assigns => { :as3_class => as3_class } )
+ end
+
+ end
+ end
+
+ protected
+
+ def banner
+ "Usage: #{$0} #{spec.name} actionscript.root.package [options]"
+ end
+
+ def add_options!(opt)
+ opt.separator ''
+ opt.separator 'Options:'
+ opt.on("--skip-helpers",
+ "Skip ActionScript helper classes that add simple remoting and Ruby/Rails style model behavior.") { |v| options[:skip_helpers] = v }
+ opt.on("--force-all",
+ "Force generation of all files. WARNING: This will overwrite any changes made to previously generated files.") { |v| options[:force_all] = v }
+ end
+
+end
+
+module RubyAMF::Quickly
+ class ActionScriptModel
+ attr_accessor :name, :properties, :package, :base_package, :ruby_class
+
+ def initialize( ar_class, root_package=nil )
+ self.name = ar_class.to_s.split(/::/).last
+ self.ruby_class = ar_class
+
+ # Determine this class' package
+ relative_package = ar_class.to_s.split(/::/)[0...-1].join('.').downcase!
+ self.package = [root_package, relative_package].compact.join('.')
+ self.base_package = [self.package, 'base'].compact.join('.')
+
+ # Build properties
+ self.properties = []
+ ar_class.columns.each do |col|
+ unless RubyAMF::Configuration::ClassMappings.ignore_fields.include? col.name
+ self.properties << ActionScriptProperty.new(col)
+ end
+ end
+
+ self.properties.sort! {|a, b| a.name <=> b.name }
+ end
+ end
+
+ class ActionScriptProperty
+ attr_accessor :name, :static_type, :accessor
+
+ def initialize( ar_column )
+ self.name = (RubyAMF::Configuration::ClassMappings.translate_case ? ar_column.name.dup.to_camel! : ar_column.name.dup)
+ self.static_type = TypeConverter.convert(ar_column)
+ self.accessor = (self.static_type == 'Boolean' && RubyAMF::Quickly::Config.prefix_booleans ? "is#{self.name.capitalize}" : self.name)
+ end
+
+ end
+
+ class TypeConverter
+ def self.convert( ar_col )
+ ruby_class, col_type = ar_col.klass, ar_col.type
+ if ruby_class == String or ruby_class < String
+ return 'String'
+ elsif ruby_class < Numeric
+ return 'Number'
+ elsif ruby_class == Object and ar_col.type == :boolean
+ return 'Boolean'
+ elsif ruby_class == Time or ruby_class == Date or ruby_class < Date or ruby_class < Time
+ return 'Date'
+ else
+ return 'Object'
+ end
+ end
+ end
+end
+
41 generators/action_script_models/templates/.svn/all-wcprops
@@ -0,0 +1,41 @@
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/!svn/ver/110/plugins/rubyamf_quickly/generators/action_script_models/templates
+END
+as3_helper_hash.erb
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/svn/!svn/ver/79/plugins/rubyamf_quickly/generators/action_script_models/templates/as3_helper_hash.erb
+END
+as3_helper_rubyamf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 105
+/svn/!svn/ver/32/plugins/rubyamf_quickly/generators/action_script_models/templates/as3_helper_rubyamf.erb
+END
+as3_base.erb
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/svn/!svn/ver/108/plugins/rubyamf_quickly/generators/action_script_models/templates/as3_base.erb
+END
+as3_model_base.erb
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/svn/!svn/ver/110/plugins/rubyamf_quickly/generators/action_script_models/templates/as3_model_base.erb
+END
+as3_helper_errors.erb
+K 25
+svn:wc:ra_dav:version-url
+V 104
+/svn/!svn/ver/75/plugins/rubyamf_quickly/generators/action_script_models/templates/as3_helper_errors.erb
+END
+as3_model.erb
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/svn/!svn/ver/73/plugins/rubyamf_quickly/generators/action_script_models/templates/as3_model.erb
+END
102 generators/action_script_models/templates/.svn/entries
@@ -0,0 +1,102 @@
+8
+
+dir
+111
+http://www.treetrunkmedia.com/svn/plugins/rubyamf_quickly/generators/action_script_models/templates
+http://www.treetrunkmedia.com/svn
+
+
+
+2008-05-27T20:11:47.203764Z
+110
+lpillow
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+975abe41-da3c-0410-88f3-9b76e4b188a3
+
+as3_helper_hash.erb
+file
+
+
+
+
+2008-07-30T17:47:08.000000Z
+1ee3dac2dcfb2de34caabea94b82a2f3
+2008-04-22T03:08:45.950664Z
+79
+lpillow
+
+as3_helper_rubyamf.erb
+file
+
+
+
+
+2008-07-30T17:47:08.000000Z
+cab249e074f1e412b28742c5edc3bb11
+2008-04-19T20:53:42.433678Z
+32
+lpillow
+
+as3_base.erb
+file
+
+
+
+
+2008-07-30T17:47:08.000000Z
+5e32d247b354f4cf85a4cf956f476b2c
+2008-05-27T19:43:20.851794Z
+108
+lpillow
+
+as3_model_base.erb
+file
+
+
+
+
+2008-07-30T17:47:08.000000Z
+15e7a9ad5f920c5ecbaa62777eca193b
+2008-05-27T20:11:47.203764Z
+110
+lpillow
+has-props
+
+as3_helper_errors.erb
+file
+
+
+
+
+2008-07-30T17:47:08.000000Z
+4a11978836c86168f508ff9127d0c60e
+2008-04-22T02:32:21.319421Z
+75
+lpillow
+
+as3_model.erb
+file
+
+
+
+
+2008-07-30T17:47:08.000000Z
+37156691b4ad01e6d174468cae1653bf
+2008-04-22T01:21:23.108672Z
+73
+lpillow
+has-props
+
1 generators/action_script_models/templates/.svn/format
@@ -0,0 +1 @@
+8
5 generators/action_script_models/templates/.svn/prop-base/as3_model.erb.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END
5 generators/action_script_models/templates/.svn/prop-base/as3_model_base.erb.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END
6 generators/action_script_models/templates/.svn/text-base/as3_base.erb.svn-base
@@ -0,0 +1,6 @@
+package <%= package %>
+{
+ public class Base
+ {
+ }
+}
124 generators/action_script_models/templates/.svn/text-base/as3_helper_errors.erb.svn-base
@@ -0,0 +1,124 @@
+package <%= package %>
+{
+ <%= RubyAMF::Configuration::ClassMappings.assume_types ? "[RemoteClass(alias='ActiveRecord::Errors')]" : '' %>
+ public dynamic class Errors
+ {
+ public static const INVALID:String = 'is invalid';
+ private static const BASE:String = 'base';
+
+ /**
+ * Adds an error message (msg) to the property, which will be returned on a call to on(property) for the same property
+ * and ensure that this error object returns false when asked if isEmpty().
+ * More than one error can be added to the same property in which case an array will be returned on a call to on(property).
+ * If no msg is supplied, "invalid" is assumed.
+ */
+ public function add(propertyName:String, msg:String=INVALID):void {
+
+ if(!this.errors[propertyName]) {
+ this.errors[propertyName] = [];
+ }
+
+ this.errors[propertyName].push(msg);
+ }
+
+ /**
+ * Adds an error to the base object instead of any particular property.
+ * This is used to report errors that don‘t tie to any specific property, but rather to the object as a whole.
+ * These error messages don‘t get prepended with any property name when iterating with forEachFull, so they should be complete sentences.
+ */
+ public function addToBase(msg:String):void {
+ add(BASE, msg);
+ }
+
+ /**
+ * Removes all errors that have been added.
+ */
+ public function clear():void {
+ this.errors = {};
+ }
+
+ /**
+ * Returns the total number of errors added. Two errors added to the same property will be counted as such.
+ */
+ public function length():int {
+ var count:int = 0;
+
+ for(var prop:String in this.errors) {
+ count += this.errors[prop].length;
+ }
+
+ return count;
+ }
+
+ /**
+ * Execute the callback function for each property and associated message.
+ *
+ * @param callback function callback(property:String, message:String):void;
+ * @param thisObject An object to use as this for the function.
+ */
+ public function forEach(callback:Function, thisObject:*=null):void {
+ for(var prop:* in this.errors) {
+ this.errors[prop].forEach( function(msg:String, i:int, arr:Array):void {
+ callback.apply(thisObject, [prop, msg]);
+ });
+ }
+ }
+
+ /**
+ * Execute the callback function fore each full error message added. So myPerson.errors.add("name", "can't be empty") will be returned through iteration as "name can't be empty".
+ *
+ * @param callback function callback(message:String):void;
+ * @param thisObject An object to use as this for the function.
+ */
+ public function forEachFull(callback:Function, thisObject:*=null):void {
+ fullMessages().forEach( function(msg:String, i:int, arr:Array):void {
+ callback.apply(thisObject, [msg]);
+ });
+ }
+
+ /**
+ * Returns all the full error messages in an Array.
+ */
+ public function fullMessages():Array {
+ var msgs:Array = [];
+
+ forEach( function(prop:String, msg:String):void {
+ if( prop == BASE )
+ msgs.push(msg);
+ else
+ msgs.push(prop + " " + msg);
+ });
+
+ return msgs;
+ }
+
+ /**
+ * Returns true if no errors have been added.
+ */
+ public function isEmpty():Boolean {
+ return length() == 0;
+ }
+
+ /**
+ * Returns true if the specified property has errors associated with it.
+ */
+ public function isInvalid(propertyName:String):Boolean {
+ return !this.errors[propertyName];
+ }
+
+ /**
+ * Returns null, if no errors are associated with the specified property.
+ * Returns an Array of error messages if any errors are associated with the specified property.
+ */
+ public function on(propertyName:String):Array {
+ return this.errors[propertyName];
+ }
+
+ /**
+ * Returns errors assigned to the base object through addToBase() according to the normal rules of on(property).
+ */
+ public function onBase():Array {
+ return on(BASE);
+ }
+ }
+}
35 generators/action_script_models/templates/.svn/text-base/as3_helper_hash.erb.svn-base
@@ -0,0 +1,35 @@
+package <%= package %>
+{
+ public dynamic class Hash
+ {
+ public function Hash(hash:Object=null) {
+ super();
+ this.merge(hash);
+ }
+
+ /**
+ * Adds the contents of other to this, overwriting entries with duplicate keys with those from other.
+ */
+ public function merge(other:Object):Hash {
+ if(other) {
+ for( var prop:* in other ) {
+ this[prop] = other[prop];
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * Delete the keys and values from the Hash.
+ * Return this Hash.
+ */
+ public function remove(...keys):Hash {
+ for(var key:* in keys) {
+ delete this[key];
+ }
+
+ return this;
+ }
+ }
+}
38 generators/action_script_models/templates/.svn/text-base/as3_helper_rubyamf.erb.svn-base
@@ -0,0 +1,38 @@
+package <%= package %>
+{
+ import mx.rpc.remoting.RemoteObject;
+ import mx.rpc.AbstractOperation;
+ import mx.rpc.AsyncToken;
+ import mx.collections.ItemResponder;
+ import flash.events.Event;
+
+ public class RubyAMF
+ {
+ private static var _controllers:Object = new Object();
+
+ public static function call( controllerClassName:String, actionName:String, params:Object, resultHandler:Function, faultHandler:Function ):void {
+ var controller:RemoteObject = controller(controllerClassName);
+ var action:AbstractOperation = controller.getOperation(actionName);
+
+ var token:AsyncToken = action.send(params);
+
+ token.addResponder( new ItemResponder(
+ function(result:Event, tkn:Object):void { if(resultHandler != null) resultHandler(result) },
+ function(fault:Event, tkn:Object):void { if(faultHandler != null) faultHandler(fault) } ));
+ }
+
+ private static function controller( controllerClassName:String ):RemoteObject {
+ var controller:RemoteObject = _controllers[controllerClassName];
+
+ if( controller == null ) {
+ controller = new RemoteObject("rubyamf");
+ controller.makeObjectsBindable = true;
+ controller.source = controllerClassName;
+ _controllers[controllerClassName] = controller;
+ }
+
+ return controller;
+ }
+
+ }
+}
11 generators/action_script_models/templates/.svn/text-base/as3_model.erb.svn-base
@@ -0,0 +1,11 @@
+package <%= as3_class.package %>
+{
+ import <%= "#{as3_class.base_package}.#{as3_class.name}Base" %>
+
+ <%= RubyAMF::Configuration::ClassMappings.assume_types ? "[RemoteClass(alias='#{as3_class.ruby_class.to_s}')]" : '' %>
+ [Bindable]
+ public class <%= as3_class.name %> extends <%= as3_class.name %>Base
+ {
+
+ }
+}
41 generators/action_script_models/templates/.svn/text-base/as3_model_base.erb.svn-base
@@ -0,0 +1,41 @@
+/*
+* WARNING: DO NOT MODIFY THIS GENERATED CLASS. ANY CHANGES WILL BE LOST.
+* ADD CUSTOM MODIFICATIONS TO <%= as3_class.name %>.as
+*/
+package <%= as3_class.base_package %>
+{
+ <% if use_helpers %>
+ import <%= "#{helper_package}.Hash;" %>
+ import <%= "#{helper_package}.Errors;" %>
+ <% end %>
+ [Bindable]
+ public class <%= as3_class.name %>Base extends Base
+ {
+ <% as3_class.properties.each {|property| %>private var _<%= property.name %>:<%= property.static_type %>;
+ <% } %>
+ <%= 'public var errors:Errors = new Errors;' if use_helpers %>
+ <% params_class = use_helpers ? 'Hash' : 'Object' %>
+ /**
+ * Create <%= use_helpers ? "a #{params_class}" : "an #{params_class}" %> representing this object's persistent properties.
+ * <% if use_helpers %>@param ...exclude any String property names that should not be included in the Hash<% end %>
+ */
+ public function toParams(<%= '...exclude' if use_helpers %>):<%= params_class %> {
+ var params:<%= params_class %> = new <%= params_class %>();
+ <% as3_class.properties.each do |property| %>
+ params['<%= property.name %>'] = this.<%= property.accessor %>;<% end %>
+
+ return params<%= '.remove(exclude)' if use_helpers %>;
+ }
+
+ <% as3_class.properties.each do |property| %>
+ // ACCESSORS: <%= property.name %>
+ public function get <%= property.accessor %>():<%= property.static_type %> {
+ return this._<%= property.name %>;
+ }
+
+ public function set <%= property.accessor %>(value:<%= property.static_type %>):void {
+ this._<%= property.name %> = value;
+ }
+ <% end %>
+ }
+}
6 generators/action_script_models/templates/as3_base.erb
@@ -0,0 +1,6 @@
+package <%= package %>
+{
+ public class Base
+ {
+ }
+}
124 generators/action_script_models/templates/as3_helper_errors.erb
@@ -0,0 +1,124 @@
+package <%= package %>
+{
+ <%= RubyAMF::Configuration::ClassMappings.assume_types ? "[RemoteClass(alias='ActiveRecord::Errors')]" : '' %>
+ public dynamic class Errors
+ {
+ public static const INVALID:String = 'is invalid';
+ private static const BASE:String = 'base';
+
+ /**
+ * Adds an error message (msg) to the property, which will be returned on a call to on(property) for the same property
+ * and ensure that this error object returns false when asked if isEmpty().
+ * More than one error can be added to the same property in which case an array will be returned on a call to on(property).
+ * If no msg is supplied, "invalid" is assumed.
+ */
+ public function add(propertyName:String, msg:String=INVALID):void {
+
+ if(!this.errors[propertyName]) {
+ this.errors[propertyName] = [];
+ }
+
+ this.errors[propertyName].push(msg);
+ }
+
+ /**
+ * Adds an error to the base object instead of any particular property.
+ * This is used to report errors that don‘t tie to any specific property, but rather to the object as a whole.
+ * These error messages don‘t get prepended with any property name when iterating with forEachFull, so they should be complete sentences.
+ */
+ public function addToBase(msg:String):void {
+ add(BASE, msg);
+ }
+
+ /**
+ * Removes all errors that have been added.
+ */
+ public function clear():void {
+ this.errors = {};
+ }
+
+ /**
+ * Returns the total number of errors added. Two errors added to the same property will be counted as such.
+ */
+ public function length():int {
+ var count:int = 0;
+
+ for(var prop:String in this.errors) {
+ count += this.errors[prop].length;
+ }
+
+ return count;
+ }
+
+ /**
+ * Execute the callback function for each property and associated message.
+ *
+ * @param callback function callback(property:String, message:String):void;
+ * @param thisObject An object to use as this for the function.
+ */
+ public function forEach(callback:Function, thisObject:*=null):void {
+ for(var prop:* in this.errors) {
+ this.errors[prop].forEach( function(msg:String, i:int, arr:Array):void {
+ callback.apply(thisObject, [prop, msg]);
+ });
+ }
+ }
+
+ /**
+ * Execute the callback function fore each full error message added. So myPerson.errors.add("name", "can't be empty") will be returned through iteration as "name can't be empty".
+ *
+ * @param callback function callback(message:String):void;
+ * @param thisObject An object to use as this for the function.
+ */
+ public function forEachFull(callback:Function, thisObject:*=null):void {
+ fullMessages().forEach( function(msg:String, i:int, arr:Array):void {
+ callback.apply(thisObject, [msg]);
+ });
+ }
+
+ /**
+ * Returns all the full error messages in an Array.
+ */
+ public function fullMessages():Array {
+ var msgs:Array = [];
+
+ forEach( function(prop:String, msg:String):void {
+ if( prop == BASE )
+ msgs.push(msg);
+ else
+ msgs.push(prop + " " + msg);
+ });
+
+ return msgs;
+ }
+
+ /**
+ * Returns true if no errors have been added.
+ */
+ public function isEmpty():Boolean {
+ return length() == 0;
+ }
+
+ /**
+ * Returns true if the specified property has errors associated with it.
+ */
+ public function isInvalid(propertyName:String):Boolean {
+ return !this.errors[propertyName];
+ }
+
+ /**
+ * Returns null, if no errors are associated with the specified property.
+ * Returns an Array of error messages if any errors are associated with the specified property.
+ */
+ public function on(propertyName:String):Array {
+ return this.errors[propertyName];
+ }
+
+ /**
+ * Returns errors assigned to the base object through addToBase() according to the normal rules of on(property).
+ */
+ public function onBase():Array {
+ return on(BASE);
+ }
+ }
+}
35 generators/action_script_models/templates/as3_helper_hash.erb
@@ -0,0 +1,35 @@
+package <%= package %>
+{
+ public dynamic class Hash
+ {
+ public function Hash(hash:Object=null) {
+ super();
+ this.merge(hash);
+ }
+
+ /**
+ * Adds the contents of other to this, overwriting entries with duplicate keys with those from other.
+ */
+ public function merge(other:Object):Hash {
+ if(other) {
+ for( var prop:* in other ) {
+ this[prop] = other[prop];
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * Delete the keys and values from the Hash.
+ * Return this Hash.
+ */
+ public function remove(...keys):Hash {
+ for(var key:* in keys) {
+ delete this[key];
+ }
+
+ return this;
+ }
+ }
+}
38 generators/action_script_models/templates/as3_helper_rubyamf.erb
@@ -0,0 +1,38 @@
+package <%= package %>
+{
+ import mx.rpc.remoting.RemoteObject;
+ import mx.rpc.AbstractOperation;
+ import mx.rpc.AsyncToken;
+ import mx.collections.ItemResponder;
+ import flash.events.Event;
+
+ public class RubyAMF
+ {
+ private static var _controllers:Object = new Object();
+
+ public static function call( controllerClassName:String, actionName:String, params:Object, resultHandler:Function, faultHandler:Function ):void {
+ var controller:RemoteObject = controller(controllerClassName);
+ var action:AbstractOperation = controller.getOperation(actionName);
+
+ var token:AsyncToken = action.send(params);
+
+ token.addResponder( new ItemResponder(
+ function(result:Event, tkn:Object):void { if(resultHandler != null) resultHandler(result) },
+ function(fault:Event, tkn:Object):void { if(faultHandler != null) faultHandler(fault) } ));
+ }
+
+ private static function controller( controllerClassName:String ):RemoteObject {
+ var controller:RemoteObject = _controllers[controllerClassName];
+
+ if( controller == null ) {
+ controller = new RemoteObject("rubyamf");
+ controller.makeObjectsBindable = true;
+ controller.source = controllerClassName;
+ _controllers[controllerClassName] = controller;
+ }
+
+ return controller;
+ }
+
+ }
+}
11 generators/action_script_models/templates/as3_model.erb
@@ -0,0 +1,11 @@
+package <%= as3_class.package %>
+{
+ import <%= "#{as3_class.base_package}.#{as3_class.name}Base" %>
+
+ <%= RubyAMF::Configuration::ClassMappings.assume_types ? "[RemoteClass(alias='#{as3_class.ruby_class.to_s}')]" : '' %>
+ [Bindable]
+ public class <%= as3_class.name %> extends <%= as3_class.name %>Base
+ {
+
+ }
+}
41 generators/action_script_models/templates/as3_model_base.erb
@@ -0,0 +1,41 @@
+/*
+* WARNING: DO NOT MODIFY THIS GENERATED CLASS. ANY CHANGES WILL BE LOST.
+* ADD CUSTOM MODIFICATIONS TO <%= as3_class.name %>.as
+*/
+package <%= as3_class.base_package %>
+{
+ <% if use_helpers %>
+ import <%= "#{helper_package}.Hash;" %>
+ import <%= "#{helper_package}.Errors;" %>
+ <% end %>
+ [Bindable]
+ public class <%= as3_class.name %>Base extends Base
+ {
+ <% as3_class.properties.each {|property| %>private var _<%= property.name %>:<%= property.static_type %>;
+ <% } %>
+ <%= 'public var errors:Errors = new Errors;' if use_helpers %>
+ <% params_class = use_helpers ? 'Hash' : 'Object' %>
+ /**
+ * Create <%= use_helpers ? "a #{params_class}" : "an #{params_class}" %> representing this object's persistent properties.
+ * <% if use_helpers %>@param ...exclude any String property names that should not be included in the Hash<% end %>
+ */
+ public function toParams(<%= '...exclude' if use_helpers %>):<%= params_class %> {
+ var params:<%= params_class %> = new <%= params_class %>();
+ <% as3_class.properties.each do |property| %>
+ params['<%= property.name %>'] = this.<%= property.accessor %>;<% end %>
+
+ return params<%= '.remove(exclude)' if use_helpers %>;
+ }
+
+ <% as3_class.properties.each do |property| %>
+ // ACCESSORS: <%= property.name %>
+ public function get <%= property.accessor %>():<%= property.static_type %> {
+ return this._<%= property.name %>;
+ }
+
+ public function set <%= property.accessor %>(value:<%= property.static_type %>):void {
+ this._<%= property.name %> = value;
+ }
+ <% end %>
+ }
+}
9 init.rb
@@ -0,0 +1,9 @@
+require File.join('app', 'controllers', 'application')
+require 'rubyamf_quickly'
+
+# Include the filter methods
+ActionController::Base.send(:include, RubyAMF::Quickly::Filters)
+
+# Add the filters to ApplicationController
+ApplicationController.before_filter( :prepare_amf_params ) if RubyAMF::Quickly::Config.stuff_params
+ApplicationController.rescue_from( Exception, :with => :amf_exception_handler ) if RubyAMF::Quickly::Config.convert_unhandled_exceptions
85 install.rb
@@ -0,0 +1,85 @@
+
+begin
+ # Make sure RubyAMF is installed.
+ rubyamf_plugin = File.join( RAILS_ROOT, 'vendor', 'plugins', 'rubyamf' )
+ raise 'RubyAMF not installed' unless File.exists?(rubyamf_plugin)
+
+ # Add the quickly configuration to rubyamf_config.rb
+ add_quickly_config = true
+ rubyamf_config = File.join( RAILS_ROOT, 'config', 'rubyamf_config.rb')
+ File.open( rubyamf_config, 'r') do |config|
+ while line = config.gets
+ add_quickly_config = false if line =~ /RubyAMF::Quickly::Config/
+ end
+ end
+
+ if add_quickly_config
+ quickly_config =
+<<-CONFIG
+
+
+# ==============================
+# => RubyAMF::Quickly::Config <=
+# ==============================
+ require 'rubyamf_quickly'
+ # => ACTIONSCRIPT GENERATION CONFIGURATION
+
+ # The ./script/generate action_script_models script will generate an ActionScript class for every concrete ActiveRecord model
+ # in the RAILS_ROOT/app/models directory.
+
+ #=> Where do you want to generate ActionScript classes?
+ # Defaults to Peter Armstrong's suggested RAILS_ROOT/app/flex
+ # RubyAMF::Quickly::Config.relative_flex_root = 'app/flex'
+
+ #=> What package should your generated ActionScript classes belong to?
+ # Defaults to no package so all ActionScript classes will be generated to RubyAMF::Quickly.relative_flex_root
+ # If you specified a value of 'org.mypackage.models' and defaulted the RubyAMF::Quickly.relative_flex_root, then all would
+ # be generated to RAILS_ROOT/app/flex/org/mypacket/models. Any namespaced ActiveRecord models will be added to sub-packages.
+ # RubyAMF::Quickly::Config.action_script_package = nil
+
+ #=> What, if any ActiveRecord models should NOT have corresponding ActionScript classes generated?
+ # RubyAMF::Quickly::Config.ignore_classes = [ 'Person', 'User', 'Address' ]
+
+ #=> Prefix ActionScript boolean types with 'is'?
+ # Defaults to true so generated ActionScript classes will follow ActionScript coding style.
+ # RubyAMF::Quickly::Config.prefix_booleans = true
+
+ # => CONTROLLERS; THE BEFORE AND AFTER
+
+ #=> Stuff Params Hash
+ # If set to true, then RubyAMF::Quickly expects the first RubyAMF request parameter (rubyamf_params[0]) to be a hash and will merge
+ # it into the params hash for conventional Rails params access. No need for conditional is_amf controller logic.
+ # RubyAMF::Quickly::Config.stuff_params = true
+
+ #=> Convert unhandled Exceptions to FaultEvents
+ # If set to true, then all unhandled Ruby Exceptions will be rescued, converted to and rendered as a RubyAMF FaultObject to trigger
+ # an ActionScript fault handler with the FaultEvent's fault.message set to the rescued exception's message.
+ # RubyAMF::Quickly::Config.convert_unhandled_exceptions = true
+
+ # => QUICK OPINIONS
+ # The following overrides some of the above RubyAMF::Configuration settings to get things going in the most natural Rails and Flex way.
+
+ #=> Case Translations
+ # Translate the case so ActionScript model properties follow ActionScript coding style.
+ RubyAMF::Configuration::ClassMappings.translate_case = true
+
+ #=> Assume Class Types
+ # Skip mappings. The RubyAMF::Quickly action_script_models generator creates the RemoteObject declarations.
+ RubyAMF::Configuration::ClassMappings.assume_types = true
+
+ #=> Don't Put Remoting Parameters into the "params" hash
+ # Let RubyAMF::Quickly stuff the params for you with only the attributes you need.
+ # You may want to set it back to true if you've overridden the default RubyAMF::Quickly::Config.stuff_params to false
+ RubyAMF::Configuration::ParameterMappings.always_add_to_params = false
+CONFIG
+
+ File.open( rubyamf_config, 'a' ) do |config|
+ config.puts ""
+ config.puts quickly_config
+ end
+ end
+
+rescue Exception => e
+ puts "ERROR INSTALLING RubyAMF::Quickly - #{e.message}"
+end
+
41 lib/rubyamf_quickly.rb
@@ -0,0 +1,41 @@
+require 'active_support'
+
+module RubyAMF
+ module Quickly
+
+ module Config
+ # DESIGN TIME
+ mattr_accessor :relative_flex_root
+ mattr_accessor :action_script_package
+ mattr_accessor :ignore_classes
+ mattr_accessor :prefix_booleans
+
+ @@relative_flex_root = 'app/flex'
+ @@action_script_package = nil
+ @@ignore_classes = []
+ @@prefix_booleans = true
+
+ # RUNTIME
+ mattr_accessor :convert_unhandled_exceptions
+ mattr_accessor :stuff_params
+
+ @@convert_unhandled_exceptions = true;
+ @@stuff_params = true;
+ end
+
+ module Filters
+ # If the first parameter of the incoming params/rubyamf_params is a hash, then merge them into the params hash
+ def prepare_amf_params
+ if is_amf
+ params_src = RubyAMF::Configuration::ParameterMappings.always_add_to_params ? params : rubyamf_params
+ params.merge! params_src[0] if params_src.is_a?(Hash)
+ end
+ end
+
+ # Convert any unhandled exception to an AMF FaultObject so it triggers a FaultEvent
+ def amf_exception_handler(ex)
+ render :amf => FaultObject.new(ex.to_s) if is_amf
+ end
+ end
+ end
+end
4 tasks/rubyamf_quickly_tasks.rake
@@ -0,0 +1,4 @@
+# desc "Explaining what the task does"
+# task :rubyamf_quickly do
+# # Task goes here
+# end
8 test/rubyamf_quickly_test.rb
@@ -0,0 +1,8 @@
+require 'test/unit'
+
+class RubyamfQuicklyTest < Test::Unit::TestCase
+ # Replace this with your real tests.
+ def test_this_plugin
+ flunk
+ end
+end
1 uninstall.rb
@@ -0,0 +1 @@
+# Uninstall hook code here

0 comments on commit fc8432b

Please sign in to comment.