GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Rubygem
Description: Resource-oriented open source Ruby framework for Web apps.
Homepage: http://rubywaves.com/
Clone URL: git://github.com/dyoder/waves.git
Working version of new mappings, albeit somewhat buggy.
dyoder (author)
Sun Jun 22 02:20:14 -0700 2008
automatthew (committer)
Tue Jul 01 07:00:10 -0700 2008
commit  445d9d86095e63f8936b0c96b7ed2bda807adbc7
tree    898ea7932a66d997b4e66c1bad1db626863267f0
parent  38baa870e7a019bb0e9807bf0fdb7bbb5e319231
...
48
49
50
 
 
 
 
 
 
 
 
 
 
 
51
52
53
...
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
0
@@ -48,6 +48,17 @@ module Waves
0
           auto_load true, :directories => [ :helpers ]
0
         end
0
 
0
+ app.auto_eval :Resources do
0
+ const_set( :Default, Class.new( Waves::Resources::Base ) ).module_eval do
0
+ def __c ; @controller ||= controllers[ resource ].process( @request ) { self } ; end
0
+ def __v ; @view ||= views[ resource ].process( @request ) { self } ; end
0
+ def action( method, *args ) ; @data = __c.send( method, *args ) ; end
0
+ def render( method ) ; puts "RENDER: #{resource}"; __v.send( method, ( @data.kind_of?( Enumerable ) ? resources : resource ) => @data ) ; end
0
+ def method_missing( name, *args, &block) ; params[ name ] ; end
0
+ end
0
+ auto_create_class true, self::Default
0
+ end
0
+
0
       end
0
     end
0
   end
...
29
30
31
 
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 
 
 
48
 
49
50
51
...
29
30
31
32
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
35
36
37
38
39
40
41
0
@@ -29,23 +29,13 @@ module Waves
0
           auto_eval :Mapping do
0
             extend Waves::Mapping
0
           end
0
+ end
0
           
0
- auto_create_module( :Resources ) do
0
- include AutoCode
0
- auto_create_class true, Waves::Resources::Base do
0
- def resource ; self.class.name ; end
0
- def resources ; resource.plural ; end
0
- def controller ; @controller ||= controllers[ resource ].process( @request ) { self } ; end
0
- def view ; @view ||= views[ resource ].process( @request ) { self } ; end
0
- def render( method ) ; view.send( method, ( @data.kind_of? Enumerable ? resources : resource ) => @data ) ; end
0
- def redirect( path ) ; request.redirect( path ) ; end
0
- def method_missing( name, *args, &block) ; @data = controller.send( name, *args, &block ) ; end
0
- # have to define this explicitly for now because for some reason sequel defines it on Object ...
0
- def all ; method_missing( :all ) ; end
0
- end
0
- end
0
-
0
+ app.auto_create_module( :Resources ) do
0
+ include AutoCode
0
+ auto_create_class true, Waves::Resources::Base
0
         end
0
+
0
       end
0
     end
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
28
29
30
31
 
 
32
33
34
...
41
42
43
44
 
45
 
46
47
 
48
49
50
 
51
...
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
...
40
41
42
 
43
44
45
46
 
47
48
49
 
50
51
0
@@ -4,31 +4,30 @@ module Waves
0
     
0
     class Action
0
       
0
- attr_accessor :name, :resource, :pattern, :constraints, :descriptors
0
+ attr_reader :name, :resource, :pattern, :constraints, :descriptors
0
       
0
       def initialize( options, &block )
0
- name = options[:name]
0
- pattern = Pattern.new( options )
0
- matcher = Constraints.new( options )
0
- descriptors = Descriptors.new( options )
0
- resource = Waves.application[:resources][ options[:resource] ]
0
- resource.instance_eval{ define_method name, &block } if block_given?
0
+ @name = name = options[:name]
0
+ @pattern = pattern = Pattern.new( options )
0
+ @constraints = Constraints.new( options )
0
+ @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 { meta_def name, &pattern.generator }
0
       end
0
       
