waves 0.7.3 → 0.7.5

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.
Files changed (96) hide show
  1. data/app/Rakefile +11 -19
  2. data/app/bin/waves-console +3 -5
  3. data/app/bin/waves-server +3 -5
  4. data/app/configurations/development.rb.erb +19 -11
  5. data/app/configurations/mapping.rb.erb +4 -5
  6. data/app/configurations/production.rb.erb +18 -13
  7. data/app/{doc/EMTPY → controllers/.gitignore} +0 -0
  8. data/app/{public/css/EMPTY → doc/.gitignore} +0 -0
  9. data/app/{public/flash/EMPTY → helpers/.gitignore} +0 -0
  10. data/app/lib/application.rb.erb +4 -51
  11. data/app/{public/images/EMPTY → lib/tasks/.gitignore} +0 -0
  12. data/app/{public/javascript/EMPTY → log/.gitignore} +0 -0
  13. data/app/{tmp/sessions/EMPTY → models/.gitignore} +0 -0
  14. data/app/public/css/.gitignore +0 -0
  15. data/app/public/flash/.gitignore +0 -0
  16. data/app/public/images/.gitignore +0 -0
  17. data/app/public/javascript/.gitignore +0 -0
  18. data/app/schema/migrations/.gitignore +0 -0
  19. data/app/startup.rb +5 -0
  20. data/app/templates/layouts/default.mab +2 -2
  21. data/app/tmp/sessions/.gitignore +0 -0
  22. data/app/views/.gitignore +0 -0
  23. data/bin/waves +38 -27
  24. data/bin/waves-console +3 -25
  25. data/bin/waves-server +4 -45
  26. data/lib/commands/waves-console.rb +21 -0
  27. data/lib/commands/waves-server.rb +55 -0
  28. data/lib/controllers/base.rb +11 -0
  29. data/lib/controllers/mixin.rb +130 -102
  30. data/lib/dispatchers/base.rb +65 -50
  31. data/lib/dispatchers/default.rb +79 -52
  32. data/lib/foundations/default.rb +26 -0
  33. data/lib/foundations/simple.rb +30 -0
  34. data/lib/helpers/common.rb +60 -56
  35. data/lib/helpers/default.rb +13 -0
  36. data/lib/helpers/form.rb +39 -38
  37. data/lib/helpers/formatting.rb +11 -11
  38. data/lib/helpers/model.rb +12 -12
  39. data/lib/helpers/view.rb +13 -13
  40. data/lib/layers/default_errors.rb +29 -0
  41. data/lib/layers/mvc.rb +58 -0
  42. data/lib/layers/orm/active_record.rb +41 -0
  43. data/lib/layers/orm/active_record/migrations/empty.rb.erb +9 -0
  44. data/lib/layers/orm/active_record/tasks/schema.rb +30 -0
  45. data/lib/layers/orm/data_mapper.rb +42 -0
  46. data/lib/layers/orm/filebase.rb +22 -0
  47. data/lib/layers/orm/migration.rb +70 -0
  48. data/lib/layers/orm/sequel.rb +82 -0
  49. data/lib/layers/orm/sequel/migrations/empty.rb.erb +9 -0
  50. data/lib/layers/orm/sequel/tasks/schema.rb +24 -0
  51. data/lib/layers/simple.rb +39 -0
  52. data/lib/layers/simple_errors.rb +26 -0
  53. data/lib/mapping/mapping.rb +222 -120
  54. data/lib/mapping/pretty_urls.rb +42 -41
  55. data/lib/renderers/erubis.rb +54 -31
  56. data/lib/renderers/markaby.rb +28 -28
  57. data/lib/renderers/mixin.rb +49 -52
  58. data/lib/runtime/application.rb +66 -48
  59. data/lib/runtime/blackboard.rb +57 -0
  60. data/lib/runtime/configuration.rb +117 -101
  61. data/lib/runtime/console.rb +19 -20
  62. data/lib/runtime/debugger.rb +9 -0
  63. data/lib/runtime/logger.rb +43 -37
  64. data/lib/runtime/mime_types.rb +19 -19
  65. data/lib/runtime/request.rb +72 -46
  66. data/lib/runtime/response.rb +37 -37
  67. data/lib/runtime/response_mixin.rb +26 -23
  68. data/lib/runtime/response_proxy.rb +25 -24
  69. data/lib/runtime/server.rb +99 -80
  70. data/lib/runtime/session.rb +63 -53
  71. data/lib/tasks/cluster.rb +26 -0
  72. data/lib/tasks/gem.rb +31 -0
  73. data/lib/tasks/generate.rb +80 -0
  74. data/lib/utilities/hash.rb +22 -0
  75. data/lib/utilities/inflect.rb +194 -0
  76. data/lib/utilities/integer.rb +15 -12
  77. data/lib/utilities/kernel.rb +32 -32
  78. data/lib/utilities/module.rb +11 -4
  79. data/lib/utilities/object.rb +5 -5
  80. data/lib/utilities/proc.rb +10 -0
  81. data/lib/utilities/string.rb +44 -38
  82. data/lib/utilities/symbol.rb +4 -4
  83. data/lib/views/base.rb +9 -0
  84. data/lib/views/mixin.rb +91 -89
  85. data/lib/waves.rb +29 -9
  86. metadata +52 -26
  87. data/app/configurations/default.rb.erb +0 -8
  88. data/app/controllers/default.rb.erb +0 -29
  89. data/app/helpers/default.rb.erb +0 -13
  90. data/app/lib/startup.rb.erb +0 -3
  91. data/app/lib/tasks/cluster.rb +0 -24
  92. data/app/lib/tasks/generate.rb +0 -15
  93. data/app/lib/tasks/schema.rb +0 -29
  94. data/app/models/default.rb.erb +0 -13
  95. data/app/schema/migrations/templates/empty.rb.erb +0 -9
  96. data/app/views/default.rb.erb +0 -13
