public
Rubygem
Description: Resource-oriented open source Ruby framework for Web apps.
Homepage: http://rubywaves.com/
Clone URL: git://github.com/dyoder/waves.git
Finished initial implementation of new mappings, including filters, 
resources, the whole shabang.
dyoder (author)
Sun Jun 29 17:22:50 -0700 2008
automatthew (committer)
Tue Jul 01 07:06:50 -0700 2008
commit  9c6decd5c5d4935854c3a9063fed23e06a3adc91
tree    b33fd2da06e6902da2c98dbd9e7ec5329e59b561
parent  3097fbef54f940ff997ce394677e194794e2f4f6
...
16
17
18
 
 
 
19
20
21
...
16
17
18
19
20
21
22
23
24
0
@@ -16,6 +16,9 @@ module Waves
0
         @path = path
0
         @status = status
0
       end
0
+ def message
0
+ "location: #{@path} status: #{@status}"
0
+ end
0
     end
0
 
0
     # Waves::Dispatchers::Base provides the basic request processing structure.
...
37
38
39
40
 
41
42
43
44
45
46
47
 
 
48
49
50
51
 
 
 
52
53
54
55
 
56
57
58
...
37
38
39
 
40
41
 
 
 
 
 
 
42
43
44
45
46
 
47
48
49
50
51
52
 
53
54
55
56
0
@@ -37,22 +37,20 @@ module Waves
0
 
0
         begin
0
 
0
- request.not_found unless mapping[ :action ]
0
+ request.not_found if mapping[ :action ].empty?
0
           mapping[ :before ].each { | action | action.call( request ) }
0
-
0
- begin
0
- response.write( mapping[ :action ].first.call( request ) )
0
- ensure
0
- mapping[ :after ].each { | action | action.call( request ) }
0
- end
0
+ response.write( mapping[ :action ].first.call( request ) )
0
+ mapping[ :after ].each { | action | action.call( request ) }
0
           
0
         rescue Exception => e
0
 
0
- raise e unless Waves.mapping.handle( e )
0
+ Waves::Logger.info e.to_s
0
+ handler = mapping[ :handle ].find { | action | action.exception === e }
0
+ ( handler.call( request ) if handler ) or raise e
0
 
0
         ensure
0
 
0
- mapping[:always].each do | action |
0
+ mapping[ :always ].each do | action |
0
             begin
0
               action.call( request )
0
             rescue Exception => e
...
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
 
 
21
22
23
24
25
26
27
28
 
 
 
 
 
29
30
31
32
33
 
 
 
 
 
 
 
 
 
 
34
35
36
37
 
38
39
40
...
47
48
49
50
 
51
52
 
 
 
53
54
55
...
4
5
6
 
 
7
8
9
10
11
 
 
 
 
 
 
 
12
13
14
15
16
17
18
19
20
 
 
21
22
23
24
25
26
27
28
 
 
29
30
31
32
33
34
35
36
37
38
39
40
41
 
42
43
44
45
...
52
53
54
 
55
56
57
58
59
60
61
62
63
0
@@ -4,37 +4,42 @@ module Waves
0
     
0
     class Action
0
       
0
- # TODO: Make this more generic and able to support Handler (or push add'l code into Handler).
0
- # Should support anonymous blocks (i.e. that don't call a method on Resource), or cases where
0
       # no path was provided. Should also always use :path rather than relying on target (this is
0
       # actually code in patter), and add code for :scheme, :domain, etc. constraints (Constraints).
0
       #
0
       # Can some o the resource determination related code be factored out of there or simplified?
0
       
0
- attr_reader :name, :resource, :pattern, :constraints, :descriptors
0
-
0
- def initialize( options, &block )
0
- @name = name = options[:name]
0
- @pattern = pattern = Pattern.new( options )
0
- @constraints = Constraints.new( options )
0
- @descriptors = Descriptors.new( options )
0
+ def initialize( options )
0
+ @name = name = options[:name] ; @pattern = pattern = Pattern.new( options )
0
+ @constraints = Constraints.new( options ) ; @descriptors = Descriptors.new( options )
0
         if rname = options[ :resource ]
0
           @resource = resource = Waves.application[:resources][ rname ]