0
- # how / when can i take the results of the pattern match
0
- # and merge them with the request params ... can't do it here
0
- # because a number of actions may be run, but I can't store
0
- # it as state because actions are shared between requests
0
- def call?( request )
0
- constraints.satisfy?( request ) and pattern.match( request )
0
+ def bind( request )
0
+ ( constraints.satisfy?( request ) and
0
+ ( params = pattern.match( request ) ) and Binding.new( self, params ) )
0
       end
0
       
0
- def call( request )
0
- resource.new( request ).send( name )
0
- end
0
-
0
- def method_missing( name, *args )
0
- descriptors.send( name, *args )
0
+ def threaded?
0
+ descriptors.threaded?
0
       end
0
       
0
     end
0
@@ -41,10 +40,11 @@ module Waves
0
       
0
       def call( request )
0
         request.params.merge!( @params )
0
- @action.call( request )
0
+ @action.resource.new( request ).send( @action.name )
0
       end
0
+
0
     end
0
-
0
+
0
   end
0
 
0
-end
0
+end
0
\ No newline at end of file
...
6
7
8
9
 
10
11
12
13
14
15
 
 
 
16
17
18
19
20
21
22
23
 
 
 
 
24
25
26
...
6
7
8
 
9
10
11
12
13
 
 
14
15
16
17
18
19
20
 
 
 
 
21
22
23
24
25
26
27
0
@@ -6,21 +6,22 @@ module Waves
0
       
0
       # TODO: Add other header methods here ...
0
       # may include some shortcuts for accessing Rack vars also
0
- METHODS = %w( method accepts ).map( &:intern )
0
+ METHODS = %w( method accept ).map( &:intern )
0
       
0
       attr_accessor *METHODS
0
       
0
       def initialize( options )
0
- METHODS.each do |method|
0
- send( "#{method}=", options[method] ) if options[method]
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 = send( method )
0
- got = request.send( method )
0
- wanted == got if wanted == got
0
+ METHODS.all? do | method |
0
+ wanted = self.send( method )
0
+ got = request.send( method ) if wanted
0
+ wanted == got
0
         end
0
       end
0
             
...
3
4
5
6
 
7
8
9
...
3
4
5
 
6
7
8
9
0
@@ -3,7 +3,7 @@ module Waves
0
   module Mapping
0
     
0
     class Descriptors
0
-
0
+
0
       def initialize( options )
0
         @threaded = options[ :threaded ]
0
       end
...
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
58
59
60
...
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
58
59
60
0
@@ -5,55 +5,55 @@ module Waves
0
     METHODS = %w( get put post delete ).map( &:intern )
0
     RULES = %w( before action after always ).map( &:intern )
0
     
0
- def method_missing( name, *args, &block )
0
- mappings[ name ].push( map( *args, &block ) )
0
+ def mappings
0
+ @mappings ||= Hash.new { |h,k| h[k] = [] }
0
+ end
0
+
0
+ def before( options, &block )
0
     end
0
     
0
     def wrap( name, *args, &block )
0
       before( name, *args, &block ) ; after( name, *args, &block )
0
     end
0
+
0
+ def after( options, &block )
0
+ end
0
+
0
+ def always( options, &block )
0
+ end
0
+
0
+ def handle( exception )
0
+ end
0
+
0
     
0
     def with( options, &block )
0
       @options = options; yield if block_given? ; @options = nil
0
     end
0
 
0
     def path( name, options = {}, &block )
0
- mappings[ :action ] = map( options.merge!( :name => name, :target => :path ), &block )
0
+ map( options.merge!( :name => name, :target => :path ), &block )
0
     end
0
     
0
     def url( name, options = {}, &block )
0
- mappings[ :action ] = map( options.merge!( :name => name, :target => :url ), &block )
0
+ map( options.merge!( :name => name, :target => :url ), &block )
0
     end
0
     
0
- def map( *args, &block )
0
- options = ( @options || {} ).merge( normalize( *args ) )
0
+ def map( options, &block )
0
+ options = ( @options || {} ).merge( options )
0
       options[ :target ] ||= :path
0
       options[ :method ] = method = METHODS.find { |method| options[ method ] }
0
       options[ :pattern ] = options[ method ]
0
- Action.new( options, &block )
0
+ mappings[ :action ].push( Action.new( options, &block ) )
0
     end