@@ -0,0 +1,57 @@
1
+ module Waves
2
+
3
+ # Encapsulates the blackboard associated with a given request. The scope of the blackboard is
4
+ # the same as the request object it gets attached to.
5
+ #
6
+ # The Waves blackboard is a very simple shared storaged usable during the request processing.
7
+ # It is available within:
8
+ # - mappings
9
+ # - controllers
10
+ # - helpers
11
+ #
12
+ # Adding a value:
13
+ # blackboard.value1 = 1
14
+ # blackboard[:value2] = 2
15
+ #
16
+ # Retrieving values
17
+ # blackboard.value1
18
+ # blackboard[:value2]
19
+ #
20
+ # see also blackboard_verify.rb
21
+
22
+ class Blackboard
23
+
24
+ # Create a new blackboard object using the given request.
25
+ def initialize( request )
26
+ @request = request
27
+ @data = {}
28
+ end
29
+
30
+ # Access a given data element of the blackboard using the given key.
31
+ def [](key)
32
+ @data[key]
33
+ end
34
+
35
+ # Set the given data element of the blackboard using the given key and value.
36
+ def []=(key,val)
37
+ @data[key] = val
38
+ end
39
+
40
+ def each(&block)
41
+ @data.each(&block)
42
+ end
43
+
44
+ # also allow things like
45
+ # blackboard.test1 instead of blackboard[:test1]
46
+ # blackboard.test1 = 2 instead of blackboard[:test1] = 2
47
+ def method_missing(name,*args)
48
+ if (name.to_s =~ /=$/)
49
+ self[name.to_s.gsub('=', '')] = args[0]
50
+ else
51
+ self[name.to_s]
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -1,14 +1,13 @@
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.
2
+
3
+ # Waves configurations are Ruby code. This means you can use a Ruby expression as
4
+ # the value of a configuration attribute, extend and inherit your configurations, and
5
+ # add your own attributes. You can even use it as a repository
6
+ # for your application configuration.
7
7
  #
