waves 0.7.3 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.
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