0
         else
0
           resource = Waves.application[:resources][ :default ]
0
           @resource = Waves::Resources::Proxy
0
         end
0
- resource.instance_eval { define_method name, &block } if name and block_given?
0
- resource::Paths.instance_eval { define_method( name ) { |*args| generate( options[ :pattern ], args ) } }
0
+ if name
0
+ block = options[:block]
0
+ resource.instance_eval { define_method( name, &block ) } if block
0
+ resource::Paths.instance_eval { define_method( name ) { |*args| generate( options[ :path ], args ) } }
0
+ end
0
       end
0
       
0
       def bind( request )
0
- ( constraints.satisfy?( request ) and
0
- ( params = pattern.match( request ) ) and Binding.new( self, params ) )
0
+ ( @constraints.satisfy?( request ) and
0
+ ( params = @pattern.match( request ) ) and Binding.new( self, params ) )
0
+ end
0
+
0
+ def call( request )
0
+ if @name
0
+ @resource.new( request ).send( @name )
0
+ elsif @block
0
+ @resource.new( request ).instance_eval( &@block )
0
+ end
0
       end
0
 
0
       def threaded?
0
- descriptors.threaded?
0
+ @descriptors.threaded?
0
       end
0
       
0
     end
0
@@ -47,9 +52,12 @@ module Waves
0
       
0
       def call( request )
0
         request.params.merge!( @params )
0
- @action.resource.new( request ).send( @action.name )
0
+ @action.call( request )
0
       end
0
     
0
+ def method_missing(name,*args,&block)
0
+ @action.respond_to?( name ) ? @action.send( name, *args, &block ) : super
0
+ end
0
     end
0
     
0
   end
...
4
5
6
7
8
9
10
11
 
12
13
14
15
16
17
18
19
20
21
22
 
23
24
 
25
26
27
...
4
5
6
 
 
 
 
 
7
8
9
10
11
 
12
13
14
15
16
 
17
18
 
19
20
21
22
0
@@ -4,24 +4,19 @@ module Waves
0
     
0
     class Constraints
0
       
0
- # TODO: Add other header methods here ...
0
- # may include some shortcuts for accessing Rack vars also
0
- METHODS = %w( method accept ).map( &:intern )
0
-
0
- attr_accessor *METHODS
0
+ METHODS = %w( domain scheme method accept ).map( &:intern )
0
       
0
       def initialize( options )
0
         METHODS.each do | method |
0
           instance_variable_set( "@#{method}", options[ method ] ) if options[ method ]
0
- send( "#{method}=", options[ method ] ) if options[ method ]
0
         end
0
       end
0
       
0
       def satisfy?( request )
0
         METHODS.all? do | method |
0
- wanted = self.send( method )
0
+ wanted = instance_variable_get( "@#{method}")
0
           got = request.send( method ) if wanted
0
- wanted == got
0
+ wanted === got
0
         end
0
       end
0
             
...
7
8
9
10
11
 
 
12
 
 
13
14
15
...
7
8
9
 
 
10
11
12
13
14
15
16
17
0
@@ -7,9 +7,11 @@ module Waves
0
       attr_reader :exception
0
       
0
       def initialize( e, options )
0
- @exception = e
0
- super
0
+ @exception = e ; options[:resource] ||= 'error'
0
+ super( options )
0
       end
0
+
0
+ end
0
     
0
   end
0
 
...
5
6
7
8
 
9
10
11
12
 
13
14
15
16
 
 
17
18
19
20
21
22
23
24
25
 
26
27
28
 
29
30
31
32
 
33
34
35
36
 
 
 
 
 
37
38
39
 
 
 
40
41
 
 
42
43
44
45
46
 
47
48
49
50
51
52
53
54
 
55
56
57
...
5
6
7
 
8
9
 
 
 
10
11
12
13
 
14
15
16
17
18
19
20
21
 
 
 
22
23
24
 
25
26
27
28
 
29
30
31
 
 
32
33
34
35
36
37
 
 
38
39
40
41
 
42
43
44
45
46
47
 
48
49
50
51
52
 
 
 
 
53
54
55
56
0
@@ -5,53 +5,52 @@ module Waves
0
     include Functor::Method
