dyoder-waves 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/app/Rakefile +14 -0
  2. data/app/bin/waves-console +3 -0
  3. data/app/bin/waves-server +3 -0
  4. data/app/configurations/development.rb.erb +31 -0
  5. data/app/configurations/mapping.rb.erb +14 -0
  6. data/app/configurations/production.rb.erb +30 -0
  7. data/app/lib/application.rb.erb +3 -0
  8. data/app/startup.rb +5 -0
  9. data/app/templates/errors/not_found_404.mab +2 -0
  10. data/app/templates/errors/server_error_500.mab +2 -0
  11. data/app/templates/layouts/default.mab +14 -0
  12. data/bin/waves +66 -0
  13. data/bin/waves-console +4 -0
  14. data/bin/waves-server +4 -0
  15. data/lib/commands/waves-console.rb +24 -0
  16. data/lib/commands/waves-server.rb +55 -0
  17. data/lib/controllers/mixin.rb +158 -0
  18. data/lib/dispatchers/base.rb +52 -0
  19. data/lib/dispatchers/default.rb +67 -0
  20. data/lib/foundations/default.rb +28 -0
  21. data/lib/foundations/simple.rb +17 -0
  22. data/lib/helpers/common.rb +62 -0
  23. data/lib/helpers/form.rb +39 -0
  24. data/lib/helpers/formatting.rb +30 -0
  25. data/lib/helpers/model.rb +33 -0
  26. data/lib/helpers/view.rb +24 -0
  27. data/lib/layers/default_errors.rb +24 -0
  28. data/lib/layers/simple_errors.rb +17 -0
  29. data/lib/mapping/mapping.rb +252 -0
  30. data/lib/mapping/pretty_urls.rb +94 -0
  31. data/lib/renderers/erubis.rb +61 -0
  32. data/lib/renderers/markaby.rb +33 -0
  33. data/lib/renderers/mixin.rb +53 -0
  34. data/lib/runtime/application.rb +65 -0
  35. data/lib/runtime/configuration.rb +180 -0
  36. data/lib/runtime/console.rb +20 -0
  37. data/lib/runtime/debugger.rb +9 -0
  38. data/lib/runtime/logger.rb +52 -0
  39. data/lib/runtime/mime_types.rb +22 -0
  40. data/lib/runtime/request.rb +77 -0
  41. data/lib/runtime/response.rb +40 -0
  42. data/lib/runtime/response_mixin.rb +35 -0
  43. data/lib/runtime/response_proxy.rb +27 -0
  44. data/lib/runtime/server.rb +94 -0
  45. data/lib/runtime/session.rb +56 -0
  46. data/lib/tasks/cluster.rb +25 -0
  47. data/lib/tasks/gem.rb +31 -0
  48. data/lib/tasks/generate.rb +15 -0
  49. data/lib/utilities/inflect.rb +194 -0
  50. data/lib/utilities/integer.rb +17 -0
  51. data/lib/utilities/kernel.rb +34 -0
  52. data/lib/utilities/module.rb +17 -0
  53. data/lib/utilities/object.rb +17 -0
  54. data/lib/utilities/proc.rb +9 -0
  55. data/lib/utilities/string.rb +47 -0
  56. data/lib/utilities/symbol.rb +7 -0
  57. data/lib/verify/mapping.rb +29 -0
  58. data/lib/verify/request.rb +40 -0
  59. data/lib/views/mixin.rb +108 -0
  60. data/lib/waves.rb +80 -0
  61. 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,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'startup'
3
+ require 'commands/waves-console'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'startup'
3
+ require 'commands/waves-server'
@@ -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,14 @@
1
+ module <%= name %>
2
+
3
+ module Configurations
4
+
5
+ module Mapping
6
+ extend Waves::Mapping
7
+ # your custom rules go here
8
+ include Waves::Mapping::PrettyUrls::RestRules
9
+ include Waves::Mapping::PrettyUrls::GetRules
10
+ end
11
+
12
+ end
13
+
14
+ 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
@@ -0,0 +1,3 @@
1
+ module <%= name %>
2
+ include Waves::Foundations::Default
3
+ end
data/app/startup.rb ADDED
@@ -0,0 +1,5 @@
1
+ lambda {
2
+ waves = ( ( WAVES if defined? WAVES ) || ENV['WAVES'] || File.join(File.dirname(__FILE__), 'waves') )
3
+ $:.unshift(File.join( waves, "lib" )) if File.exist? waves
4
+ }.call
5
+ require 'waves'
@@ -0,0 +1,2 @@
1
+ h1 '404'
2
+ p %q( That URL does not exist on this server. )
@@ -0,0 +1,2 @@
1
+ h1 '500'
2
+ p %q( Internal server error. Sorry, but your request could not be processed. )
@@ -0,0 +1,14 @@
1
+ doctype :html4_strict
2
+
3
+ html do
4
+
5
+ head do
6
+ title @title
7
+ end
8
+
9
+ body do
10
+ layout_content
11
+ end
12
+
13
+ end
14
+
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
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'startup'
3
+
4
+ require 'commands/waves-console'
data/bin/waves-server ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'startup'
3
+
4
+ require 'commands/waves-server'
@@ -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