dyoder-waves 0.7.3 → 0.7.6
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/bin/waves-console +1 -0
- data/app/bin/waves-server +1 -0
- data/app/configurations/development.rb.erb +5 -6
- data/app/configurations/mapping.rb.erb +1 -2
- data/app/configurations/production.rb.erb +2 -2
- data/app/controllers/.gitignore +0 -0
- data/app/doc/.gitignore +0 -0
- data/app/helpers/.gitignore +0 -0
- data/app/lib/application.rb.erb +4 -2
- data/app/lib/tasks/.gitignore +0 -0
- data/app/log/.gitignore +0 -0
- data/app/models/.gitignore +0 -0
- data/app/public/css/.gitignore +0 -0
- data/app/public/flash/.gitignore +0 -0
- data/app/public/images/.gitignore +0 -0
- data/app/public/javascript/.gitignore +0 -0
- data/app/schema/migrations/.gitignore +0 -0
- data/app/tmp/sessions/.gitignore +0 -0
- data/app/views/.gitignore +0 -0
- data/bin/waves +29 -46
- data/bin/waves-console +1 -1
- data/bin/waves-server +1 -1
- data/lib/commands/waves-console.rb +0 -3
- data/lib/controllers/base.rb +11 -0
- data/lib/controllers/mixin.rb +39 -32
- data/lib/dispatchers/base.rb +37 -22
- data/lib/dispatchers/default.rb +25 -11
- data/lib/foundations/default.rb +6 -8
- data/lib/foundations/simple.rb +13 -0
- data/lib/helpers/asset_helper.rb +67 -0
- data/lib/helpers/common.rb +4 -0
- data/lib/helpers/default.rb +13 -0
- data/lib/helpers/form.rb +1 -0
- data/lib/helpers/number_helper.rb +25 -0
- data/lib/helpers/tag_helper.rb +58 -0
- data/lib/helpers/url_helper.rb +77 -0
- data/lib/layers/default_errors.rb +7 -5
- data/lib/layers/mvc.rb +54 -0
- data/lib/layers/orm/active_record.rb +93 -0
- data/lib/layers/orm/active_record/migrations/empty.rb.erb +9 -0
- data/lib/layers/orm/active_record/tasks/generate.rb +28 -0
- data/lib/layers/orm/active_record/tasks/schema.rb +22 -0
- data/lib/layers/orm/data_mapper.rb +38 -0
- data/lib/layers/orm/filebase.rb +22 -0
- data/lib/layers/orm/migration.rb +79 -0
- data/lib/layers/orm/sequel.rb +86 -0
- data/lib/layers/orm/sequel/migrations/empty.rb.erb +9 -0
- data/lib/layers/orm/sequel/tasks/generate.rb +28 -0
- data/lib/layers/orm/sequel/tasks/schema.rb +16 -0
- data/lib/layers/simple.rb +35 -0
- data/lib/layers/simple_errors.rb +11 -5
- data/lib/mapping/mapping.rb +61 -24
- data/lib/mapping/pretty_urls.rb +5 -3
- data/lib/renderers/erubis.rb +3 -1
- data/lib/renderers/mixin.rb +1 -4
- data/lib/runtime/application.rb +12 -8
- data/lib/runtime/blackboard.rb +57 -0
- data/lib/runtime/configuration.rb +60 -55
- data/lib/runtime/logger.rb +8 -1
- data/lib/runtime/request.rb +5 -4
- data/lib/runtime/response.rb +3 -3
- data/lib/runtime/response_mixin.rb +3 -0
- data/lib/runtime/response_proxy.rb +4 -1
- data/lib/runtime/server.rb +18 -5
- data/lib/runtime/session.rb +20 -10
- data/lib/tasks/cluster.rb +2 -1
- data/lib/tasks/generate.rb +76 -11
- data/lib/utilities/hash.rb +31 -0
- data/lib/utilities/inflect.rb +86 -170
- data/lib/utilities/inflect/english.rb +84 -0
- data/lib/utilities/integer.rb +23 -16
- data/lib/utilities/module.rb +19 -15
- data/lib/utilities/object.rb +22 -14
- data/lib/utilities/proc.rb +13 -6
- data/lib/utilities/string.rb +58 -44
- data/lib/utilities/symbol.rb +4 -1
- data/lib/views/base.rb +9 -0
- data/lib/views/mixin.rb +3 -1
- data/lib/waves.rb +15 -13
- metadata +50 -25
- data/lib/utilities/kernel.rb +0 -34
- data/lib/verify/mapping.rb +0 -29
- data/lib/verify/request.rb +0 -40
data/app/bin/waves-console
CHANGED
data/app/bin/waves-server
CHANGED
@@ -1,13 +1,12 @@
|
|
1
|
-
module <%= name %>
|
1
|
+
module <%= @name %>
|
2
2
|
|
3
3
|
module Configurations
|
4
4
|
|
5
|
-
class Development
|
5
|
+
class Development < Default
|
6
6
|
|
7
|
-
database :
|
8
|
-
:user => 'root', :password => ''
|
7
|
+
database :adapter => 'sqlite', :database => '<%= @name.downcase %>'
|
9
8
|
|
10
|
-
reloadable [ <%= name %> ]
|
9
|
+
reloadable [ <%= @name %> ]
|
11
10
|
|
12
11
|
log :level => :debug
|
13
12
|
|
@@ -15,7 +14,7 @@ module <%= name %>
|
|
15
14
|
|
16
15
|
port 3000
|
17
16
|
|
18
|
-
|
17
|
+
handler ::Rack::Handler::Mongrel, :Host => host, :Port => port
|
19
18
|
# handler ::Rack::Handler::WEBrick, :BindAddress => host, :Port => port
|
20
19
|
# handler ::Rack::Handler::Thin, :Host => host, :Port => port
|
21
20
|
|
@@ -1,10 +1,10 @@
|
|
1
|
-
module <%= name %>
|
1
|
+
module <%= @name %>
|
2
2
|
|
3
3
|
module Configurations
|
4
4
|
|
5
5
|
class Production < Default
|
6
6
|
|
7
|
-
database :host => 'localhost', :adapter => 'mysql', :database => '<%= name.downcase %>',
|
7
|
+
database :host => 'localhost', :adapter => 'mysql', :database => '<%= @name.downcase %>',
|
8
8
|
:user => 'root', :password => ''
|
9
9
|
|
10
10
|
reloadable []
|
File without changes
|
data/app/doc/.gitignore
ADDED
File without changes
|
File without changes
|
data/app/lib/application.rb.erb
CHANGED
File without changes
|
data/app/log/.gitignore
ADDED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/bin/waves
CHANGED
@@ -1,10 +1,26 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'choice'
|
4
|
+
require 'rakegen'
|
5
|
+
|
6
|
+
# if we're in the waves source, prepend it to the load path
|
7
|
+
waves_lib = File.expand_path( "#{File.dirname(__FILE__)}/../../waves/lib" )
|
8
|
+
$:.unshift waves_lib if File.exist?(waves_lib)
|
9
|
+
require 'waves'
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'utilities/string'
|
13
|
+
rescue LoadError
|
14
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'utilities', 'string')
|
15
|
+
end
|
2
16
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
17
|
+
Choice.options do
|
18
|
+
banner 'Usage: waves path/to/app [-h]'
|
19
|
+
option :help do
|
20
|
+
long '--help'
|
21
|
+
desc 'Show this message'
|
22
|
+
end
|
23
|
+
|
8
24
|
end
|
9
25
|
|
10
26
|
app_path = ARGV[0]
|
@@ -16,51 +32,18 @@ if app_name =~ /[^\w\d_]/
|
|
16
32
|
TEXT
|
17
33
|
end
|
18
34
|
|
35
|
+
template = "#{WAVES}/app"
|
19
36
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
rescue LoadError
|
26
|
-
require File.join(File.dirname(__FILE__), '..', 'lib', 'utilities', 'string')
|
37
|
+
generator = Rakegen.new("waves:app") do |gen|
|
38
|
+
gen.source = template
|
39
|
+
gen.target = app_path
|
40
|
+
gen.template_assigns = {:name => app_name.camel_case}
|
41
|
+
gen.executables = %w{ bin/waves-console bin/waves-server}
|
27
42
|
end
|
28
43
|
|
29
|
-
require 'fileutils'
|
30
|
-
include FileUtils
|
31
|
-
|
32
|
-
# are we calling this script from within the waves framework source?
|
33
|
-
script_path = File.expand_path(__FILE__)
|
34
|
-
WAVES_SRC = File.dirname(File.dirname(script_path))
|
35
|
-
IN_WAVES_SRC = Dir.pwd.match(WAVES_SRC) ? true : false
|
36
|
-
|
37
|
-
|
38
44
|
puts "** Creating new Waves application ..."
|
39
|
-
template = begin
|
40
|
-
File.join File.dirname(File.readlink(__FILE__)), '..', 'app'
|
41
|
-
rescue Exception
|
42
|
-
File.join( File.dirname(__FILE__),'..','app')
|
43
|
-
end
|
44
|
-
mkdir(app_path)
|
45
|
-
cp_r Dir["#{template}/*"], app_path
|
46
45
|
|
47
|
-
|
48
|
-
Dir["#{app_path}/**/EMPTY"].each { |path| rm path }
|
49
|
-
# Dir["#{app_path}/**/EMPTY"].each { |path| system "rm #{path}" }
|
50
|
-
|
51
|
-
# next, process all template files ...
|
52
|
-
Dir["#{app_path}/**/*.erb"].each do |path|
|
53
|
-
unless path =~ %r{^#{app_path}/(schema/migrations/templates|templates)}
|
54
|
-
name = app_name.camel_case
|
55
|
-
File.write( path.gsub(/\.erb$/,''),
|
56
|
-
Erubis::Eruby.new( File.read( path ) ).result( binding ) )
|
57
|
-
rm path
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
unless RUBY_PLATFORM =~ /mswin32/
|
62
|
-
# make the scripts executable
|
63
|
-
system "chmod ug+x #{app_path}/bin/waves-*"
|
64
|
-
end
|
46
|
+
Rake::Task["waves:app"].invoke
|
65
47
|
|
66
48
|
puts "** Application created!"
|
49
|
+
|
data/bin/waves-console
CHANGED
data/bin/waves-server
CHANGED
data/lib/controllers/mixin.rb
CHANGED
@@ -7,7 +7,7 @@ module Waves
|
|
7
7
|
# a request. For example, a controller updates a model instance using
|
8
8
|
# parameters from the request.
|
9
9
|
#
|
10
|
-
#
|
10
|
+
# Public controller methods simply return data (a resource), if necessary, that
|
11
11
|
# can be then used by views to determine how to render that data.
|
12
12
|
# Controllers do not determine which view will be invoked. They are
|
13
13
|
# independent of the view; one controller method might be suitable for
|
@@ -76,13 +76,12 @@ module Waves
|
|
76
76
|
module Controllers
|
77
77
|
|
78
78
|
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
79
|
+
# Waves::Controllers::Mixin adapts a controller class for use in mappings and provides utility methods.
|
80
|
+
# It is included in controllers autocreated by the Default foundation, so you do not need to include
|
81
|
+
# it in subclasses of the same.
|
82
82
|
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
# to be written generically (i.e., without reference to a specific model); and provide
|
83
|
+
# The utility methods include simple reflection to allow controller methods
|
84
|
+
# to be written generically (i.e., without reference to a specific model) and
|
86
85
|
# parameter destructuring for the request parameters.
|
87
86
|
#
|
88
87
|
|
@@ -92,18 +91,20 @@ module Waves
|
|
92
91
|
|
93
92
|
include Waves::ResponseMixin
|
94
93
|
|
95
|
-
# When
|
96
|
-
# which accepts a request object and a block. The
|
97
|
-
# the
|
98
|
-
# controller to be used within a mapping
|
94
|
+
# When this mixin is included it adds a class method named +process+,
|
95
|
+
# which accepts a request object and a block. The +process+ method initializes the
|
96
|
+
# controller with the request, then evaluates the block using +instance_eval+. This allows the
|
97
|
+
# controller to be used from within a mapping lambda (i.e. a ResponseProxy).
|
99
98
|
|
100
|
-
def self.included(
|
101
|
-
def
|
99
|
+
def self.included( mod )
|
100
|
+
def mod.process( request, &block )
|
102
101
|
self.new( request ).instance_eval( &block )
|
103
102
|
end
|
104
103
|
end
|
105
104
|
|
106
|
-
def initialize( request )
|
105
|
+
def initialize( request )
|
106
|
+
@request = request
|
107
|
+
end
|
107
108
|
|
108
109
|
# The params variable is taken from the request object and "destructured", so that
|
109
110
|
# a parameter named 'blog.title' becomes:
|
@@ -111,16 +112,16 @@ module Waves
|
|
111
112
|
# params['blog']['title']
|
112
113
|
#
|
113
114
|
# If you want to access the original parameters object, you can still do so using
|
114
|
-
# +request.
|
115
|
+
# +request.params+ instead of simply +params+.
|
115
116
|
def params; @params ||= destructure(request.params); end
|
116
117
|
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
118
|
+
# Returns the name of the model corresponding to this controller by taking the basename
|
119
|
+
# of the module and converting it to snake case. If the model plurality is different than
|
120
|
+
# the controller, this will not, in fact, be the model name.
|
120
121
|
def model_name; self.class.basename.snake_case; end
|
121
122
|
|
122
|
-
#
|
123
|
-
#
|
123
|
+
# Returns the model corresponding to this controller by naively assuming that
|
124
|
+
# +model_name+ must be correct. This allows you to write generic controller methods such as:
|
124
125
|
#
|
125
126
|
# model.find( name )
|
126
127
|
#
|
@@ -130,24 +131,30 @@ module Waves
|
|
130
131
|
|
131
132
|
private
|
132
133
|
|
133
|
-
def destructure(hash)
|
134
|
-
|
135
|
-
hash.keys.map{ |key|key.split('.') }.each do |keys|
|
136
|
-
destructure_with_array_keys(hash,'',keys,
|
134
|
+
def destructure( hash )
|
135
|
+
destructured = {}
|
136
|
+
hash.keys.map { |key| key.split('.') }.each do |keys|
|
137
|
+
destructure_with_array_keys(hash, '', keys, destructured)
|
137
138
|
end
|
138
|
-
|
139
|
+
destructured
|
139
140
|
end
|
140
141
|
|
141
|
-
def destructure_with_array_keys(hash,prefix,keys,
|
142
|
+
def destructure_with_array_keys( hash, prefix, keys, destructured )
|
142
143
|
if keys.length == 1
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
when
|
144
|
+
key = "#{prefix}#{keys.first}"
|
145
|
+
val = hash[key]
|
146
|
+
destructured[keys.first.intern] = case val
|
147
|
+
when String
|
148
|
+
val.strip
|
149
|
+
when Hash
|
150
|
+
val
|
151
|
+
when nil
|
152
|
+
raise key.inspect
|
147
153
|
end
|
148
154
|
else
|
149
|
-
|
150
|
-
|
155
|
+
destructured = ( destructured[keys.first.intern] ||= {} )
|
156
|
+
new_prefix = "#{prefix}#{keys.shift}."
|
157
|
+
destructure_with_array_keys( hash, new_prefix, keys, destructured )
|
151
158
|
end
|
152
159
|
end
|
153
160
|
|
data/lib/dispatchers/base.rb
CHANGED
@@ -2,8 +2,14 @@ module Waves
|
|
2
2
|
|
3
3
|
module Dispatchers
|
4
4
|
|
5
|
+
# A NotFoundError means what you think it means. The dispatchers included with Waves do not
|
6
|
+
# natively intercept this exception. Instead an exception handler must be registered in the application
|
7
|
+
# mappings. The Simple foundation registers a minimal handler, while the Default foundation registers
|
8
|
+
# a slightly fleshier one.
|
5
9
|
class NotFoundError < Exception ; end
|
6
10
|
|
11
|
+
# Redirect exceptions are rescued by the Waves dispatcher and used to set the
|
12
|
+
# response status and location.
|
7
13
|
class Redirect < Exception
|
8
14
|
attr_reader :path, :status
|
9
15
|
def initialize( path, status = '302' )
|
@@ -12,38 +18,47 @@ module Waves
|
|
12
18
|
end
|
13
19
|
end
|
14
20
|
|
15
|
-
#
|
16
|
-
# from it.
|
17
|
-
#
|
18
|
-
# exceptions and redirects. Derived classes need only
|
19
|
-
#
|
21
|
+
# Waves::Dispatchers::Base provides the basic request processing structure.
|
22
|
+
# All other Waves dispatchers should inherit from it. It creates a Waves request,
|
23
|
+
# determines whether to enclose the request processing in a mutex, benchmarks it,
|
24
|
+
# logs it, and handles common exceptions and redirects. Derived classes need only
|
25
|
+
# process the request within the +safe+ method, which must take a Waves::Request and return a Waves::Response.
|
20
26
|
|
21
27
|
class Base
|
22
28
|
|
23
|
-
#
|
24
|
-
#
|
29
|
+
# As with any Rack application, a Waves dispatcher must provide a call method
|
30
|
+
# that takes an +env+ parameter.
|
25
31
|
def call( env )
|
26
|
-
Waves
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
begin
|
31
|
-
safe( request )
|
32
|
-
rescue Dispatchers::Redirect => redirect
|
33
|
-
response.status = redirect.status
|
34
|
-
response.location = redirect.path
|
35
|
-
end
|
36
|
-
end
|
37
|
-
Waves::Logger.info "#{request.method}: #{request.url} handled in #{(t*1000).round} ms."
|
38
|
-
response.finish
|
32
|
+
if Waves.config.synchronize?
|
33
|
+
Waves::Application.instance.synchronize { _call( env ) }
|
34
|
+
else
|
35
|
+
_call( env )
|
39
36
|
end
|
40
37
|
end
|
41
38
|
|
42
|
-
# Called by event driven servers like thin and ebb.
|
43
|
-
# the server should run the request in a separate thread
|
39
|
+
# Called by event driven servers like thin and ebb. Returns true if
|
40
|
+
# the server should run the request in a separate thread, as determined by
|
41
|
+
# Configurations::Mapping#threaded?
|
44
42
|
def deferred?( env )
|
45
43
|
Waves::Application.instance.mapping.threaded?( env )
|
46
44
|
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def _call( env )
|
49
|
+
request = Waves::Request.new( env )
|
50
|
+
response = request.response
|
51
|
+
t = Benchmark.realtime do
|
52
|
+
begin
|
53
|
+
safe( request )
|
54
|
+
rescue Dispatchers::Redirect => redirect
|
55
|
+
response.status = redirect.status
|
56
|
+
response.location = redirect.path
|
57
|
+
end
|
58
|
+
end
|
59
|
+
Waves::Logger.info "#{request.method}: #{request.url} handled in #{(t*1000).round} ms."
|
60
|
+
response.finish
|
61
|
+
end
|
47
62
|
|
48
63
|
end
|
49
64
|
|
data/lib/dispatchers/default.rb
CHANGED
@@ -3,13 +3,14 @@ module Waves
|
|
3
3
|
module Dispatchers
|
4
4
|
|
5
5
|
#
|
6
|
-
#
|
7
|
-
# what
|
8
|
-
#
|
6
|
+
# Waves::Dispatchers::Default matches requests against an application's mappings to
|
7
|
+
# determine what main action to take, as well as what before, after, always, and exception-handling
|
8
|
+
# blocks must run.
|
9
9
|
#
|
10
10
|
# The default dispatcher also attempts to set the content type based on the
|
11
|
-
#
|
12
|
-
#
|
11
|
+
# file extension used in the request URL. It does this using the class defined in
|
12
|
+
# the current configuration's +mime_types+ attribute, which defaults to Mongrel's
|
13
|
+
# MIME type handler.
|
13
14
|
#
|
14
15
|
# You can write your own dispatcher and use it in your application's configuration
|
15
16
|
# file. By default, they use the default dispatcher, like this:
|
@@ -27,13 +28,14 @@ module Waves
|
|
27
28
|
# Takes a Waves::Request and returns a Waves::Reponse
|
28
29
|
def safe( request )
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
response = request.response
|
32
|
+
|
33
|
+
Waves::Application.instance.reload if Waves::Application.instance.debug?
|
34
|
+
response.content_type = Waves::Application.instance.config.mime_types[ request.path ] || 'text/html'
|
32
35
|
|
33
|
-
|
34
|
-
response.content_type = Waves::Application.instance.config.mime_types[ request.path ] || 'text/html'
|
36
|
+
mapping = Waves::Application.instance.mapping[ request ]
|
35
37
|
|
36
|
-
|
38
|
+
begin
|
37
39
|
|
38
40
|
mapping[:before].each do | block, args |
|
39
41
|
ResponseProxy.new(request).instance_exec(*args,&block)
|
@@ -43,11 +45,13 @@ module Waves
|
|
43
45
|
|
44
46
|
block, args = mapping[:action]
|
45
47
|
response.write( ResponseProxy.new(request).instance_exec(*args, &block) )
|
46
|
-
|
48
|
+
|
47
49
|
mapping[:after].each do | block, args |
|
48
50
|
ResponseProxy.new(request).instance_exec(*args,&block)
|
49
51
|
end
|
52
|
+
|
50
53
|
rescue Exception => e
|
54
|
+
|
51
55
|
handler = mapping[:handlers].detect do | exception, block, args |
|
52
56
|
e.is_a? exception
|
53
57
|
end
|
@@ -56,6 +60,16 @@ module Waves
|
|
56
60
|
else
|
57
61
|
raise e
|
58
62
|
end
|
63
|
+
|
64
|
+
ensure
|
65
|
+
mapping[:always].each do | block, args |
|
66
|
+
begin
|
67
|
+
ResponseProxy.new(request).instance_exec(*args,&block)
|
68
|
+
rescue Exception => e
|
69
|
+
Waves::Logger.info e.to_s
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
59
73
|
end
|
60
74
|
|
61
75
|
end
|