8
- # The form for configuration parameters to use the parameter name as a method name. Passing
9
- # in a parameter sets the value.
8
+ # You can access configuration attributes using the attribute name as a method, with the value as the argument.
10
9
  #
11
- # == Example
10
+ # == Example
12
11
  #
13
12
  # module Blog
14
13
  # module Configurations
@@ -16,37 +15,36 @@ module Waves
16
15
  # host '127.0.0.1'
17
16
  # port 2000
18
17
  # reloadable [ Blog ]
19
- # log :level => :debug
18
+ # log :level => :debug
20
19
  # application do
21
20
  # use Rack::ShowExceptions
22
21
  # run Waves::Dispatchers::Default.new
23
- # end
22
+ # end
24
23
  # end
25
24
  # end
26
25
  # end
27
26
  #
28
- # There are three forms for accessing parameters:
27
+ # There are three forms for accessing attributes:
29
28
  #
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
29
+ # Waves.config.port # generic form - gets the value for current config
30
+ # Blog.configurations[:development].port # gets the value for a specified config
31
+ # Blog::Configurations::Development.port # Access a specific config constant directly
33
32
  #
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:
33
+ # Configuration data is inheritable, as shown in the example above. Typically, you
34
+ # would set data common to all configurations in the Default class, from which
35
+ # your variations inherit.
36
+ #
37
+ # You may define your own heritable attributes using the +attribute+ class method:
40
38
  #
41
39
  # class Default < Waves::Configurations::Default
42
- # attribute 'theme' # define a theme attribute
43
- # theme 'ultra' # give it a default
40
+ # attribute 'theme' # define an attribute named "theme"
41
+ # theme 'ultra' # set an inheritable default
44
42
  # end
45
43
  #
46
- # There are a number of reserved or built-in attributes. These are:
44
+ # Certain attributes are reserved for internal use by Waves:
47
45
  #
48
46
  # - application: configure the application for use with Rack
49
- # - database: takes a hash of parameters used to initalize the database; see below
47
+ # - database: initialization parameters needed by the ORM layer
50
48
  # - reloadable: an array of module names to reload; see below for more
51
49
  # - log: takes a hash of parameters; see below for more
52
50
  # - host: the host to bind the server to (string)
@@ -58,112 +56,130 @@ module Waves
58
56
  #
59
57
  # One of the really nice features of Rack is the ability to install "middleware"
60
58
  # components to optimize the way you handle requests. Waves exposes this ability
61
- # directly to the application developer via the +application+ configuration parameter.
62
- #
59
+ # directly to the application developer via the +application+ configuration method.
60
+ #
63
61
  # *Example*
64
- #
62
+ #
65
63
  # # Typical debugging configuration
66
64
  # application do
67
- # use Rack::ShowExceptions
68
- # run Waves::Dispatchers::Default.new
69
- # end
65
+ # use Rack::ShowExceptions
66
+ # run Waves::Dispatchers::Default.new
67
+ # end
70
68
  #
71
69
  # == Configuring Database Access
72
70
  #
73
- # The database parameter takes a hash with the following elements:
71
+ # The ORM layers provided with Waves use the +database+ attribute for connection initialization.
72
+ # Most ORMs take a hash for this purpose, with keys that may vary depending on the ORM and backend.
74
73
  #
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
74
+ # # Sequel with a MySQL db
75
+ # database :host => 'localhost', :adapter => 'mysql', :database => 'blog',
76
+ # :user => 'root', :password => 'guess'
80
77
  #
81
- # *Example*
78
+ # # Sequel with an SQLite db
79
+ # database :adapter => 'sqlite', :database => 'blog'
82
80
  #
83
- # database :host => host, :adapter => 'mysql', :database => 'blog',
84
- # :user => 'root', :password => 'guess'
81
+ # See the documentation for each ORM layer for details.
85
82
  #