0
     
0
     def []( request )
0
- results = {} ; RULES.each do | rule |
0
- results[ rule ] = mappings[ rule ].select do | action |
0
- ( params = action.call?( request ) ) and Action::Binding.new( action, params )
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
         end
0
       end
0
- return results
0
     end
0
-
0
- private
0
-
0
- def mappings; @mappings ||= {}; end
0
-
0
- include Functor::Method
0
-
0
- functor( :normalize, Symbol, Hash ) { | name, options | options.merge!( :name => name ) }
0
- functor( :normalize, String, Hash ) { | pattern, options | options.merge!( :pattern => pattern ) }
0
- functor( :normalize, Regexp, Hash ) { | regexp, options | options.merge!( :pattern => regexp ) }
0
- functor( :normalize, Exception ) { | exception | { :exception => exception } }
0
- functor( :normalize, Hash ) { | options | options }
0
-
0
+
0
   end
0
 
0
 end
0
\ No newline at end of file
...
 
 
1
2
3
...
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
...
1
2
3
4
5
...
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
0
@@ -1,3 +1,5 @@
0
+require 'generator'
0
+
0
 module Waves
0
 
0
   module Mapping
0
@@ -6,27 +8,36 @@ module Waves
0
       
0
       include Functor::Method
0
       
0
- attr_accessor :target, :pattern
0
+ attr_accessor :target, :pattern, :generator
0
+
0
       def initialize( options )
0
         @keys = [] ; @target = options[ :target ]
0
- @pattern = compile( options[ :pattern ] )
0
+ compile( options[ :pattern ] )
0
       end
0
       
0
       def match( request )
0
- return false unless m = pattern.match( request.send( target ) )
0
- params = [] ; @keys.zip( m ) { | key, val | r[ key ] = val } ; params
0
+ return false unless m = @pattern.match( request.send( target ) )
0
+ returning( Hash.new ) { | r | @keys.zip( m[1..-1] ) { | k, v | r[ k ] = v } }
0
       end
0
       
0
       private
0
       
0
- functor( :compile, Regexp ) { |pattern| pattern }
0
-
0
- functor( :compile, String ) do | pattern |
0
- pattern = Regexp.escape( pattern ).gsub!( /<([\w\_\-\\]+)>/ ) { |match| @keys << match ; "(#{ match })" }
0
- "^#{pattern}/?$"
0
+ functor( :compile, Array ) do | path |
0
+ @generator = lambda { |*args| self.instance_eval { generate( path, args ) } }
0
+ @pattern = Regexp.new( path.map { |component| compile( component ) }.join('/') )
0
       end
0
       
0
-
0
+ functor( :compile, String ) { |s| Regexp.escape( s ) }
0
+ functor( :compile, Regexp ) { |re| s }
0
+ functor( :compile, Symbol ) { |sy| @keys << sy.to_s ; '([\w\_\-\#]+)' }
0
+
0
+ functor( :generate, Array, Array ) { | keys, vals | keys.map { |key| generate( key, vals ) }.join('/') }
0
+ functor( :generate, :resource, Array ) { | key, vals | resource }
0
+ functor( :generate, :resources, Array ) { | key, vals | resources }
0
+ functor( :generate, Symbol, Array ) { | key, vals | generate( key, vals.shift ) }
0
+ functor( :generate, Symbol, Symbol ) { | key, val | val }
0
+ functor( :generate, Regexp, Array ) { | key, vals | raise ArgumentError.new( "Can't generate a path from Regexp." ) }
0
+
0
     end
0
 
0
   end
...
7
8
9
10
11
 
 
 
 
 
 
 
 
 
 
12
13
14
15
16
 
17
18
19
...
7
8
9
 
 
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
24
25
26
27
0
@@ -7,13 +7,21 @@ module Waves
0
       attr_reader :request
0
 
0
       include ResponseMixin
0
-
0
- def initialize(request); @request = request; end
0
+
0
+ def self.included( target )
0
+ def target.paths ; @paths ||= Object.new ; end
0
+ end
0
+
0
+ def initialize(request); @request = request ; end
0
+ def resource ; self.class.basename.downcase ; end
0
+ def resources ; resource.plural ; end
0
+ def redirect( path ) ; request.redirect( path ) ; end
0
+ def paths ; self.class.paths ; end
0
       
