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.
Files changed (83) hide show
  1. data/app/bin/waves-console +1 -0
  2. data/app/bin/waves-server +1 -0
  3. data/app/configurations/development.rb.erb +5 -6
  4. data/app/configurations/mapping.rb.erb +1 -2
  5. data/app/configurations/production.rb.erb +2 -2
  6. data/app/controllers/.gitignore +0 -0
  7. data/app/doc/.gitignore +0 -0
  8. data/app/helpers/.gitignore +0 -0
  9. data/app/lib/application.rb.erb +4 -2
  10. data/app/lib/tasks/.gitignore +0 -0
  11. data/app/log/.gitignore +0 -0
  12. data/app/models/.gitignore +0 -0
  13. data/app/public/css/.gitignore +0 -0
  14. data/app/public/flash/.gitignore +0 -0
  15. data/app/public/images/.gitignore +0 -0
  16. data/app/public/javascript/.gitignore +0 -0
  17. data/app/schema/migrations/.gitignore +0 -0
  18. data/app/tmp/sessions/.gitignore +0 -0
  19. data/app/views/.gitignore +0 -0
  20. data/bin/waves +29 -46
  21. data/bin/waves-console +1 -1
  22. data/bin/waves-server +1 -1
  23. data/lib/commands/waves-console.rb +0 -3
  24. data/lib/controllers/base.rb +11 -0
  25. data/lib/controllers/mixin.rb +39 -32
  26. data/lib/dispatchers/base.rb +37 -22
  27. data/lib/dispatchers/default.rb +25 -11
  28. data/lib/foundations/default.rb +6 -8
  29. data/lib/foundations/simple.rb +13 -0
  30. data/lib/helpers/asset_helper.rb +67 -0
  31. data/lib/helpers/common.rb +4 -0
  32. data/lib/helpers/default.rb +13 -0
  33. data/lib/helpers/form.rb +1 -0
  34. data/lib/helpers/number_helper.rb +25 -0
  35. data/lib/helpers/tag_helper.rb +58 -0
  36. data/lib/helpers/url_helper.rb +77 -0
  37. data/lib/layers/default_errors.rb +7 -5
  38. data/lib/layers/mvc.rb +54 -0
  39. data/lib/layers/orm/active_record.rb +93 -0
  40. data/lib/layers/orm/active_record/migrations/empty.rb.erb +9 -0
  41. data/lib/layers/orm/active_record/tasks/generate.rb +28 -0
  42. data/lib/layers/orm/active_record/tasks/schema.rb +22 -0
  43. data/lib/layers/orm/data_mapper.rb +38 -0
  44. data/lib/layers/orm/filebase.rb +22 -0
  45. data/lib/layers/orm/migration.rb +79 -0
  46. data/lib/layers/orm/sequel.rb +86 -0
  47. data/lib/layers/orm/sequel/migrations/empty.rb.erb +9 -0
  48. data/lib/layers/orm/sequel/tasks/generate.rb +28 -0
  49. data/lib/layers/orm/sequel/tasks/schema.rb +16 -0
  50. data/lib/layers/simple.rb +35 -0
  51. data/lib/layers/simple_errors.rb +11 -5
  52. data/lib/mapping/mapping.rb +61 -24
  53. data/lib/mapping/pretty_urls.rb +5 -3
  54. data/lib/renderers/erubis.rb +3 -1
  55. data/lib/renderers/mixin.rb +1 -4
  56. data/lib/runtime/application.rb +12 -8
  57. data/lib/runtime/blackboard.rb +57 -0
  58. data/lib/runtime/configuration.rb +60 -55
  59. data/lib/runtime/logger.rb +8 -1
  60. data/lib/runtime/request.rb +5 -4
  61. data/lib/runtime/response.rb +3 -3
  62. data/lib/runtime/response_mixin.rb +3 -0
  63. data/lib/runtime/response_proxy.rb +4 -1
  64. data/lib/runtime/server.rb +18 -5
  65. data/lib/runtime/session.rb +20 -10
  66. data/lib/tasks/cluster.rb +2 -1
  67. data/lib/tasks/generate.rb +76 -11
  68. data/lib/utilities/hash.rb +31 -0
  69. data/lib/utilities/inflect.rb +86 -170
  70. data/lib/utilities/inflect/english.rb +84 -0
  71. data/lib/utilities/integer.rb +23 -16
  72. data/lib/utilities/module.rb +19 -15
  73. data/lib/utilities/object.rb +22 -14
  74. data/lib/utilities/proc.rb +13 -6
  75. data/lib/utilities/string.rb +58 -44
  76. data/lib/utilities/symbol.rb +4 -1
  77. data/lib/views/base.rb +9 -0
  78. data/lib/views/mixin.rb +3 -1
  79. data/lib/waves.rb +15 -13
  80. metadata +50 -25
  81. data/lib/utilities/kernel.rb +0 -34
  82. data/lib/verify/mapping.rb +0 -29
  83. data/lib/verify/request.rb +0 -40
