dyoder-waves 0.7.3

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 (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
@@ -0,0 +1,94 @@
1
+ module Waves
2
+ module Mapping
3
+
4
+ # A set of pre-packed mapping rules for dealing with pretty URLs (that use names instead
5
+ # of numbers to identify resources). There are two modules.
6
+ # - GetRules, which defines all the GET methods for dealing with named resources
7
+ # - RestRules, which defines add, update, and delete rules using a REST style interface
8
+ #
9
+ module PrettyUrls
10
+
11
+ #
12
+ # GetRules defines the following URL conventions:
13
+ #
14
+ # /resources # => get a list of all instances of resource
15
+ # /resource/name # => get a specific instance of resource with the given name
16
+ # /resource/name/editor # => display an edit page for the given resource
17
+ #
18
+ module GetRules
19
+
20
+ def self.included(target)
21
+
22
+ target.module_eval do
23
+
24
+ extend Waves::Mapping
25
+
26
+ name = '([\w\-\_\.\+\@]+)'; model = '([\w\-]+)'
27
+
28
+ # get all resources for the given model
29
+ path %r{^/#{model}/?$}, :method => :get do | model |
30
+ resource( model.singular ) { controller { all } | view { |data| list( model => data ) } }
31
+ end
32
+
33
+ # get the given resource for the given model
34
+ path %r{^/#{model}/#{name}/?$}, :method => :get do | model, name |
35
+ resource( model ) { controller { find( name ) } | view { |data| show( model => data ) } }
36
+ end
37
+
38
+ # display an editor for the given resource / model
39
+ path %r{^/#{model}/#{name}/editor/?$}, :method => :get do | model, name |
40
+ resource( model ) { controller { find( name ) } | view { |data| editor( model => data ) } }
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+
49
+ #
50
+ # RestRules defines the following URL conventions:
51
+ #
52
+ # POST /resources # => add a new resource
53
+ # PUT /resource/name # => update the given resource
54
+ # DELETE /resource/name # => delete the given resource
55
+ #
56
+ module RestRules
57
+
58
+ def self.included(target)
59
+
60
+ target.module_eval do
61
+
62
+ extend Waves::Mapping
63
+
64
+ name = '([\w\-\_\.\+\@]+)'; model = '([\w\-]+)'
65
+
66
+ # create a new resource for the given model
67
+ path %r{^/#{model}/?$}, :method => :post do | model |
68
+ resource( model.singular ) do
69
+ instance = controller { create }
70
+ redirect( "/#{model.singular}/#{instance.name}/editor" )
71
+ end
72
+ end
73
+
74
+ # update the given resource for the given model
75
+ path %r{^/#{model}/#{name}/?$}, :method => :put do | model, name |
76
+ resource( model ) { controller { update( name ) }; redirect( url ) }
77
+ end
78
+
79
+ # delete the given resource for the given model
80
+ path %r{^/#{model}/#{name}/?$}, :method => :delete do | model, name |
81
+ resource( model ) { controller { delete( name ) } }
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+
92
+ end
93
+
94
+ end
@@ -0,0 +1,61 @@
1
+ require 'erubis'
2
+
3
+ module Erubis
4
+
5
+ # This is added to the Erubis Content class to allow the same helper methods
6
+ # to be used with both Markaby and Erubis.
7
+ class Context
8
+ include Waves::Helpers::UrlHelper
9
+ include Waves::Helpers::TagHelper
10
+
11
+ def <<(s)
12
+ eval("_buf", @binding).concat s # add to rendered output
13
+ end
14
+
15
+ def capture
16
+ eval("_context.push(_buf); _buf = ''", @binding) #ignore output from that eval, will be added via "<<"
17
+ result = Erubis::Eruby.new(yield).result @binding
18
+ eval("_buf = _context.pop", @binding)
19
+ result
20
+ end
21
+
22
+ def render(eruby)
23
+ unless @binding
24
+ @binding = binding
25
+ eval("_buf = ''; _context = []", @binding)
26
+ end
27
+ eruby.result @binding
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ module Waves
35
+
36
+ module Renderers
37
+
38
+ class Erubis
39
+
40
+ include Renderers::Mixin
41
+
42
+ extension :erb
43
+
44
+ def self.render( path, assigns )
45
+ eruby = ::Erubis::Eruby.new( template( path ) )
46
+ helper = helper( path )
47
+ context = ::Erubis::Context.new
48
+ context.meta_eval { include( helper ) ; }
49
+ context.instance_eval do
50
+ assigns.each do |key,val|
51
+ instance_variable_set("@#{key}",val)
52
+ end
53
+ end
54
+ context.render(eruby)
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,33 @@
1
+ require 'markaby'
2
+
3
+ ::Markaby::Builder.set( :indent, 2 )
4
+
5
+ module Waves
6
+
7
+ module Renderers
8
+
9
+ class Markaby
10
+
11
+ include Renderers::Mixin
12
+
13
+ extension :mab
14
+
15
+ # capture needed here for content fragments, otherwise
16
+ # you'll just get the last tag's output ...
17
+ # def self.capture( template )
18
+ # "capture { #{template} }"
19
+ # end
20
+
21
+ def self.render( path, assigns )
22
+ builder = ::Markaby::Builder.new( assigns )
23
+ helper = helper( path )
24
+ builder.meta_eval { include( helper ) }
25
+ builder.instance_eval( template( path ) )
26
+ builder.to_s
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,53 @@
1
+ module Waves
2
+
3
+ module Renderers
4
+
5
+ extend Autocode
6
+ # autoload :renderers, Class
7
+
8
+ # The renderers mixin provides a number of methods to simplify writing new renderers.
9
+ # Just include this in your Renderer class and write your render method.
10
+ module Mixin
11
+
12
+ # Adds the following methods to the target class:
13
+ #
14
+ # - extension: allows you to set or get the extension used by this renderer.
15
+ #
16
+ # Renderers::Markaby.extension 'foo' # tell Waves to use .foo as Markaby extension
17
+ #
18
+ # - filename: generate a filename for the template based on a logical path.
19
+ # - template: read the template from the file corresponding to the given logical path.
20
+ # - helper: return a helper module that corresponds to the given logical path.
21
+ #
22
+ def self.included(target)
23
+ class << target
24
+
25
+ def extension(*args)
26
+ return @extension if args.length == 0
27
+ @extension = args.first
28
+ end
29
+
30
+ def filename(path)
31
+ :templates / "#{path}.#{self.extension}"
32
+ end
33
+
34
+ def render(path,args=nil)
35
+ end
36
+
37
+ def template( path )
38
+ File.read( filename( path ) )
39
+ end
40
+
41
+ def helper( path )
42
+ Waves.application.helpers[
43
+ File.basename( File.dirname( path ) ).camel_case ]
44
+ end
45
+ end
46
+ end
47
+
48
+
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,65 @@
1
+ # See the README for an overview.
2
+ module Waves
3
+
4
+ class << self
5
+
6
+ # Access the principal Waves application.
7
+ attr_reader :application
8
+
9
+ # Register a module as a Waves application.
10
+ # Also, initialize the database connection if necessary.
11
+ def << ( app )
12
+ @application = app if Module === app
13
+ app.database if app.respond_to? 'database'
14
+ end
15
+
16
+ def instance ; Waves::Application.instance ; end
17
+
18
+ def method_missing(name,*args,&block)
19
+ instance.send(name,*args,&block)
20
+ end
21
+
22
+ end
23
+
24
+ # An application in Waves is anything that provides access to the Waves
25
+ # runtime and the registered Waves applications. This includes both
26
+ # Waves::Server and Waves::Console. Waves::Application is *not* the actual
27
+ # application module(s) registered as Waves applications. To access the
28
+ # main Waves application, you can use +Waves+.+application+.
29
+ class Application
30
+
31
+ class << self; attr_accessor :instance; end
32
+
33
+ # Accessor for options passed to the application. Valid options include
34
+ attr_reader :options
35
+
36
+ # Create a new Waves application instance.
37
+ def initialize( options={} )
38
+ @options = options
39
+ Dir.chdir options[:directory] if options[:directory]
40
+ Application.instance = self
41
+ Kernel.load( :lib / 'application.rb' ) if Waves.application.nil?
42
+ end
43
+
44
+ def synchronize( &block ) ; ( @mutex ||= Mutex.new ).synchronize( &block ) ; end
45
+
46
+ # The 'mode' of the application determines which configuration it will run under.
47
+ def mode ; @mode ||= @options[:mode]||:development ; end
48
+
49
+ # Debug is true if debug is set to true in the current configuration.
50
+ def debug? ; config.debug ; end
51
+
52
+ # Access the current configuration. *Example:* +Waves::Server.config+
53
+ def config ; Waves.application.configurations[ mode ] ; end
54
+
55
+ # Access the mappings for the application.
56
+ def mapping ; Waves.application.configurations[ :mapping ] ; end
57
+
58
+ # Reload the modules specified in the current configuration.
59
+ def reload ; config.reloadable.each { |mod| mod.reload } ; end
60
+
61
+ # Returns the cache set for the current configuration
62
+ def cache ; config.cache ; end
63
+ end
64
+
65
+ end
@@ -0,0 +1,180 @@
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.
7
+ #
8
+ # The form for configuration parameters to use the parameter name as a method name. Passing
9
+ # in a parameter sets the value.
10
+ #
11
+ # == Example
12
+ #
13
+ # module Blog
14
+ # module Configurations
15
+ # class Development < Default
16
+ # host '127.0.0.1'
17
+ # port 2000
18
+ # reloadable [ Blog ]
19
+ # log :level => :debug
20
+ # application do
21
+ # use Rack::ShowExceptions
22
+ # run Waves::Dispatchers::Default.new
23
+ # end
24
+ # end
25
+ # end
26
+ # end
27
+ #
28
+ # There are three forms for accessing parameters:
29
+ #
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
33
+ #
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:
40
+ #
41
+ # class Default < Waves::Configurations::Default
42
+ # attribute 'theme' # define a theme attribute
43
+ # theme 'ultra' # give it a default
44
+ # end
45
+ #
46
+ # There are a number of reserved or built-in attributes. These are:
47
+ #
48
+ # - application: configure the application for use with Rack
49
+ # - database: takes a hash of parameters used to initalize the database; see below
50
+ # - reloadable: an array of module names to reload; see below for more
51
+ # - log: takes a hash of parameters; see below for more
52
+ # - host: the host to bind the server to (string)
53
+ # - port: the port for the server to listen on (number)
54
+ # - ports: used by the cluster:start task for clustering servers (array of numbers)
55
+ # - debug: true if running in "debug" mode, which automatically reloads code
56
+ #
57
+ # == Configuring The Rack Application
58
+ #
59
+ # One of the really nice features of Rack is the ability to install "middleware"
60
+ # components to optimize the way you handle requests. Waves exposes this ability
61
+ # directly to the application developer via the +application+ configuration parameter.
62
+ #
63
+ # *Example*
64
+ #
65
+ # # Typical debugging configuration
66
+ # application do
67
+ # use Rack::ShowExceptions
68
+ # run Waves::Dispatchers::Default.new
69
+ # end
70
+ #
71
+ # == Configuring Database Access
72
+ #
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*
82
+ #
83
+ # database :host => 'localhost', :adapter => 'mysql', :database => 'blog',
84
+ # :user => 'root', :password => 'guess'
85
+ #
86
+ #
87
+ # == Configuring Code Reloading
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:
96
+ #
97
+ # reloadable [ Blog ]
98
+ #
99
+ # although you could do this with several modules just as easily (say, your primary
100
+ # application and several helper applications).
101
+ #
102
+ # == Configuring Logging
103
+ #
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.
107
+ #
108
+ # *Examples*
109
+ #
110
+ # log :level => :info, :output => $stderr
111
+ # log :level => :error, :output => 'log/blog.log'
112
+ #
113
+
114
+ module Configurations
115
+
116
+ class Base
117
+
118
+ # Set the given attribute with the given value. Typically, you wouldn't
119
+ # use this directly.
120
+ def self.[]=( name, val )
121
+ meta_def("_#{name}") { val }
122
+ end
123
+
124
+ # Get the value of the given attribute. Typically, you wouldn't
125
+ # use this directly.
126
+ def self.[]( name ) ; send "_#{name}" ; end
127
+
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 root ).
144
+ each { |name| attribute(name) }
145
+
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.
149
+ def self.handler(*args)
150
+ if args.length > 0
151
+ @rack_handler, @rack_handler_options = args
152
+ else
153
+ [ @rack_handler, @rack_handler_options ]
154
+ end
155
+ end
156
+
157
+ # Provide access to the Waves::MimeTypes class via the configuration. You
158
+ # could potentially point this to your own MIME types repository class.
159
+ def self.mime_types
160
+ Waves::MimeTypes
161
+ end
162
+
163
+ # Defines the application for use with Rack.
164
+ def self.application( &block )
165
+ if block_given?
166
+ self['application'] = Rack::Builder.new( &block )
167
+ else
168
+ self['application']
169
+ end
170
+ end
171
+
172
+ debug true
173
+ session :duration => 30.minutes, :path => '/tmp/sessions'
174
+ log :level => :info, :output => $stderr
175
+ reloadable []
176
+ end
177
+ end
178
+ end
179
+
180
+