0
     end
0
       
0
     # :)
0
- const_set( :Base, Class.new ).module_eval { include Mixin }
0
+ const_set( :Base, Class.new ).module_eval { include Mixin }
0
 
0
   end
0
 
...
19
20
21
22
23
 
 
 
 
24
25
26
...
38
39
40
41
 
42
43
44
45
46
47
 
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 
 
64
65
66
...
19
20
21
 
 
22
23
24
25
26
27
28
...
40
41
42
 
43
44
 
 
 
 
 
45
46
47
48
49
50
51
 
 
 
 
 
 
 
 
 
 
52
53
54
55
56
0
@@ -19,8 +19,10 @@ module Waves
0
 
0
     # Accessor not explicitly defined by Waves::Request are delegated to Rack::Request.
0
     # Check the Rack documentation for more information.
0
- def method_missing(name,*args)
0
- @request.send(name,*args)
0
+ def method_missing( name, *args )
0
+ ( ( @request.respond_to?( name ) and @request.send( name,*args ) ) or
0
+ ( args.empty? and ( @request.env[ "HTTP_#{name.to_s.upcase}" ] or
0
+ @request.env[ "rack.#{name.to_s.downcase}" ] ) ) or super )
0
     end
0
 
0
     # The request path (PATH_INFO). Ex: +/entry/2008-01-17+
0
@@ -38,29 +40,17 @@ module Waves
0
       @request.env['CONTENT_TYPE']
0
     end
0
 
0
- # Supported request methods
0
+ # Request method predicates, defined in terms of #method.
0
     METHODS = %w{get post put delete head options trace}
0
-
0
- # Override the Rack methods for querying the request method.
0
- METHODS.each do |method|
0
- class_eval "def #{method}?; method == :#{method} end"
0
- end
0
+ METHODS.each { |m| define_method( m ) { method == m } }
0
 
0
     # The request method. Because browsers can't send PUT or DELETE
0
     # requests this can be simulated by sending a POST with a hidden
0
     # field named '_method' and a value with 'PUT' or 'DELETE'. Also
0
     # accepted is when a query parameter named '_method' is provided.
0
     def method
0
- @method ||= begin
0
- request_method = @request.request_method.downcase
0
- if request_method == 'post'
0
- _method = @request['_method']
0
- _method.downcase! if _method
0
- METHODS.include?(_method) ? _method.intern : :post
0
- else
0
- request_method.intern
0
- end
0
- end
0
+ @method ||= ( ( ( m = @request.request_method.downcase ) == 'post' and
0
+ ( n = @request['_method'] ) ) ? n.downcase : m ).intern
0
     end
0
 
0
     # Raise a not found exception.
...
1
 
 
 
 
2
3
 
4
5
6
7
 
 
 
 
8
9
10
...
23
24
25
26
 
27
28
29
30
31
32
33
34
35
 
 
36
37
38
...
41
42
43
 
 
 
 
44
45
46
47
...
1
2
3
4
5
6
 
7
8
9
10
11
12
13
14
15
16
17
18
...
31
32
33
 
34
35
36
37
 
 
 
 
 
 
38
39
40
41
42
...
45
46
47
48
49
50
51
52
53
54
55
0
@@ -1,10 +1,18 @@
0
 module Attributes
0
+
0
+ def initialize(hash = {} )
0
+ attributes = hash
0
+ end
0
   
0
- def initialize(hash={})
0
+ def attributes=( hash )
0
    # copy the hash, converting all keys to strings
0
     @attrs = hash.inject({}) { |h,p| k,v = p; h[k.to_s] = v; h }
0
   end
0
   
0
+ def attributes
0
+ @attrs ||= {}
0
+ end
0
+
0
   def method_missing(name,*args)
0
    name = name.to_s
0
     if name =~/=$/ and args.length == 1
0
@@ -23,16 +31,12 @@ module Attributes
0
   end
0
   
0
   def set(name, val)
