waves 0.6.7 → 0.6.9
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 +1 -1
- data/app/configurations/default.rb.erb +1 -1
- data/app/configurations/mapping.rb.erb +6 -37
- data/app/controllers/default.rb.erb +10 -20
- data/app/lib/tasks/cluster.rb +8 -10
- data/app/lib/tasks/generate.rb +15 -0
- data/app/lib/tasks/schema.rb +6 -5
- data/app/schema/{migration → migrations}/templates/empty.rb.erb +0 -0
- data/app/templates/errors/{not_found.mab → not_found_404.mab} +0 -0
- data/app/templates/errors/{server_error.mab → server_error_500.mab} +0 -0
- data/app/templates/layouts/default.mab +1 -1
- data/bin/waves +1 -1
- data/bin/waves-console +21 -4
- data/lib/controllers/mixin.rb +85 -16
- data/lib/dispatchers/base.rb +26 -15
- data/lib/dispatchers/default.rb +25 -4
- data/lib/helpers/common.rb +50 -10
- data/lib/helpers/form.rb +18 -1
- data/lib/helpers/formatting.rb +17 -9
- data/lib/helpers/model.rb +20 -2
- data/lib/helpers/view.rb +12 -2
- data/lib/mapping/mapping.rb +187 -0
- data/lib/mapping/pretty_urls.rb +95 -0
- data/lib/renderers/erubis.rb +3 -1
- data/lib/renderers/markaby.rb +6 -4
- data/lib/renderers/mixin.rb +12 -0
- data/lib/runtime/application.rb +33 -23
- data/lib/runtime/configuration.rb +131 -9
- data/lib/runtime/console.rb +2 -2
- data/lib/runtime/logger.rb +42 -18
- data/lib/runtime/mime_types.rb +8 -4
- data/lib/runtime/request.rb +14 -5
- data/lib/runtime/response.rb +15 -1
- data/lib/runtime/response_mixin.rb +29 -47
- data/lib/runtime/server.rb +60 -35
- data/lib/runtime/session.rb +14 -1
- data/lib/utilities/integer.rb +7 -1
- data/lib/utilities/kernel.rb +28 -2
- data/lib/utilities/module.rb +3 -0
- data/lib/utilities/object.rb +5 -1
- data/lib/utilities/string.rb +7 -2
- data/lib/utilities/symbol.rb +2 -0
- data/lib/views/mixin.rb +55 -1
- data/lib/waves.rb +9 -2
- metadata +10 -8
- data/lib/runtime/mapping.rb +0 -82
data/lib/renderers/erubis.rb
CHANGED
@@ -2,6 +2,8 @@ require 'erubis'
|
|
2
2
|
|
3
3
|
module Erubis
|
4
4
|
|
5
|
+
# This is added to the Erubis Content class to allow the same helper methods
|
6
|
+
# to be used with both Markaby and Erubis.
|
5
7
|
class Context
|
6
8
|
def <<(s) ; s ; end
|
7
9
|
end
|
@@ -11,7 +13,7 @@ end
|
|
11
13
|
module Waves
|
12
14
|
|
13
15
|
module Renderers
|
14
|
-
|
16
|
+
|
15
17
|
class Erubis
|
16
18
|
|
17
19
|
include Renderers::Mixin
|
data/lib/renderers/markaby.rb
CHANGED
@@ -11,17 +11,19 @@ module Waves
|
|
11
11
|
include Renderers::Mixin
|
12
12
|
|
13
13
|
extension :mab
|
14
|
+
|
14
15
|
# capture needed here for content fragments, otherwise
|
15
16
|
# you'll just get the last tag's output ...
|
16
|
-
def self.capture( template )
|
17
|
-
|
18
|
-
end
|
17
|
+
# def self.capture( template )
|
18
|
+
# "capture { #{template} }"
|
19
|
+
# end
|
19
20
|
|
20
21
|
def self.render( path, assigns )
|
21
22
|
builder = ::Markaby::Builder.new( assigns )
|
22
23
|
helper = helper( path )
|
23
24
|
builder.meta_eval { include( helper ) }
|
24
|
-
builder.instance_eval(
|
25
|
+
builder.instance_eval( template( path ) )
|
26
|
+
builder.to_s
|
25
27
|
end
|
26
28
|
|
27
29
|
end
|
data/lib/renderers/mixin.rb
CHANGED
@@ -5,8 +5,20 @@ module Waves
|
|
5
5
|
extend Autoload
|
6
6
|
autoload :renderers
|
7
7
|
|
8
|
+
# The renderers mixin provides a number of methods to simplify writing new renderers.
|
9
|
+
# Just include this in your Renderer class and write your render method.
|
8
10
|
module Mixin
|
9
11
|
|
12
|
+
# Adds the following methods to the target class:
|
13
|
+
#
|
14
|
+
# - extension: allows you to set or get the extension used by this renderer.
|
15
|
+
#
|
16
|
+
# Renderers::Markaby.extension 'foo' # tell Waves to use .foo as Markaby extension
|
17
|
+
#
|
18
|
+
# - filename: generate a filename for the template based on a logical path.
|
19
|
+
# - template: read the template from the file corresponding to the given logical path.
|
20
|
+
# - helper: return a helper module that corresponds to the given logical path.
|
21
|
+
#
|
10
22
|
def self.included(target)
|
11
23
|
class << target
|
12
24
|
|
data/lib/runtime/application.rb
CHANGED
@@ -1,43 +1,53 @@
|
|
1
|
+
# See the README for an overview.
|
1
2
|
module Waves
|
2
3
|
|
3
4
|
class << self
|
4
5
|
|
6
|
+
# Access the principal Waves application.
|
5
7
|
attr_reader :application
|
6
8
|
|
7
|
-
#
|
9
|
+
# Register a module as a Waves application.
|
10
|
+
# Also, initialize the database connection if necessary.
|
8
11
|
def << ( app )
|
9
|
-
|
12
|
+
@application = app if Module === app
|
13
|
+
app.database if app.respond_to? 'database'
|
10
14
|
end
|
11
15
|
|
12
16
|
end
|
13
17
|
|
18
|
+
# An application in Waves is anything that provides access to the Waves
|
19
|
+
# runtime and the registered Waves applications. This includes both
|
20
|
+
# Waves::Server and Waves::Console. Waves::Application is *not* the actual
|
21
|
+
# application module(s) registered as Waves applications. To access the
|
22
|
+
# main Waves application, you can use +Waves+.+application+.
|
14
23
|
class Application
|
15
|
-
|
16
|
-
def initialize( mode = :development )
|
17
|
-
@mode = mode
|
18
|
-
end
|
19
|
-
|
20
|
-
def debug? ; @mode == :development ; end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
# and / or Waves::Application::* ... because the configuration may be
|
25
|
-
# loaded via autoload ....
|
26
|
-
def config
|
27
|
-
Waves.application.configurations[ @mode ]
|
28
|
-
end
|
25
|
+
# Accessor for options passed to the application. Valid options include
|
26
|
+
attr_reader :options
|
29
27
|
|
30
|
-
#
|
31
|
-
def
|
32
|
-
|
28
|
+
# Create a new Waves application instance.
|
29
|
+
def initialize( options={} )
|
30
|
+
@options = options
|
31
|
+
Dir.chdir options[:directory] if options[:directory]
|
33
32
|
end
|
34
33
|
|
35
|
-
# the
|
36
|
-
|
37
|
-
def reset
|
38
|
-
config.reloadable.each { |mod| mod.reload }
|
39
|
-
end
|
34
|
+
# The 'mode' of the application determines which configuration it will run under.
|
35
|
+
def mode ; @mode ||= @options[:mode]||:development ; end
|
40
36
|
|
37
|
+
# Debug is true if debug is set to true in the current configuration.
|
38
|
+
def debug? ; config.debug ; end
|
39
|
+
|
40
|
+
# Access the current configuration. *Example:* +Waves::Server.config+
|
41
|
+
def config ; Waves.application.configurations[ mode ] ; end
|
42
|
+
|
43
|
+
# Access the mappings for the application.
|
44
|
+
def mapping ; Waves.application.configurations[ :mapping ] ; end
|
45
|
+
|
46
|
+
# Reload the modules specified in the current configuration.
|
47
|
+
def reload ; config.reloadable.each { |mod| mod.reload } ; end
|
48
|
+
|
49
|
+
# Returns the cache set for the current configuration
|
50
|
+
def cache ; config.cache ; end
|
41
51
|
end
|
42
52
|
|
43
53
|
end
|
@@ -1,15 +1,131 @@
|
|
1
1
|
module Waves
|
2
|
+
|
3
|
+
# Waves configurations are simply Ruby code, meaning you can use an Ruby expression as
|
4
|
+
# a value for a configuration parameter, extend and inherit your configurations, and
|
5
|
+
# add your own configuration attributes. You can even use it as a configuration repository
|
6
|
+
# for your applications.
|
7
|
+
#
|
8
|
+
# The form for configuration parameters to use the parameter name as a method name. Passing
|
9
|
+
# in a parameter sets the value.
|
10
|
+
#
|
11
|
+
# == Example
|
12
|
+
#
|
13
|
+
# module Blog
|
14
|
+
# module Configurations
|
15
|
+
# class Development < Default
|
16
|
+
# host '127.0.0.1'
|
17
|
+
# port 2000
|
18
|
+
# reloadable [ Blog ]
|
19
|
+
# log :level => :debug
|
20
|
+
# application do
|
21
|
+
# use Rack::ShowExceptions
|
22
|
+
# run Waves::Dispatchers::Default.new
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# There are three forms for accessing parameters:
|
29
|
+
#
|
30
|
+
# Waves.config.port # generic form - gets current config
|
31
|
+
# Blog.configurations[:development] # gets a value for a specific config
|
32
|
+
# Blog::Configurations::Development.port # Access config constant directly
|
33
|
+
#
|
34
|
+
# You can inherit configurations, as is shown in the example above. Typically, you
|
35
|
+
# can use the application's "default" configuration to set shared configurations,
|
36
|
+
# and then inherit from it for specific variations.
|
37
|
+
#
|
38
|
+
# To define your own attributes, and still make them inheritable, you should use
|
39
|
+
# the +attribute+ class method, like this:
|
40
|
+
#
|
41
|
+
# class Default < Waves::Configurations::Default
|
42
|
+
# attribute 'theme' # define a theme attribute
|
43
|
+
# theme 'ultra' # give it a default
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# There are a number of reserved or built-in attributes. These are:
|
47
|
+
#
|
48
|
+
# - application: configure the application for use with Rack
|
49
|
+
# - database: takes a hash of parameters used to initalize the database; see below
|
50
|
+
# - reloadable: an array of module names to reload; see below for more
|
51
|
+
# - log: takes a hash of parameters; see below for more
|
52
|
+
# - host: the host to bind the server to (string)
|
53
|
+
# - port: the port for the server to listen on (number)
|
54
|
+
# - ports: used by the cluster:start task for clustering servers (array of numbers)
|
55
|
+
# - debug: true if running in "debug" mode, which automatically reloads code
|
56
|
+
#
|
57
|
+
# == Configuring The Rack Application
|
58
|
+
#
|
59
|
+
# One of the really nice features of Rack is the ability to install "middleware"
|
60
|
+
# components to optimize the way you handle requests. Waves exposes this ability
|
61
|
+
# directly to the application developer via the +application+ configuration parameter.
|
62
|
+
#
|
63
|
+
# *Example*
|
64
|
+
#
|
65
|
+
# # Typical debugging configuration
|
66
|
+
# application do
|
67
|
+
# use Rack::ShowExceptions
|
68
|
+
# run Waves::Dispatchers::Default.new
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# == Configuring Database Access
|
72
|
+
#
|
73
|
+
# The database parameter takes a hash with the following elements:
|
74
|
+
#
|
75
|
+
# - host: which host the database is running on
|
76
|
+
# - adapter: which adapter is being used to access the database (mysql, postgres, etc.)
|
77
|
+
# - database: the name of the database the application is connecting to
|
78
|
+
# - user: the user for authentication
|
79
|
+
# - password: password for authentication
|
80
|
+
#
|
81
|
+
# *Example*
|
82
|
+
#
|
83
|
+
# database :host => host, :adapter => 'mysql', :database => 'blog',
|
84
|
+
# :user => 'root', :password => 'guess'
|
85
|
+
#
|
86
|
+
#
|
87
|
+
# == Configuring Code Reloading
|
88
|
+
#
|
89
|
+
# You can specify a list of modules to reload on each request using the +reloadable+
|
90
|
+
# configuration parameter. The Waves server will call +reload+ on each module to trigger
|
91
|
+
# the reloading. Typically, your modules will use the Autocode gem to set parameters for
|
92
|
+
# reloading. This is done for you when you generate an application using the +waves+
|
93
|
+
# command, but you can change the default settings. See the documentation for Autocode
|
94
|
+
# for more information. Typically, you will set this parameter to just include your
|
95
|
+
# main application:
|
96
|
+
#
|
97
|
+
# reloadable [ Blog ]
|
98
|
+
#
|
99
|
+
# although you could do this with several modules just as easily (say, your primary
|
100
|
+
# application and several helper applications).
|
101
|
+
#
|
102
|
+
# == Configuring Logging
|
103
|
+
#
|
104
|
+
# The +log+ configuration parameter takes the following options (as a hash):
|
105
|
+
# - level: The level to filter logging at. Uses Ruby's built in Logger class.
|
106
|
+
# - output: A filename or IO object. Should be a filename if running as a daemon.
|
107
|
+
#
|
108
|
+
# *Examples*
|
109
|
+
#
|
110
|
+
# log :level => :info, :output => $stderr
|
111
|
+
# log :level => :error, :output => 'log/blog.log'
|
112
|
+
#
|
2
113
|
|
3
114
|
module Configurations
|
4
115
|
|
5
116
|
class Base
|
6
117
|
|
118
|
+
# Set the given attribute with the given value. Typically, you wouldn't
|
119
|
+
# use this directly.
|
7
120
|
def self.[]=( name, val )
|
8
121
|
meta_def("_#{name}") { val }
|
9
122
|
end
|
10
123
|
|
124
|
+
# Get the value of the given attribute. Typically, you wouldn't
|
125
|
+
# use this directly.
|
11
126
|
def self.[]( name ) ; send "_#{name}" ; end
|
12
127
|
|
128
|
+
# Define a new attribute. After calling this, you can get and set the value.
|
13
129
|
def self.attribute( name )
|
14
130
|
meta_def(name) do |*args|
|
15
131
|
raise ArgumentError.new('Too many arguments.') if args.length > 1
|
@@ -17,18 +133,23 @@ module Waves
|
|
17
133
|
end
|
18
134
|
self[ name ] = nil
|
19
135
|
end
|
20
|
-
|
21
|
-
def self.mime_types
|
22
|
-
Waves::MimeTypes
|
23
|
-
end
|
24
136
|
|
25
137
|
end
|
26
138
|
|
139
|
+
# The Default configuration provides a good starting point for your applications,
|
140
|
+
# defining a number of attributes that are required by Waves.
|
27
141
|
class Default < Base
|
28
142
|
|
29
|
-
%w( host port ports log reloadable
|
143
|
+
%w( host port ports log reloadable database session debug ).
|
30
144
|
each { |name| attribute(name) }
|
31
145
|
|
146
|
+
# Provide access to the Waves::MimeTypes class via the configuration. You
|
147
|
+
# could potentially point this to your own MIME types repository class.
|
148
|
+
def self.mime_types
|
149
|
+
Waves::MimeTypes
|
150
|
+
end
|
151
|
+
|
152
|
+
# Defines the application for use with Rack.
|
32
153
|
def self.application( &block )
|
33
154
|
if block_given?
|
34
155
|
self['application'] = Rack::Builder.new( &block )
|
@@ -36,10 +157,11 @@ module Waves
|
|
36
157
|
self['application']
|
37
158
|
end
|
38
159
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
160
|
+
|
161
|
+
debug true
|
162
|
+
session :duration => 30.minutes, :path => '/tmp/sessions'
|
163
|
+
log :level => :info, :output => $stderr
|
164
|
+
|
43
165
|
end
|
44
166
|
end
|
45
167
|
end
|
data/lib/runtime/console.rb
CHANGED
data/lib/runtime/logger.rb
CHANGED
@@ -1,26 +1,50 @@
|
|
1
1
|
require 'logger'
|
2
2
|
module Waves
|
3
3
|
|
4
|
+
# Waves::Logger is based on Ruby's built-in Logger. It uses the same filtering approach
|
5
|
+
# (debug, info, warn, error, fatal), although the interface is slightly different.
|
6
|
+
# You won't typically instantiate this class directly; instead, you will specify the
|
7
|
+
# logging configuration you want in your configuration files. See Waves::Configurations
|
8
|
+
# for more information on this.
|
9
|
+
#
|
10
|
+
# To use the logger for output, you can usually just call +log+, since the Waves::ResponseHelper
|
11
|
+
# mixin defines it (meaning it is available in the mapping file, controllers, views, and
|
12
|
+
# templates). Or, you can access Waves::Logger directly. Either way, the logger provides five
|
13
|
+
# methods for output corresponding to the log levels.
|
14
|
+
#
|
15
|
+
# *Examples*
|
16
|
+
# # log the value of foo
|
17
|
+
# log.info "Value of foo: #{foo}"
|
18
|
+
#
|
19
|
+
# # fatal error!
|
20
|
+
# Waves::Logger.fatal "She can't hold up any longer, cap'n!"
|
21
|
+
#
|
4
22
|
module Logger
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
23
|
+
|
24
|
+
class << self
|
25
|
+
|
26
|
+
# Returns the object being used for output by the logger.
|
27
|
+
def output
|
28
|
+
@output ||= ( config[:output] ? File.expand_path( config[:output] ) : $stderr )
|
29
|
+
end
|
30
|
+
# Returns the active configuration for the logger.
|
31
|
+
def config ; @config ||= Waves::Server.config.log ; end
|
32
|
+
# Returns the logging level used to filter logging events.
|
33
|
+
def level ; @level ||= ::Logger.const_get( config[:level].to_s.upcase || 'INFO' ) ; end
|
34
|
+
# Starts the logger, using the active configuration to initialize it.
|
35
|
+
def start
|
36
|
+
@log = config[:rotation] ?
|
37
|
+
::Logger.new( output, config[:rotation].intern ) :
|
38
|
+
::Logger.new( output )
|
39
|
+
@log.level = level
|
40
|
+
self
|
16
41
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
42
|
+
# Forwards logging methods to the logger.
|
43
|
+
def method_missing(name,*args,&block)
|
44
|
+
@log.send name,*args, &block
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
24
48
|
|
25
49
|
end
|
26
50
|
|
data/lib/runtime/mime_types.rb
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
module Waves
|
2
|
+
|
3
|
+
# Waves::MimeTypes defines an interface for adding MIME types used in mapping requests
|
4
|
+
# to content types. Mongrel's MIME_TYPES hash is used as the baseline MIME map.
|
5
|
+
|
2
6
|
module MimeTypes
|
3
7
|
|
4
8
|
def self.[]( path )
|
5
9
|
mapping[ File.extname( path ) ]
|
6
10
|
end
|
7
11
|
|
8
|
-
# TODO:
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
+
# TODO: This does not seem to be working.
|
13
|
+
def self.<<( mapping )
|
14
|
+
mapping.merge!( mapping )
|
15
|
+
end
|
12
16
|
|
13
17
|
def self.mapping
|
14
18
|
@mapping ||= Mongrel::DirHandler::MIME_TYPES
|
data/lib/runtime/request.rb
CHANGED
@@ -1,39 +1,48 @@
|
|
1
1
|
module Waves
|
2
|
+
# Waves::Request represents an HTTP request and has methods for accessing anything
|
3
|
+
# relating to the request. See Rack::Request for more information, since many methods
|
4
|
+
# are actually delegated to Rack::Request.
|
2
5
|
class Request
|
3
6
|
|
4
7
|
class ParseError < Exception ; end
|
5
8
|
|
6
9
|
attr_reader :response, :session
|
7
10
|
|
8
|
-
|
11
|
+
# Create a new request. Takes a env parameter representing the request passed in from Rack.
|
12
|
+
# You shouldn't need to call this directly.
|
13
|
+
def initialize( env )
|
9
14
|
@request = Rack::Request.new( env )
|
10
15
|
@response = Waves::Response.new( self )
|
11
16
|
@session = Waves::Session.new( self )
|
12
17
|
end
|
13
18
|
|
14
|
-
#
|
19
|
+
# Accessor not explicitly defined by Waves::Request are delegated to Rack::Request.
|
20
|
+
# Check the Rack documentation for more information.
|
15
21
|
def method_missing(name,*args)
|
16
22
|
@request.send(name,*args)
|
17
23
|
end
|
18
24
|
|
19
|
-
#
|
20
|
-
# Is there a Rack API that is more appropos
|
25
|
+
# The request path (PATH_INFO). Ex: +/entry/2008-01-17+
|
21
26
|
def path
|
22
27
|
@request.path_info
|
23
28
|
end
|
24
|
-
|
29
|
+
|
30
|
+
# The request domain. Ex: +www.fubar.com+
|
25
31
|
def domain
|
26
32
|
@request.host
|
27
33
|
end
|
28
34
|
|
35
|
+
# The request method: GET, PUT, POST, or DELETE.
|
29
36
|
def method
|
30
37
|
@request.request_method.downcase.intern
|
31
38
|
end
|
32
39
|
|
40
|
+
# Raise a not found exception.
|
33
41
|
def not_found
|
34
42
|
raise Waves::Dispatchers::NotFoundError.new( @request.url + ' not found.')
|
35
43
|
end
|
36
44
|
|
45
|
+
# Issue a redirect for the given path.
|
37
46
|
def redirect( path )
|
38
47
|
raise Waves::Dispatchers::Redirect.new( path )
|
39
48
|
end
|