86
- #
87
- # == Configuring Code Reloading
83
+ # == Configuring Code Reloading
84
+ #
85
+ # The +reloadable+ attribute takes an array of modules. Before every request, the default Waves
86
+ # dispatcher calls +reload+ on each listed module. The module should remove any reloadable constants
87
+ # currently defined in its namespace.
88
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:
89
+ # In a Waves application built on the Default foundation, +reload+ functionality is provided
90
+ # by AutoCode for the Configurations, Controllers, Helpers, Models, and Views modules.
91
+ #
92
+ # Listing only your application module will work in most cases:
96
93
  #
97
94
  # reloadable [ Blog ]
98
95
  #
99
- # although you could do this with several modules just as easily (say, your primary
100
- # application and several helper applications).
96
+ # As an alternative, you could reload only some of the modules within your application:
101
97
  #
102
- # == Configuring Logging
98
+ # reloadable [ Blog::Models, Blog::Controllers ]
103
99
  #
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.
100
+ # == Configuring Logging
101
+ #
102
+ # The +log+ configuration attribute takes hash with these keys:
103
+ # - :level - The log filter level. Uses Ruby's built in Logger class.
104
+ # - :output - A filename or IO object. Should be a filename if running as a daemon.
107
105
  #
108
106
  # *Examples*
109
107
  #
110
- # log :level => :info, :output => $stderr
111
- # log :level => :error, :output => 'log/blog.log'
108
+ # log :level => :info, :output => $stderr
109
+ # log :level => :error, :output => 'log/blog.log'
112
110
  #
113
111
 
114
- module Configurations
115
-
116
- class Base
112
+ module Configurations
117
113
 
114
+ class Base
118
115
  # Set the given attribute with the given value. Typically, you wouldn't
119
116
  # use this directly.
120
- def self.[]=( name, val )
121
- meta_def("_#{name}") { val }
122
- end
117
+ def self.[]=( name, val )
118
+ meta_def("_#{name}") { val }
119
+ end
123
120
 
124
121
  # Get the value of the given attribute. Typically, you wouldn't
125
122
  # use this directly.
126
- def self.[]( name ) ; send "_#{name}" ; end
123
+ def self.[]( name ) ; send "_#{name}" ; end
124
+
125
+ # Define a new attribute. After calling this, you can get and set the value
126
+ # using the attribute name as the method
127
+ def self.attribute( name )
128
+ meta_def(name) do |*args|
129
+ raise ArgumentError.new('Too many arguments.') if args.length > 1
130
+ args.length == 1 ? self[ name ] = args.first : self[ name ]
131
+ end
132
+ self[ name ] = nil
133
+ end
134
+
135
+ end
136
+
137
+ # The Default configuration defines sensible defaults for attributes required by Waves.
138
+ # debug true
139
+ # synchronize? true
140
+ # session :duration => 30.minutes, :path => '/tmp/sessions'
141
+ # log :level => :info, :output => $stderr
142
+ # reloadable []
143
+ class Default < Base
144
+
145
+ %w( host port ports log reloadable database session debug root synchronize? ).
146
+ each { |name| attribute(name) }
147
+
148
+ # Set the Rack handler, along with any specific options
149
+ # that need to be passed to the handler's #run method.
150
+ #
151
+ # When accessing the value
152
+ # (calling with no arguments), returns an array of the handler and options.
153
+ def self.handler(*args)
154
+ if args.length > 0
155
+ @rack_handler, @rack_handler_options = args
156
+ else
157
+ [ @rack_handler, @rack_handler_options ]
158
+ end
159
+ end
160
+
161
+ # Provides access to the Waves::MimeTypes class via the configuration. You
162
+ # can override #mime_types to return your own MIME types repository class.
163
+ def self.mime_types
164
+ Waves::MimeTypes
165
+ end
127
166
 