0
- @attrs[name.to_s] = val
0
+ attributes[name.to_s] = val
0
   end
0
   
0
   def get(name)
0
- rval = ( @attrs[name.to_s] )
0
- if Hash === rval
0
- Attributes.new(rval)
0
- else
0
- rval
0
- end
0
+ rval = attributes[name.to_s]
0
+ rval.is_a?( Hash ) ? Attributes.new( rval ) : rval
0
   end
0
   
0
   def to_h
0
@@ -41,6 +45,10 @@ module Attributes
0
   
0
   alias_method :to_hash, :to_h
0
   
0
+ class Object
0
+ include Attributes
0
+ end
0
+
0
 end
0
   
0
   
0
\ No newline at end of file
...
7
8
9
 
10
11
12
...
23
24
25
 
 
26
27
28
...
53
54
55
 
56
57
58
 
 
 
 
 
59
 
60
61
62
...
7
8
9
10
11
12
13
...
24
25
26
27
28
29
30
31
...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
0
@@ -7,6 +7,7 @@ WAVES = "#{File.dirname(__FILE__)}/.." unless defined?(WAVES)
0
 require 'rack'
0
 require 'daemons'
0
 require 'live_console'
0
+
0
 require 'autocode'
0
 require 'functor'
0
 
0
@@ -23,6 +24,8 @@ 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
@@ -53,10 +56,17 @@ require 'runtime/configuration'
0
 # waves URI mapping
0
 require 'mapping/mapping'
0
 require 'mapping/action'
0
+<<<<<<< HEAD:lib/waves.rb
0
 require 'mapping/pattern'
0
 require 'mapping/constraints'
0
 require 'mapping/descriptors'
0
+=======
0
+require 'mapping/constraints'
0
+require 'mapping/descriptors'
0
+require 'mapping/pattern'
0
+>>>>>>> Working version of new mappings, albeit somewhat buggy.:lib/waves.rb
0
 require 'resources/mixin'
0
+require 'resources/proxy'
0
 
0
 # waves mvc support
0
 require 'controllers/mixin'
...
7
8
9
10
11
 
 
12
13
14
15
16
17
18
19
20
 
 
 
 
 
 
21
22
23
24
25
26
 
27
...
7
8
9
 
 
10
11
12
13
14
 
 
 
 
 
 
15
16
17
18
19
20
21
22
23
24
25
 
26
27
0
@@ -7,20 +7,20 @@ 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
- instance = create and redirect( Blog::Resources::Entries.path.show( instance.entry.name ) )
0
+ path :create, :resource => :comment, :post => [ :comments ] do
0
+ redirect( Blog::Resources::Entries.paths.show( action( :create ).entry.name ) )
0
       end
0
       
0
       # defaults for generic resources
0
- path :list, :get => '/<resources>' { all and render( :list ) }
0
- path :show, :get => '/<resource>/<name>' { find( params[:name] ) and render( :show ) }
0
- path :edit, :get => '/<resource>/<name>/editor' { find( params[:name] ) and render( :editor ) }
0
- path :create, :post => '/<resources>' { instance = create and redirect( path.editor( instance.name ) ) }
0
- path :update, :post => '/<resource>/<name>' { update( params[:name] ) and redirect( path.show( params[:name] ) ) }
0
- path :delete, :delete => '/<resource><name>' { delete( params[:name] ) }
0
+ path( :list, :get => [ :resources ] ) { action( :all ) and render( :list ) }
0
+ path( :show, :get => [ :resource, :name ] ) { action( :find, name ) and render( :show ) }
0
+ path( :edit, :get => [ :resource, :name, :view ] ) { action( :find, name ) and render( view ) }
0
+ path( :create, :post => [ :resources ] ) { redirect( paths.edit( action( :create ).name ) ) }
0
+ path( :update, :post => [ :resource, :name ] ) { action( :update, name ) and redirect( paths.show( name ) ) }
0
+ path( :delete, :delete => [ :resource, :name ] ) { action( :delete, name ) }
0
       
0
     end
0
 
0
   end
0
 
0
-end
0
+end
0
\ No newline at end of file

Comments

    No one has commented yet.