0
     
0
     METHODS = %w( get put post delete ).map( &:intern )
0
- RULES = %w( before action after always, handle ).map( &:intern )
0
+ RULES = %w( before action after always handle ).map( &:intern )
0
     
0
- def mappings
0
- @mappings ||= Hash.new { |h,k| h[k] = [] }
0
- end
0
+ def mappings ; @mappings ||= Hash.new { |h,k| h[k] = [] } ; end
0
     
0
     def method_missing( name, *args, &block )
0
       return super unless RULES.include? name
0
- map( name, args, &block )
0
+ args << block if block_given?
0
+ mappings[ name ] << map( *args )
0
     end
0
     
0
     def with( options, &block )
0
       @options = options; yield if block_given? ; @options = nil
0
     end
0
 
0
- functor( :map, String, Array, Proc ) { | rule, args, block | map( *( args << block ) ) }
0
- functor( :map, String, Array ) { | rule, args | mappings[ rule ] << map( *args ) }
0
- functor( :map, String, Hash, Proc ) do | name, options, block |
0
+ functor( :map, Symbol, Hash, Proc ) do | name, options, block |
0
       options[:name] = name ; options[:block] = block ; map( options )
0
     end
0
- functor( :map, String, Hash ) { | name, options | options[:name] = name ; map( options ) }
0
+ functor( :map, Symbol, Hash ) { | name, options | options[:name] = name ; map( options ) }
0
     functor( :map, Hash ) do | options |
0
       options = ( @options || {} ).merge( options )
0
       options[ :method ] = method = METHODS.find { |method| options[ method ] }
0
- options[ :pattern ] = options[ method ]
0
+ options[ :path ] = options[ method ]
0
       Action.new( options )
0
     end
0
- functor( :map, Exception, String, Hash, Proc ) do | e, name, options, block |
0
- options[:name] = name ; map( e, options, block )
0
+
0
+ exception = lambda { | klass | klass.ancestors.include?( Exception ) if klass.is_a?( Class ) }
0
+
0
+ functor( :map, exception, String, Hash, Proc ) do | e, name, options, block |
0
+ options[ :name ] = name ; map( e, options, block )
0
     end
0
- functor( :map, Exception, Hash, Proc ) do | e, options, block |
0
- options[:block] = block ; map( e, options )
0
+
0
+ functor( :map, exception, Hash, Proc ) do | e, options, block |
0
+ options[ :block ] = block ; map( e, options )
0
     end
0
- functor( :map, Exception, Hash ) { | options, block | Handler.new( e, options ) }
0
+ functor( :map, exception, Proc ) { | e, block | map( e, { :block => block } ) }
0
+ functor( :map, exception, Hash ) { | e, options | Handler.new( e, options ) }
0
         
0
     def []( request )
0
       returning Hash.new { |h,k| h[k] = [] } do | results |
0
         RULES.each do | rule |
0
- mappings[ rule ].each { | action | binding = action.bind( request ) and results[ rule ].push( binding ) }
0
+ mappings[ rule ].each { | action | ( binding = action.bind( request ) ) and results[ rule ].push( binding ) }
0
         end
0
       end
0
     end
0
 
0
- private
0
-
0
- def normalize( options )
0
- end
0
+ private :map
0
     
0
   end
0
 
...
18
19
20
21
 
22
23
24
...
18
19
20
 
21
22
23
24
0
@@ -18,7 +18,7 @@ module Waves
0
       functor( :generate, Symbol, Symbol ) { | key, val | val.to_s }
0
       functor( :generate, Symbol, String ) { | key, val | val }
0
 
0
- functor( :generate, Regexp, Array ) { | key, vals | nil }
0
+ functor( :generate, Regexp, Array ) { | key, vals | generate( key, vals.shift ) }
0
 
0
       functor( :generate, Hash, Array ) { | h, vals | vals.shift or h.values.first }
0
       
...
8
9
10
11
12
13
14
 
15
16
 
 
17
18
19
20
21
 
22
23
24
...
8
9
10
 
 
 
 
11
12
 
13
14
15
16
 
 
 
17
18
19
20
0
@@ -8,17 +8,13 @@ module Waves
0
       
0
       include Functor::Method
