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.
- data/app/Rakefile +4 -0
- data/app/configurations/default.rb.erb +8 -0
- data/app/configurations/development.rb.erb +22 -0
- data/app/configurations/mapping.rb.erb +49 -0
- data/app/configurations/production.rb.erb +25 -0
- data/app/controllers/default.rb.erb +39 -0
- data/app/doc/EMTPY +0 -0
- data/app/helpers/default.rb.erb +13 -0
- data/app/lib/application.rb.erb +52 -0
- data/app/lib/startup.rb.erb +2 -0
- data/app/lib/tasks/cluster.rb +26 -0
- data/app/lib/tasks/schema.rb +28 -0
- data/app/models/default.rb.erb +13 -0
- data/app/schema/migration/templates/empty.rb.erb +9 -0
- data/app/templates/errors/not_found.mab +2 -0
- data/app/templates/errors/server_error.mab +2 -0
- data/app/templates/layouts/default.mab +14 -0
- data/app/views/default.rb.erb +13 -0
- data/bin/waves +32 -0
- data/bin/waves-console +8 -0
- data/bin/waves-server +45 -0
- data/lib/controllers/mixin.rb +62 -0
- data/lib/dispatchers/base.rb +41 -0
- data/lib/dispatchers/default.rb +33 -0
- data/lib/helpers/common.rb +22 -0
- data/lib/helpers/form.rb +22 -0
- data/lib/helpers/formatting.rb +22 -0
- data/lib/helpers/model.rb +15 -0
- data/lib/helpers/view.rb +14 -0
- data/lib/renderers/erubis.rb +38 -0
- data/lib/renderers/markaby.rb +31 -0
- data/lib/renderers/mixin.rb +41 -0
- data/lib/runtime/application.rb +43 -0
- data/lib/runtime/configuration.rb +47 -0
- data/lib/runtime/console.rb +21 -0
- data/lib/runtime/logger.rb +28 -0
- data/lib/runtime/mapping.rb +82 -0
- data/lib/runtime/mime_types.rb +18 -0
- data/lib/runtime/request.rb +43 -0
- data/lib/runtime/response.rb +26 -0
- data/lib/runtime/response_mixin.rb +53 -0
- data/lib/runtime/response_proxy.rb +29 -0
- data/lib/runtime/server.rb +58 -0
- data/lib/runtime/session.rb +43 -0
- data/lib/utilities/integer.rb +8 -0
- data/lib/utilities/kernel.rb +8 -0
- data/lib/utilities/module.rb +7 -0
- data/lib/utilities/object.rb +13 -0
- data/lib/utilities/string.rb +36 -0
- data/lib/utilities/symbol.rb +5 -0
- data/lib/views/mixin.rb +54 -0
- data/lib/waves.rb +50 -0
- 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
|
data/lib/helpers/form.rb
ADDED
@@ -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
|
data/lib/helpers/view.rb
ADDED
@@ -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
|
+
|