@@ -66,14 +66,16 @@ module Waves
66
66
  # create a new resource for the given model
67
67
  path %r{^/#{model}/?$}, :method => :post do | model |
68
68
  resource( model.singular ) do
69
- instance = controller { create }
70
- redirect( "/#{model.singular}/#{instance.name}/editor" )
69
+ controller do
70
+ instance = create
71
+ redirect( "/#{model_name}/#{instance.name}/editor" )
72
+ end
71
73
  end
72
74
  end
73
75
 
74
76
  # update the given resource for the given model
75
77
  path %r{^/#{model}/#{name}/?$}, :method => :put do | model, name |
76
- resource( model ) { controller { update( name ) }; redirect( url ) }
78
+ resource( model ) { controller { update( name ); redirect( url ) } }
77
79
  end
78
80
 
79
81
  # delete the given resource for the given model
@@ -1,12 +1,14 @@
1
1
  require 'erubis'
2
2
 
3
- module Erubis
3
+ module Erubis # :nodoc:
4
4
 
5
5
  # This is added to the Erubis Content class to allow the same helper methods
6
6
  # to be used with both Markaby and Erubis.
7
7
  class Context
8
8
  include Waves::Helpers::UrlHelper
9
9
  include Waves::Helpers::TagHelper
10
+ include Waves::Helpers::AssetHelper
11
+ include Waves::Helpers::NumberHelper
10
12
 
11
13
  def <<(s)
12
14
  eval("_buf", @binding).concat s # add to rendered output
@@ -1,9 +1,6 @@
1
1
  module Waves
2
2
 
3
- module Renderers
4
-
5
- extend Autocode
6
- # autoload :renderers, Class
3
+ module Renderers # :nodoc:
7
4
 
8
5
  # The renderers mixin provides a number of methods to simplify writing new renderers.
9
6
  # Just include this in your Renderer class and write your render method.
@@ -7,10 +7,8 @@ module Waves
7
7
  attr_reader :application
8
8
 
9
9
  # Register a module as a Waves application.
10
- # Also, initialize the database connection if necessary.
11
10
  def << ( app )
12
11
  @application = app if Module === app
13
- app.database if app.respond_to? 'database'
14
12
  end
15
13
 
16
14
  def instance ; Waves::Application.instance ; end
@@ -28,9 +26,9 @@ module Waves
28
26
  # main Waves application, you can use +Waves+.+application+.
29
27
  class Application
30
28
 
31
- class << self; attr_accessor :instance; end
29
+ class << self; attr_accessor :instance; end
32
30
 
33
- # Accessor for options passed to the application. Valid options include
31
+ # Accessor for options passed to the application.
34
32
  attr_reader :options
35
33
 
36
34
  # Create a new Waves application instance.
@@ -41,16 +39,22 @@ module Waves
41
39
  Kernel.load( :lib / 'application.rb' ) if Waves.application.nil?
42
40
  end
43
41
 
44
- def synchronize( &block ) ; ( @mutex ||= Mutex.new ).synchronize( &block ) ; end
42
+ def synchronize( &block )
43
+ ( @mutex ||= Mutex.new ).synchronize( &block )
44
+ end
45
45
 
46
46
  # The 'mode' of the application determines which configuration it will run under.
47
- def mode ; @mode ||= @options[:mode]||:development ; end
48
-
47
+ def mode
48
+ @mode ||= @options[:mode]||:development
49
+ end
50
+
49
51
  # Debug is true if debug is set to true in the current configuration.
50
52
  def debug? ; config.debug ; end
51
53
 
52
54
  # Access the current configuration. *Example:* +Waves::Server.config+
53
- def config ; Waves.application.configurations[ mode ] ; end
55
+ def config
56
+ Waves.application.configurations[ mode ]
57
+ end
54
58
 
55
59
  # Access the mappings for the application.
56
60
  def mapping ; Waves.application.configurations[ :mapping ] ; end
@@ -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,12 +1,11 @@
1
1
  module Waves
2
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.
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
10
  # == Example
12
11
  #
@@ -25,28 +24,27 @@ module Waves
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.
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.
37
36
  #
38
- # To define your own attributes, and still make them inheritable, you should use
39
- # the +attribute+ class method, like this:
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,7 +56,7 @@ 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.
59
+ # directly to the application developer via the +application+ configuration method.
62
60
  #
63
61
  # *Example*
64
62
  #
@@ -70,51 +68,50 @@ module Waves
70
68
  #
71
69
  # == Configuring Database Access
72
70
  #
73
- # The database parameter takes a hash with the following elements:
74
- #
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
80
- #
81
- # *Example*
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.
82
73
  #
74
+ # # Sequel with a MySQL db
83
75
  # database :host => 'localhost', :adapter => 'mysql', :database => 'blog',
84
76
  # :user => 'root', :password => 'guess'
85
77
  #
78
+ # # Sequel with an SQLite db
79
+ # database :adapter => 'sqlite', :database => 'blog'
80
+ #
81
+ # See the documentation for each ORM layer for details.
86
82
  #
87
83
  # == Configuring Code Reloading
88
84
  #
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:
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
+ #
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:
97
+ #
98
+ # reloadable [ Blog::Models, Blog::Controllers ]
101
99
  #
102
100
  # == Configuring Logging
103
101
  #
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.
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
112
  module Configurations
115
113
 
116
114
  class Base
117
-
118
115
  # Set the given attribute with the given value. Typically, you wouldn't
119
116
  # use this directly.
120
117
  def self.[]=( name, val )
@@ -125,7 +122,8 @@ module Waves
125
122
  # use this directly.
126
123
  def self.[]( name ) ; send "_#{name}" ; end
127
124
 
128
- # Define a new attribute. After calling this, you can get and set the value.
125
+ # Define a new attribute. After calling this, you can get and set the value
126
+ # using the attribute name as the method
129
127
  def self.attribute( name )
130
128
  meta_def(name) do |*args|
131
129
  raise ArgumentError.new('Too many arguments.') if args.length > 1
@@ -136,16 +134,22 @@ module Waves
136
134
 
137
135
  end
138
136
 
139
- # The Default configuration provides a good starting point for your applications,
140
- # defining a number of attributes that are required by Waves.
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 []
141
143
  class Default < Base
142
144
 
143
- %w( host port ports log reloadable database session debug root ).
145
+ %w( host port ports log reloadable database session debug root synchronize? ).
144
146
  each { |name| attribute(name) }
145
147
 
146
- # Set the handler for use with Rack, along with any handler-specific options
147
- # that will be passed to the handler's #run method. When accessing the value
148
- # (calling with no arguments) returns an array of the handler and options.
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.
149
153
  def self.handler(*args)
150
154
  if args.length > 0
151
155
  @rack_handler, @rack_handler_options = args
@@ -154,13 +158,14 @@ module Waves
154
158
  end
155
159
  end
156
160
 
157
- # Provide access to the Waves::MimeTypes class via the configuration. You
158
- # could potentially point this to your own MIME types repository class.
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.
159
163
  def self.mime_types
160
164
  Waves::MimeTypes
161
165
  end
162
166
 
163
- # Defines the application for use with Rack.
167
+ # Defines the application for use with Rack. Treat this method like an
168
+ # instance of Rack::Builder
164
169
  def self.application( &block )
165
170
  if block_given?
166
171
  self['application'] = Rack::Builder.new( &block )
@@ -169,7 +174,7 @@ module Waves
169
174
  end
170
175
  end
171
176
 
172
- debug true
177
+ debug true ; synchronize? true
173
178
  session :duration => 30.minutes, :path => '/tmp/sessions'
174
179
  log :level => :info, :output => $stderr
175
180
  reloadable []
@@ -27,18 +27,25 @@ module Waves
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
40
  def start
36
41
  @log = config[:rotation] ?
37
42
  ::Logger.new( output, config[:rotation].intern ) :
38
43
  ::Logger.new( output )
39
44
  @log.level = level
45
+ @log.datetime_format = "%Y-%m-%d %H:%M:%S "
40
46
  self
41
47
  end
48
+
42
49
  # Forwards logging methods to the logger.
43
50
  def method_missing(name,*args,&block)
44
51
  @log.send name,*args, &block if @log
@@ -1,12 +1,10 @@
1
1
  module Waves
2
- # Waves::Request represents an HTTP request and has methods for accessing anything
3
- # relating to the request. See Rack::Request for more information, since many methods
4
- # are actually delegated to Rack::Request.
2
+ # Waves::Request represents an HTTP request and provides convenient methods for accessing request attributes. See Rack::Request for documentation of any method not defined here.
5
3
  class Request
6
4
 
7
5
  class ParseError < Exception ; end
8
6
 
9
- attr_reader :response, :session
7
+ attr_reader :response, :session, :blackboard
10
8
 
11
9
  # Create a new request. Takes a env parameter representing the request passed in from Rack.
12
10
  # You shouldn't need to call this directly.
@@ -14,7 +12,10 @@ module Waves
14
12
  @request = Rack::Request.new( env )
15
13
  @response = Waves::Response.new( self )
16
14
  @session = Waves::Session.new( self )
15
+ @blackboard = Waves::Blackboard.new( self )
17
16
  end
17
+
18
+ def rack_request; @request; end
18
19
 
19
20
  # Accessor not explicitly defined by Waves::Request are delegated to Rack::Request.
20
21
  # Check the Rack documentation for more information.
@@ -1,9 +1,7 @@
1
1
  module Waves
2
2
  # Waves::Response represents an HTTP response and has methods for constructing a response.
3
3
  # These include setters for +content_type+, +content_length+, +location+, and +expires+
4
- # headers. You may also set the headers directly using the [] operator. If you don't find
5
- # what you are looking for here, check the documentation for Rack::Response since many
6
- # methods for this class are delegated to Rack::Response.
4
+ # headers. You may also set the headers directly using the [] operator. See Rack::Response for documentation of any method not defined here.
7
5
  class Response
8
6
 
9
7
  attr_reader :request
@@ -13,6 +11,8 @@ module Waves
13
11
  @request = request
14
12
  @response = Rack::Response.new
15
13
  end
14
+
15
+ def rack_response; @response; end
16
16
 
17
17
  %w( Content-Type Content-Length Location Expires ).each do |header|
18
18
  define_method( header.downcase.gsub('-','_')+ '=' ) do | val |
@@ -30,6 +30,9 @@ module Waves
30
30
  def not_found; request.not_found; end
31
31
  # Access the Waves::Logger.
32
32
  def log; Waves::Logger; end
33
+ # Access the Blackboard
34
+ def blackboard; request.blackboard; end
35
+
33
36
  end
34
37
 
35
38
  end