waves 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. data/app/Rakefile +4 -0
  2. data/app/configurations/default.rb.erb +8 -0
  3. data/app/configurations/development.rb.erb +22 -0
  4. data/app/configurations/mapping.rb.erb +49 -0
  5. data/app/configurations/production.rb.erb +25 -0
  6. data/app/controllers/default.rb.erb +39 -0
  7. data/app/doc/EMTPY +0 -0
  8. data/app/helpers/default.rb.erb +13 -0
  9. data/app/lib/application.rb.erb +52 -0
  10. data/app/lib/startup.rb.erb +2 -0
  11. data/app/lib/tasks/cluster.rb +26 -0
  12. data/app/lib/tasks/schema.rb +28 -0
  13. data/app/models/default.rb.erb +13 -0
  14. data/app/schema/migration/templates/empty.rb.erb +9 -0
  15. data/app/templates/errors/not_found.mab +2 -0
  16. data/app/templates/errors/server_error.mab +2 -0
  17. data/app/templates/layouts/default.mab +14 -0
  18. data/app/views/default.rb.erb +13 -0
  19. data/bin/waves +32 -0
  20. data/bin/waves-console +8 -0
  21. data/bin/waves-server +45 -0
  22. data/lib/controllers/mixin.rb +62 -0
  23. data/lib/dispatchers/base.rb +41 -0
  24. data/lib/dispatchers/default.rb +33 -0
  25. data/lib/helpers/common.rb +22 -0
  26. data/lib/helpers/form.rb +22 -0
  27. data/lib/helpers/formatting.rb +22 -0
  28. data/lib/helpers/model.rb +15 -0
  29. data/lib/helpers/view.rb +14 -0
  30. data/lib/renderers/erubis.rb +38 -0
  31. data/lib/renderers/markaby.rb +31 -0
  32. data/lib/renderers/mixin.rb +41 -0
  33. data/lib/runtime/application.rb +43 -0
  34. data/lib/runtime/configuration.rb +47 -0
  35. data/lib/runtime/console.rb +21 -0
  36. data/lib/runtime/logger.rb +28 -0
  37. data/lib/runtime/mapping.rb +82 -0
  38. data/lib/runtime/mime_types.rb +18 -0
  39. data/lib/runtime/request.rb +43 -0
  40. data/lib/runtime/response.rb +26 -0
  41. data/lib/runtime/response_mixin.rb +53 -0
  42. data/lib/runtime/response_proxy.rb +29 -0
  43. data/lib/runtime/server.rb +58 -0
  44. data/lib/runtime/session.rb +43 -0
  45. data/lib/utilities/integer.rb +8 -0
  46. data/lib/utilities/kernel.rb +8 -0
  47. data/lib/utilities/module.rb +7 -0
  48. data/lib/utilities/object.rb +13 -0
  49. data/lib/utilities/string.rb +36 -0
  50. data/lib/utilities/symbol.rb +5 -0
  51. data/lib/views/mixin.rb +54 -0
  52. data/lib/waves.rb +50 -0
  53. metadata +189 -0