128
- # Define a new attribute. After calling this, you can get and set the value.
129
- def self.attribute( name )
130
- meta_def(name) do |*args|
131
- raise ArgumentError.new('Too many arguments.') if args.length > 1
132
- args.length == 1 ? self[ name ] = args.first : self[ name ]
133
- end
134
- self[ name ] = nil
135
- end
136
-
137
- end
138
-
139
- # The Default configuration provides a good starting point for your applications,
140
- # defining a number of attributes that are required by Waves.
141
- class Default < Base
142
-
143
- %w( host port ports log reloadable database session debug ).
144
- each { |name| attribute(name) }
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
167
+ # Defines the application for use with Rack. Treat this method like an
168
+ # instance of Rack::Builder
169
+ def self.application( &block )
170
+ if block_given?
171
+ self['application'] = Rack::Builder.new( &block )
172
+ else
173
+ self['application']
174
+ end
175
+ end
151
176
 
152
- # Defines the application for use with Rack.
153
- def self.application( &block )
154
- if block_given?
155
- self['application'] = Rack::Builder.new( &block )
156
- else
157
- self['application']
158
- end
159
- end
160
-
161
- debug true
162
- session :duration => 30.minutes, :path => '/tmp/sessions'
163
- log :level => :info, :output => $stderr
164
-
165
- end
166
- end
177
+ debug true ; synchronize? true
178
+ session :duration => 30.minutes, :path => '/tmp/sessions'
179
+ log :level => :info, :output => $stderr
180
+ reloadable []
181
+ end
182
+ end
167
183
  end
168
184
 
169
185
 
@@ -1,21 +1,20 @@
1
1
  module Waves
2
-
3
- class Console < Application
4
-
5
- class << self
6
-
7
- attr_reader :console
8
-
9
- def load( options={} )
10
- @console ||= Waves::Console.new( options )
11
- Kernel.load( :lib / 'startup.rb' )
12
- end
13
-
14
- # allow Waves::Console to act as The Console Instance
15
- def method_missing(*args); @console.send(*args); end
16
-
17
- end
18
-
19
- end
20
-
21
- end
2
+
3
+ class Console < Application
4
+
5
+ class << self
6
+
7
+ attr_reader :console
8
+
9
+ def load( options={} )
10
+ @console ||= Waves::Console.new( options )
11
+ end
12
+
13
+ # allow Waves::Console to act as The Console Instance
14
+ def method_missing(*args); @console.send(*args); end
15
+
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,9 @@
1
+ module Kernel
2
+ unless respond_to?(:debugger)
3
+ # Starts a debugging session if ruby-debug has been loaded (call waves-server --debugger to do load it).
4
+ def debugger
5
+ puts "debugger called"
6
+ Waves::Logger.info "\n***** Debugger requested, but was not available: Start server with --debugger to enable *****\n"
7
+ end
8
+ end
9
+ end
@@ -1,52 +1,58 @@
1
1
  require 'logger'
2
2
  module Waves
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
- #
22
- module Logger
23
-
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
+ #
22
+ module Logger
23
+
24
24
  class << self
25
-
25
+
26
26
  # Returns the object being used for output by the logger.
27
27
  def output
28
28
  @output ||= ( config[:output] ? File.expand_path( config[:output] ) : $stderr )
29
29
  end
30
+
30
31
  # Returns the active configuration for the logger.
31
- def config ; @config ||= Waves::Server.config.log ; end
32
+ def config
33
+ @config ||= Waves::Server.config.log
34
+ end
35
+
32
36
  # Returns the logging level used to filter logging events.
33
37
  def level ; @level ||= ::Logger.const_get( config[:level].to_s.upcase || 'INFO' ) ; end
38
+
34
39
  # 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
41
- end
42
- # Forwards logging methods to the logger.
43
- def method_missing(name,*args,&block)
44
- @log.send name,*args, &block
45
- end
40
+ def start
41
+ @log = config[:rotation] ?
42
+ ::Logger.new( output, config[:rotation].intern ) :
43
+ ::Logger.new( output )
44
+ @log.level = level
45
+ self
46
+ end
47
+
48
+ # Forwards logging methods to the logger.
49
+ def method_missing(name,*args,&block)
50
+ @log.send name,*args, &block if @log
51
+ end
52
+
53
+ end
46
54
 
47
- end
48
-
49
- end
55
+ end
50
56
 
51
57
  end
52
58