0
       
0
- def initialize( options )
0
- @target = options[ :target ]
0
- @pattern = options[ :pattern ]
0
- end
0
+ def initialize( options ) ; @pattern = options[ :path ] ; end
0
       
0
- functor( :match, Waves::Request ) { | request | match( @pattern, request.send( @target ) ) }
0
+ functor( :match, Waves::Request ) { | request | match( @pattern, request.path ) }
0
+ functor( :match, nil, String ) { |patern, path| {} }
0
       functor( :match, Array, String ) { | pattern, path | match( pattern, path.split('/')[1..-1] ) }
0
       functor( :match, Array, Array ) do | wants, gots |
0
- r = {}; matches = wants.all? do | want |
0
- match( r, want, gots.shift )
0
- end
0
+ r = {}; matches = wants.all? { | want | match( r, want, gots.shift ) }
0
         r if matches and gots.empty?
0
       end
0
       functor( :match, Hash, String, String ) { | r, want, got | got if want == got }
...
9
10
11
 
12
13
14
...
24
25
26
27
28
29
30
31
...
56
57
58
 
 
59
60
61
62
63
64
...
9
10
11
12
13
14
15
...
25
26
27
 
 
28
29
30
...
55
56
57
58
59
60
61
 
62
63
64
0
@@ -9,6 +9,7 @@ require 'daemons'
0
 require 'live_console'
0
 
0
 require 'autocode'
0
+gem 'dyoder-functor'
0
 require 'functor'
0
 
0
 # for mimetypes only or when using as default handler
0
@@ -24,8 +25,6 @@ require 'benchmark'
0
 # require 'memcache'
0
 require 'base64'
0
 
0
-require 'functor'
0
-
0
 # selected project-specific extensions
0
 require 'utilities/module'
0
 require 'utilities/string'
0
@@ -56,9 +55,10 @@ require 'runtime/configuration'
0
 # waves URI mapping
0
 require 'mapping/mapping'
0
 require 'mapping/action'
0
+require 'mapping/handler'
0
+require 'mapping/pattern'
0
 require 'mapping/constraints'
0
 require 'mapping/descriptors'
0
-require 'mapping/pattern'
0
 require 'mapping/paths'
0
 require 'resources/mixin'
0
 require 'resources/proxy'
...
7
8
9
10
 
11
12
13
14
15
16
17
18
19
 
 
 
 
 
20
21
22
...
7
8
9
 
10
11
12
13
14
 
 
 
 
 
15
16
17
18
19
20
21
22
0
@@ -7,16 +7,16 @@ module Blog
0
       extend Waves::Mapping
0
       
0
       # specific to comments - on create redirect to the entry, not the comment itself
0
- path :create, :resource => :comment, :post => [ '/comments' ] do
0
+ action :create, :resource => :comment, :post => [ '/comments' ] do
0
         redirect( Blog::Resources::Entries.paths.read( action( :create ).entry.name ) )
0
       end
0
       
0
       # defaults for generic resources
0
- path( :list, :get => [ :resources ] ) { action( :all ) and render( :list ) }
0
- path( :create, :post => [ :resources ] ) { redirect( paths.read( action( :create ).name, 'edit' ) ) }
0
- path( :read, :get => [ :resource, :name, { :mode => 'show' } ] ) { action( :find, name ) and render( mode ) }
0
- path( :update, :put => [ :resource, :name ] ) { action( :update, name ) and redirect( paths.read( name ) ) }
0
- path( :delete, :delete => [ :resource, :name ] ) { action( :delete, name ) }
0
+ action( :list, :get => [ :resources ] ) { action( :all ) and render( :list ) }
0
+ action( :create, :post => [ :resources ] ) { redirect( paths.read( action( :create ).name, 'edit' ) ) }
0
+ action( :read, :get => [ :resource, :name, { :mode => 'show' } ] ) { action( :find, name ) and render( mode ) }
0
+ action( :update, :put => [ :resource, :name ] ) { action( :update, name ) and redirect( paths.read( name ) ) }
0
+ action( :delete, :delete => [ :resource, :name ] ) { action( :delete, name ) }
0
       
0
     end
0
 

Comments

    No one has commented yet.