@@ -0,0 +1,62 @@
1
+ module Waves
2
+
3
+ module Controllers
4
+
5
+ module Mixin
6
+
7
+ attr_reader :request
8
+
9
+ include Waves::ResponseMixin
10
+
11
+ def self.included( c )
12
+ def c.process( request, &block )
13
+ self.new( request ).instance_eval( &block )
14
+ end
15
+ end
16
+
17
+ def initialize( request )
18
+ @request = request
19
+ end
20
+
21
+
22
+ # override to convert 'foo.bar' to 'foo' => 'bar' => value
23
+ def params
24
+ @params ||= destructure(request.params)
25
+ end
26
+
27
+ def model_name
28
+ self.class.basename.snake_case
29
+ end
30
+
31
+ def model
32
+ Waves.application.models[ model_name.intern ]
33
+ end
34
+
35
+ private
36
+
37
+ def destructure(hash)
38
+ rval = {}
39
+ hash.keys.map{ |key|key.split('.') }.each do |keys|
40
+ destructure_with_array_keys(hash,'',keys,rval)
41
+ end
42
+ rval
43
+ end
44
+
45
+ def destructure_with_array_keys(hash,prefix,keys,rval)
46
+ if keys.length == 1
47
+ val = hash[prefix+keys.first]
48
+ rval[keys.first.intern] = case val
49
+ when String then val.strip
50
+ when Hash then val
51
+ end
52
+ else
53
+ rval = ( rval[keys.first.intern] ||= {} )
54
+ destructure_with_array_keys(hash,(keys.shift<<'.'),keys,rval)
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,41 @@
1
+ module Waves
2
+
3
+ module Dispatchers
4
+
5
+ class NotFoundError < Exception ; end
6
+
7
+ class Redirect < Exception
8
+ attr_reader :path
9
+ def initialize( path )
10
+ @path = path
11
+ end
12
+ end
13
+
14
+ class Base
15
+
16
+ def call( env )
17
+ Waves::Server.synchronize do
18
+ request = Waves::Request.new( env )
19
+ response = request.response
20
+ begin
21
+ safe( request )
22
+ rescue Dispatchers::Redirect => redirect
23
+ response.status = '302'
24
+ response.location = redirect.path
25
+ rescue Dispatchers::NotFoundError => e
26
+ html = Waves.application.views[:errors].process( request ) do
27
+ not_found_404( :error => e )
28
+ end
29
+ response.status = '404'
30
+ response.content_type = 'text/html'
31
+ response.write( html )
32
+ end
33
+ response.finish
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,33 @@
1
+ module Waves
2
+
3
+ module Dispatchers
4
+
5
+ class Default < Base
6
+
7
+ def safe( request )
8
+
9
+ response = request.response
10
+
11
+ Waves::Server.reset if Waves::Server.debug?
12
+ response.content_type = Waves::Server.config.mime_types[ request.path ] || 'text/html'
13
+
14
+ mapping = Waves::Server.mapping[ request ]
15
+
16
+ mapping[:before].each do | block, args |
17
+ ResponseProxy.new(request).instance_exec(*args,&block)
18
+ end
19
+
20
+ block, args = mapping[:action]
21
+ response.write( ResponseProxy.new(request).instance_exec(*args, &block) )
22
+
23
+ mapping[:after].each do | block, args |
24
+ ResponseProxy.new(request).instance_exec(*args,&block)
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,22 @@
1
+ module Waves
2
+ module Helpers
3
+ module Common
4
+
5
+ def layout( name, assigns = {}, &block )
6
+ assigns[ :content ] = yield
7
+ Blog::Views::Layouts.process( request ) do
8
+ send( name, assigns )
9
+ end
10
+ end
11
+
12
+ def doctype(type)
13
+ case type
14
+ when :html4_strict
15
+ '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" ' <<
16
+ '"http://www.w3.org/TR/html4/strict.dtd">'
17
+ end
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module Waves
2
+
3
+ module Helpers
4
+
5
+ module Form
6
+
7
+ def properties(&block)
8
+ div.properties do
9
+ yield
10
+ end
11
+ end
12
+
13
+ def property( options )
14
+ self << view( :form, options[:type], options )
15
+ end
16
+
17
+
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'redcloth'
2
+ module Waves
3
+ module Helpers
4
+ module Formatting
5
+
6
+ # TODO: this won't work inside a erb template!
7
+ # but i hate to do a whole new Builder when I'm
8
+ # already inside one! test self === Builder?
9
+ def mab( content )
10
+ eval content
11
+ end
12
+
13
+ def textile( content )
14
+ ( ::RedCloth::TEXTILE_TAGS << [ 96.chr, '&8216;'] ).each do |pat,ent|
15
+ content.gsub!( pat, ent.gsub('&','&#') )
16
+ end
17
+ ::RedCloth.new( content ).to_html
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ module Waves
2
+ module Helpers
3
+ module Model
4
+
5
+ def all( model )
6
+ Application.models[ model ].all( domain )
7
+ end
8
+
9
+ def find( model, name )
10
+ Application.models[ model ].find( domain, name ) rescue nil
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ module Waves
2
+ module Helpers
3
+ module View
4
+
5
+ def view( model, view, assigns = {} )
6
+ self << Application.views[ model ].process( request ) do
7
+ send view, assigns
8
+ end
9
+ end
10
+
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,38 @@
1
+ require 'erubis'
2
+
3
+ module Erubis
4
+
5
+ class Context
6
+ def <<(s) ; s ; end
7
+ end
8
+
9
+ end
10
+
11
+ module Waves
12
+
13
+ module Renderers
14
+
15
+ class Erubis
16
+
17
+ include Renderers::Mixin
18
+
19
+ extension :erb
20
+
21
+ def self.render( path, assigns )
22
+ eruby = ::Erubis::Eruby.new( template( path ) )
23
+ helper = helper( path )
24
+ context = ::Erubis::Context.new
25
+ context.meta_eval { include( helper ) ; }
26
+ context.instance_eval do
27
+ assigns.each do |key,val|
28
+ instance_variable_set("@#{key}",val)
29
+ end
30
+ end
31
+ eruby.evaluate( context )
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,31 @@
1
+ require 'markaby'
2
+
3
+ ::Markaby::Builder.set( :indent, 2 )
4
+
5
+ module Waves
6
+
7
+ module Renderers
8
+
9
+ class Markaby
10
+
11
+ include Renderers::Mixin
12
+
13
+ extension :mab
14
+ # capture needed here for content fragments, otherwise
15
+ # you'll just get the last tag's output ...
16
+ def self.capture( template )
17
+ "capture { #{template} }"
18
+ end
19
+
20
+ def self.render( path, assigns )
21
+ builder = ::Markaby::Builder.new( assigns )
22
+ helper = helper( path )
23
+ builder.meta_eval { include( helper ) }
24
+ builder.instance_eval( capture( template( path ) ) ).to_s
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,41 @@
1
+ module Waves
2
+
3
+ module Renderers
4
+
5
+ extend Autoload
6
+ autoload :renderers
7
+
8
+ module Mixin
9
+
10
+ def self.included(target)
11
+ class << target
12
+
13
+ def extension(*args)
14
+ return @extension if args.length == 0
15
+ @extension = args.first
16
+ end
17
+
18
+ def filename(path)
19
+ :templates / "#{path}.#{self.extension}"
20
+ end
21
+
22
+ def render(path,args=nil)
23
+ end
24
+
25
+ def template( path )
26
+ File.read( filename( path ) )
27
+ end
28
+
29
+ def helper( path )
30
+ Waves.application.helpers[
31
+ File.basename( File.dirname( path ) ).camel_case ]
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,43 @@
1
+ module Waves
2
+
3
+ class << self
4
+
5
+ attr_reader :application
6
+
7
+ # give us the root namespace for the application
8
+ def << ( app )
9
+ @application = app if Module === app
10
+ end
11
+
12
+ end
13
+
14
+ class Application
15
+
16
+ def initialize( mode = :development )
17
+ @mode = mode
18
+ end
19
+
20
+ def debug? ; @mode == :development ; end
21
+
22
+ # now we can get the configuration, based on the mode
23
+ # we must specify global scope to avoid picking up Waves::Configurations::*
24
+ # and / or Waves::Application::* ... because the configuration may be
25
+ # loaded via autoload ....
26
+ def config
27
+ Waves.application.configurations[ @mode ]
28
+ end
29
+
30
+ # and, similarly, the url mapping ...
31
+ def mapping
32
+ Waves.application.configurations[ :mapping ]
33
+ end
34
+
35
+ # the config then tells us whether to unload any namespaces
36
+ # after each request ...
37
+ def reset
38
+ config.reloadable.each { |mod| mod.reload }
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,47 @@
1
+ module Waves
2
+
3
+ module Configurations
4
+
5
+ class Base
6
+
7
+ def self.[]=( name, val )
8
+ meta_def("_#{name}") { val }
9
+ end
10
+
11
+ def self.[]( name ) ; send "_#{name}" ; end
12
+
13
+ def self.attribute( name )
14
+ meta_def(name) do |*args|
15
+ raise ArgumentError.new('Too many arguments.') if args.length > 1
16
+ args.length == 1 ? self[ name ] = args.first : self[ name ]
17
+ end
18
+ self[ name ] = nil
19
+ end
20
+
21
+ def self.mime_types
22
+ Waves::MimeTypes
23
+ end
24
+
25
+ end
26
+
27
+ class Default < Base
28
+
29
+ %w( host port ports log reloadable server database session ).
30
+ each { |name| attribute(name) }
31
+
32
+ def self.application( &block )
33
+ if block_given?
34
+ self['application'] = Rack::Builder.new( &block )
35
+ else
36
+ self['application']
37
+ end
38
+ end
39
+
40
+ session :duration => 30.minutes,
41
+ :path => :tmp / :sessions
42
+
43
+ end
44
+ end
45
+ end
46
+
47
+