dyoder-waves 0.7.3
Sign up to get free protection for your applications and to get access to all the features.
- data/app/Rakefile +14 -0
- data/app/bin/waves-console +3 -0
- data/app/bin/waves-server +3 -0
- data/app/configurations/development.rb.erb +31 -0
- data/app/configurations/mapping.rb.erb +14 -0
- data/app/configurations/production.rb.erb +30 -0
- data/app/lib/application.rb.erb +3 -0
- data/app/startup.rb +5 -0
- data/app/templates/errors/not_found_404.mab +2 -0
- data/app/templates/errors/server_error_500.mab +2 -0
- data/app/templates/layouts/default.mab +14 -0
- data/bin/waves +66 -0
- data/bin/waves-console +4 -0
- data/bin/waves-server +4 -0
- data/lib/commands/waves-console.rb +24 -0
- data/lib/commands/waves-server.rb +55 -0
- data/lib/controllers/mixin.rb +158 -0
- data/lib/dispatchers/base.rb +52 -0
- data/lib/dispatchers/default.rb +67 -0
- data/lib/foundations/default.rb +28 -0
- data/lib/foundations/simple.rb +17 -0
- data/lib/helpers/common.rb +62 -0
- data/lib/helpers/form.rb +39 -0
- data/lib/helpers/formatting.rb +30 -0
- data/lib/helpers/model.rb +33 -0
- data/lib/helpers/view.rb +24 -0
- data/lib/layers/default_errors.rb +24 -0
- data/lib/layers/simple_errors.rb +17 -0
- data/lib/mapping/mapping.rb +252 -0
- data/lib/mapping/pretty_urls.rb +94 -0
- data/lib/renderers/erubis.rb +61 -0
- data/lib/renderers/markaby.rb +33 -0
- data/lib/renderers/mixin.rb +53 -0
- data/lib/runtime/application.rb +65 -0
- data/lib/runtime/configuration.rb +180 -0
- data/lib/runtime/console.rb +20 -0
- data/lib/runtime/debugger.rb +9 -0
- data/lib/runtime/logger.rb +52 -0
- data/lib/runtime/mime_types.rb +22 -0
- data/lib/runtime/request.rb +77 -0
- data/lib/runtime/response.rb +40 -0
- data/lib/runtime/response_mixin.rb +35 -0
- data/lib/runtime/response_proxy.rb +27 -0
- data/lib/runtime/server.rb +94 -0
- data/lib/runtime/session.rb +56 -0
- data/lib/tasks/cluster.rb +25 -0
- data/lib/tasks/gem.rb +31 -0
- data/lib/tasks/generate.rb +15 -0
- data/lib/utilities/inflect.rb +194 -0
- data/lib/utilities/integer.rb +17 -0
- data/lib/utilities/kernel.rb +34 -0
- data/lib/utilities/module.rb +17 -0
- data/lib/utilities/object.rb +17 -0
- data/lib/utilities/proc.rb +9 -0
- data/lib/utilities/string.rb +47 -0
- data/lib/utilities/symbol.rb +7 -0
- data/lib/verify/mapping.rb +29 -0
- data/lib/verify/request.rb +40 -0
- data/lib/views/mixin.rb +108 -0
- data/lib/waves.rb +80 -0
- metadata +260 -0
data/app/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Warning: This file is clobbered when you update your
|
4
|
+
# application with the waves script. Accordingly, you may
|
5
|
+
# wish to keep your tasks in .rb or .rake files in lib/tasks
|
6
|
+
require 'startup'
|
7
|
+
Waves::Console.load(:mode => ENV['mode'])
|
8
|
+
|
9
|
+
# load tasks from waves framework
|
10
|
+
%w( cluster generate gem ).each { |task| require "tasks/#{task}.rb" }
|
11
|
+
|
12
|
+
# load tasks from this app's lib/tasks
|
13
|
+
Dir["lib/tasks/*.{rb,rake}"].each { |task| require task }
|
14
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module <%= name %>
|
2
|
+
|
3
|
+
module Configurations
|
4
|
+
|
5
|
+
class Development
|
6
|
+
|
7
|
+
database :host => 'localhost', :adapter => 'sqlite', :database => '<%= name.downcase %>',
|
8
|
+
:user => 'root', :password => ''
|
9
|
+
|
10
|
+
reloadable [ <%= name %> ]
|
11
|
+
|
12
|
+
log :level => :debug
|
13
|
+
|
14
|
+
host '127.0.0.1'
|
15
|
+
|
16
|
+
port 3000
|
17
|
+
|
18
|
+
handler ::Rack::Handler::Mongrel, :Host => host, :Port => port
|
19
|
+
# handler ::Rack::Handler::WEBrick, :BindAddress => host, :Port => port
|
20
|
+
# handler ::Rack::Handler::Thin, :Host => host, :Port => port
|
21
|
+
|
22
|
+
application do
|
23
|
+
use ::Rack::ShowExceptions
|
24
|
+
run ::Waves::Dispatchers::Default.new
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module <%= name %>
|
2
|
+
|
3
|
+
module Configurations
|
4
|
+
|
5
|
+
class Production < Default
|
6
|
+
|
7
|
+
database :host => 'localhost', :adapter => 'mysql', :database => '<%= name.downcase %>',
|
8
|
+
:user => 'root', :password => ''
|
9
|
+
|
10
|
+
reloadable []
|
11
|
+
|
12
|
+
log :level => :error,
|
13
|
+
:output => ( :log / "waves.#{$$}" ),
|
14
|
+
:rotation => :weekly
|
15
|
+
|
16
|
+
host '0.0.0.0'
|
17
|
+
|
18
|
+
port 80
|
19
|
+
|
20
|
+
handler ::Rack::Handler::Mongrel, :Host => host, :Port => port
|
21
|
+
# handler ::Rack::Handler::WEBrick, :BindAddress => host, :Port => port
|
22
|
+
# handler ::Rack::Handler::Thin, :Host => host, :Port => port
|
23
|
+
|
24
|
+
application do
|
25
|
+
run ::Waves::Dispatchers::Default.new
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/app/startup.rb
ADDED
data/bin/waves
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# rudimentary argument checks
|
4
|
+
if ARGV.length != 1 || ARGV[0] == '--help'
|
5
|
+
$stderr.puts "Usage: waves {app_name}"
|
6
|
+
$stderr.puts "app_name may contain only letters, numbers, and underscores."
|
7
|
+
exit 1
|
8
|
+
end
|
9
|
+
|
10
|
+
app_path = ARGV[0]
|
11
|
+
app_name = File.basename(app_path)
|
12
|
+
if app_name =~ /[^\w\d_]/
|
13
|
+
raise ArgumentError, <<-TEXT
|
14
|
+
Unusable name: \"#{app_name}\"
|
15
|
+
Application names may contain only letters, numbers, and underscores."
|
16
|
+
TEXT
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
require 'rubygems'
|
21
|
+
require 'erubis'
|
22
|
+
require 'extensions/all'
|
23
|
+
begin
|
24
|
+
require 'utilities/string'
|
25
|
+
rescue LoadError
|
26
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'utilities', 'string')
|
27
|
+
end
|
28
|
+
|
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
|
+
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
|
+
|
47
|
+
# get rid of placeholder files left over from gem install
|
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
|
65
|
+
|
66
|
+
puts "** Application created!"
|
data/bin/waves-console
ADDED
data/bin/waves-server
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'choice'
|
2
|
+
|
3
|
+
Choice.options do
|
4
|
+
header 'Run waves in console mode.'
|
5
|
+
header ''
|
6
|
+
option :mode do
|
7
|
+
short '-c'
|
8
|
+
long '--config=CONFIG'
|
9
|
+
desc 'Configuration to use.'
|
10
|
+
desc 'Defaults to development.'
|
11
|
+
cast Symbol
|
12
|
+
end
|
13
|
+
separator ''
|
14
|
+
end
|
15
|
+
|
16
|
+
console = Waves::Console.load( Choice.choices )
|
17
|
+
Object.send(:define_method, :waves) { console }
|
18
|
+
Object.instance_eval do
|
19
|
+
include Waves::Verify::Helpers::Request
|
20
|
+
end
|
21
|
+
require 'irb'
|
22
|
+
require 'irb/completion'
|
23
|
+
ARGV.clear
|
24
|
+
IRB.start
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'choice'
|
2
|
+
|
3
|
+
Choice.options do
|
4
|
+
header 'Run a waves application server.'
|
5
|
+
header ''
|
6
|
+
option :port do
|
7
|
+
short '-p'
|
8
|
+
long '--port=PORT'
|
9
|
+
desc 'Port to listen on.'
|
10
|
+
desc 'Defaults to value given in configuration.'
|
11
|
+
cast Integer
|
12
|
+
end
|
13
|
+
separator ''
|
14
|
+
option :host do
|
15
|
+
short '-h'
|
16
|
+
long '--host=HOST'
|
17
|
+
desc 'Host or IP address of the host to bind.'
|
18
|
+
desc 'Defaults to value given in configuration.'
|
19
|
+
end
|
20
|
+
separator ''
|
21
|
+
option :mode do
|
22
|
+
short '-c'
|
23
|
+
long '--config=CONFIG'
|
24
|
+
desc 'Configuration to use.'
|
25
|
+
desc 'Defaults to development.'
|
26
|
+
cast Symbol
|
27
|
+
end
|
28
|
+
separator ''
|
29
|
+
option :directory do
|
30
|
+
short '-D'
|
31
|
+
long '--dir=DIR'
|
32
|
+
desc 'Directory containing the application.'
|
33
|
+
desc 'Defaults to the current directory.'
|
34
|
+
end
|
35
|
+
separator ''
|
36
|
+
option :daemon do
|
37
|
+
short '-d'
|
38
|
+
long '--daemon'
|
39
|
+
desc 'Run as a daemon.'
|
40
|
+
end
|
41
|
+
separator ''
|
42
|
+
option :debugger do
|
43
|
+
short '-u'
|
44
|
+
long '--debugger'
|
45
|
+
desc 'Enable ruby-debug.'
|
46
|
+
end
|
47
|
+
separator ''
|
48
|
+
option :startup do
|
49
|
+
short '-s'
|
50
|
+
long '--startup'
|
51
|
+
desc 'Startup file to load.'
|
52
|
+
desc 'Defaults to "lib/startup.rb"'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
Waves::Server.run( Choice.choices )
|
@@ -0,0 +1,158 @@
|
|
1
|
+
module Waves
|
2
|
+
|
3
|
+
#
|
4
|
+
# Controllers in Waves are simply classes that provide a request / response
|
5
|
+
# context for operating on a model. While models are essentially just a way
|
6
|
+
# to manage data in an application, controllers manage data in response to
|
7
|
+
# a request. For example, a controller updates a model instance using
|
8
|
+
# parameters from the request.
|
9
|
+
#
|
10
|
+
# Controller methods simply return data (a resource), if necessary, that
|
11
|
+
# can be then used by views to determine how to render that data.
|
12
|
+
# Controllers do not determine which view will be invoked. They are
|
13
|
+
# independent of the view; one controller method might be suitable for
|
14
|
+
# several different views. In some cases, controllers can choose to
|
15
|
+
# directly modify the response and possibly even short-circuit the view
|
16
|
+
# entirely. A good example of this is a redirect.
|
17
|
+
#
|
18
|
+
# Controllers, like Views and Mappings, use the Waves::ResponseMixin to
|
19
|
+
# provide a rich context for working with the request and response objects.
|
20
|
+
# They can even call other controllers or views using the controllers method.
|
21
|
+
# In addition, they provide some basic reflection (access to the model and
|
22
|
+
# model_name that corresponds to the class name for the given model) and
|
23
|
+
# automatic parameter destructuring. This allows controller methods to access
|
24
|
+
# the request parameters as a hash, so that a POST variable named
|
25
|
+
# <tt>entry.title</tt> is accessed as <tt>params[:entry][:title]</tt>.
|
26
|
+
#
|
27
|
+
# Controllers often do not have to be explicitly defined. Instead, one or more
|
28
|
+
# default controllers can be defined that are used as exemplars for a given
|
29
|
+
# model. By default, the +waves+ command generates a single default, placed in
|
30
|
+
# the application's <tt>controllers/default.rb</tt> file. This can be modified
|
31
|
+
# to change the default behavior for all controllers. Alternatively, the
|
32
|
+
# <tt>rake generate:controller</tt> command can be used to explicitly define a
|
33
|
+
# controller.
|
34
|
+
#
|
35
|
+
# As an example, the code for the default controller is below for the Blog application.
|
36
|
+
#
|
37
|
+
# module Blog
|
38
|
+
# module Controllers
|
39
|
+
# class Default
|
40
|
+
#
|
41
|
+
# # Pick up the default controller methods, like param, url, etc.
|
42
|
+
# include Waves::Controllers::Mixin
|
43
|
+
#
|
44
|
+
# # This gets me the parameters associated with this model
|
45
|
+
# def attributes; params[model_name.singular.intern]; end
|
46
|
+
#
|
47
|
+
# # A simple generic delegator to the model
|
48
|
+
# def all; model.all; end
|
49
|
+
#
|
50
|
+
# # Find a specific instance based on a name or raise a 404
|
51
|
+
# def find( name ); model[ :name => name ] or not_found; end
|
52
|
+
#
|
53
|
+
# # Create a new instance based on the request params
|
54
|
+
# def create; model.create( attributes ); end
|
55
|
+
#
|
56
|
+
# # Update an existing record. find will raise a 404 if not found.
|
57
|
+
# def update( name )
|
58
|
+
# instance = find( name )
|
59
|
+
# instance.set( attributes )
|
60
|
+
# instance.save_changes
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# # Find and delete - or will raise a 404 if it doesn't exist
|
64
|
+
# def delete( name ); find( name ).destroy; end
|
65
|
+
#
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# Since the mapping file handles "glueing" controllers to views, controllers
|
71
|
+
# don't have to be at all concerned with views. They don't have to set
|
72
|
+
# instance variables, layouts, or contain logic to select the appropriate
|
73
|
+
# view based on the request. All they do is worry about updating the model
|
74
|
+
# when necessary based on the request.
|
75
|
+
|
76
|
+
module Controllers
|
77
|
+
|
78
|
+
#
|
79
|
+
# This mixin provides some handy methods for Waves controllers. You will probably
|
80
|
+
# want to include it in any controllers you define for your application. The default
|
81
|
+
# controllers generated using the +wave+ command already do this.
|
82
|
+
#
|
83
|
+
# Basically, what the mixin does is adapt the class so that it can be used within
|
84
|
+
# mappings (see Waves::Mapping); add some simple reflection to allow controller methods
|
85
|
+
# to be written generically (i.e., without reference to a specific model); and provide
|
86
|
+
# parameter destructuring for the request parameters.
|
87
|
+
#
|
88
|
+
|
89
|
+
module Mixin
|
90
|
+
|
91
|
+
attr_reader :request
|
92
|
+
|
93
|
+
include Waves::ResponseMixin
|
94
|
+
|
95
|
+
# When you include this Mixin, a +process+ class method is added to your class,
|
96
|
+
# which accepts a request object and a block. The request object is used to initialize
|
97
|
+
# the controller and the block is evaluated using +instance_eval+. This allows the
|
98
|
+
# controller to be used within a mapping file.
|
99
|
+
|
100
|
+
def self.included( c )
|
101
|
+
def c.process( request, &block )
|
102
|
+
self.new( request ).instance_eval( &block )
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def initialize( request ); @request = request; end
|
107
|
+
|
108
|
+
# The params variable is taken from the request object and "destructured", so that
|
109
|
+
# a parameter named 'blog.title' becomes:
|
110
|
+
#
|
111
|
+
# params['blog']['title']
|
112
|
+
#
|
113
|
+
# If you want to access the original parameters object, you can still do so using
|
114
|
+
# +request.parameters+ instead of simply +params+.
|
115
|
+
def params; @params ||= destructure(request.params); end
|
116
|
+
|
117
|
+
# You can access the name of the model related to this controller using this method.
|
118
|
+
# It simply takes the basename of the module and converts it to snake case, so if the
|
119
|
+
# model uses a different plurality, this won't, in fact, be the model name.
|
120
|
+
def model_name; self.class.basename.snake_case; end
|
121
|
+
|
122
|
+
# This uses the model_name method to attempt to identify the model corresponding to this
|
123
|
+
# controller. This allows you to write generic controller methods such as:
|
124
|
+
#
|
125
|
+
# model.find( name )
|
126
|
+
#
|
127
|
+
# to find an instance of a given model. Again, the plurality of the controller and
|
128
|
+
# model must be the same for this to work.
|
129
|
+
def model; Waves.application.models[ model_name.intern ]; end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def destructure(hash)
|
134
|
+
rval = {}
|
135
|
+
hash.keys.map{ |key|key.split('.') }.each do |keys|
|
136
|
+
destructure_with_array_keys(hash,'',keys,rval)
|
137
|
+
end
|
138
|
+
rval
|
139
|
+
end
|
140
|
+
|
141
|
+
def destructure_with_array_keys(hash,prefix,keys,rval)
|
142
|
+
if keys.length == 1
|
143
|
+
val = hash[prefix+keys.first]
|
144
|
+
rval[keys.first.intern] = case val
|
145
|
+
when String then val.strip
|
146
|
+
when Hash then val
|
147
|
+
end
|
148
|
+
else
|
149
|
+
rval = ( rval[keys.first.intern] ||= {} )
|
150
|
+
destructure_with_array_keys(hash,(keys.shift<<'.'),keys,rval)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|