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
@@ -1,56 +1,66 @@
1
1
  module Waves
2
-
2
+
3
3
  # Encapsulates the session associated with a given request. A session has an expiration
4
- # and path. You must set these in your configuration file. See Waves::Configuration for
5
- # more information.
6
- #
7
- class Session
8
-
9
- # Create a new session object using the given request. This is not necessarily the
10
- # same as constructing a new session. The session_id cookie for the request domain
11
- # is used to store a session id. The actual session data will be stored in a directory
12
- # specified by the application's configuration file.
13
- def initialize( request )
14
- @request = request
15
- @data ||= ( File.exist?( session_path ) ? load_session : {} )
16
- end
17
-
18
- # Save the session data. You shouldn't typically have to call this directly, since it
19
- # is called by Waves::Response#finish.
20
- def save
21
- if @data && @data.length > 0
22
- File.write( session_path, @data.to_yaml )
23
- @request.response.set_cookie( 'session_id',
24
- :value => session_id, :path => '/',
25
- :expires => Time.now + Waves::Server.config.session[:duration] )
26
- end
27
- end
28
-
29
- # Access a given data element of the session using the given key.
30
- def [](key) ; @data[key] ; end
31
- # Set the given data element of the session using the given key and value.
32
- def []=(key,val) ; @data[key] = val ; end
33
-
34
- private
35
-
36
- def session_id
37
- @session_id ||= ( @request.cookies['session_id'] || generate_session_id )
38
- end
39
-
40
- def generate_session_id # from Camping ...
41
- chars = [*'A'..'Z'] + [*'0'..'9'] + [*'a'..'z']
42
- (0..48).inject(''){|s,x| s+=chars[ rand(chars.length) ] }
43
- end
44
-
45
- def session_path
46
- Waves::Server.config.session[:path] / session_id
47
- end
48
-
49
- def load_session
50
- YAML.load( File.read( session_path ) )
51
- end
52
-
53
- end
54
-
4
+ # and path, which must be provided in a Waves::Configuration. Sensible defaults are defined
5
+ # in Waves::Configurations::Default
6
+ class Session
7
+
8
+ # Concoct a (probably) unique session id
9
+ def self.generate_session_id
10
+ # from Camping ...
11
+ chars = [*'A'..'Z'] + [*'0'..'9'] + [*'a'..'z']
12
+ (0..48).inject(''){|s,x| s+=chars[ rand(chars.length) ] }
13
+ end
14
+
15
+ # Create a new session object using the given request. This is not necessarily the
16
+ # same as constructing a new session. The session_id cookie for the request domain
17
+ # is used to store a session id. The actual session data will be stored in a directory
18
+ # specified by the application's configuration file.
19
+ def initialize( request )
20
+ @request = request
21
+ @data ||= ( File.exist?( session_path ) ? load_session : {} )
22
+ end
23
+
24
+ # Return the session data as a hash
25
+ def to_hash
26
+ @data.to_hash
27
+ end
28
+
29
+ def self.base_path
30
+ Waves::Application.instance.config.session[:path]
31
+ end
32
+
33
+ # Save the session data. You shouldn't typically have to call this directly, since it
34
+ # is called by Waves::Response#finish.
35
+ def save
36
+ if @data && @data.length > 0
37
+ File.write( session_path, @data.to_yaml )
38
+ @request.response.set_cookie( 'session_id',
39
+ :value => session_id, :path => '/',
40
+ :expires => Time.now + Waves::Server.config.session[:duration] )
41
+ end
42
+ end
43
+
44
+ # Access a given data element of the session using the given key.
45
+ def [](key) ; @data[key] ; end
46
+ # Set the given data element of the session using the given key and value.
47
+ def []=(key,val) ; @data[key] = val ; end
48
+
49
+ private
50
+
51
+ def session_id
52
+ @session_id ||= ( @request.cookies['session_id'] || Waves::Session.generate_session_id )
53
+ end
54
+
55
+ def session_path
56
+ Waves::Session.base_path / session_id
57
+ end
58
+
59
+ def load_session
60
+ YAML.load( File.read( session_path ) )
61
+ end
62
+
63
+ end
64
+
55
65
  end
56
-
66
+
@@ -0,0 +1,26 @@
1
+ namespace :cluster do
2
+
3
+ desc 'Start a cluster of waves applications.'
4
+ task :start do |task|
5
+ using_waves_src = defined?(WAVES) || ENV['WAVES'] || File.exist( File.dirname(__FILE__) / :waves )
6
+ script = using_waves_src ? :bin / 'waves-server' : 'waves-server'
7
+ ( Waves::Console.config.ports || [ Waves::Console.config.port ] ).each do |port|
8
+ cmd = "#{script} -p #{port} -c #{ENV['mode']||'development'} -d"
9
+ puts cmd ; `#{cmd}`
10
+ end
11
+ end
12
+
13
+ desc 'Stop a cluster of waves applications.'
14
+ task :stop do |task|
15
+ Dir[ :log / '*.pid' ].each do |pidfile|
16
+ pid = File.read(pidfile).to_i
17
+ puts "Stopping process #{pid} ..."
18
+ Process.kill( 'INT', pid ) rescue nil
19
+ end
20
+ end
21
+
22
+ desc 'Restart a cluster of waves applications.'
23
+ task :restart => [ :stop, :start ] do |task|
24
+ end
25
+
26
+ end
data/lib/tasks/gem.rb ADDED
@@ -0,0 +1,31 @@
1
+ namespace :gem do
2
+ desc "freeze a gem using gem=<gem name> [version=<gem version>]"
3
+ task :freeze do
4
+ raise "No gem specified" unless gem_name = ENV['gem']
5
+
6
+ require 'rubygems'
7
+ Gem.manage_gems
8
+
9
+ gem = (version = ENV['version']) ?
10
+ Gem.cache.search(gem_name, "= #{version}").first :
11
+ Gem.cache.search(gem_name).sort_by { |g| g.version }.last
12
+
13
+ version ||= gem.version.version rescue nil
14
+
15
+ target_dir = File.join(Waves::Configurations::Default.root, 'gems')
16
+ mkdir_p target_dir
17
+ sh "gem install #{gem_name} --version #{version} -i #{target_dir} --no-rdoc --no-ri"
18
+
19
+ puts "Unpacked #{gem_name} #{version} to '#{target_dir}'"
20
+ end
21
+
22
+ desc "unfreeze a gem using gem=<gem>"
23
+ task :unfreeze do
24
+ raise "No gem specified" unless gem_name = ENV['gem']
25
+
26
+ target_dir = File.join(Waves::Configurations::Default.root, 'gems')
27
+ ENV['GEM_HOME'] = target_dir # no install_dir option for gem uninstall
28
+
29
+ sh "gem uninstall #{gem_name}"
30
+ end
31
+ end
@@ -0,0 +1,80 @@
1
+ namespace :generate do
2
+
3
+ desc 'Generate a new controller, with name=<name>'
4
+ task :controller do |task|
5
+ name = ENV['name']
6
+ controller_name = name.camel_case
7
+ raise "Cannot generate Default yet" if controller_name == 'Default'
8
+
9
+ filename = File.expand_path "controllers/#{name}.rb"
10
+ if File.exist?(filename)
11
+ $stderr.puts "#{filename} already exists"
12
+ exit
13
+ end
14
+
15
+ controller = <<TEXT
16
+ module #{Waves.application.name}
17
+ module Controllers
18
+ class #{controller_name} < Default
19
+
20
+ end
21
+ end
22
+ end
23
+ TEXT
24
+
25
+ File.write( filename, controller )
26
+ end
27
+
28
+ desc 'Generate new view, with name=<name>'
29
+ task :view do |task|
30
+ name = ENV['name']
31
+ view_name = name.camel_case
32
+ raise "Cannot generate Default yet" if view_name == 'Default'
33
+
34
+ filename = File.expand_path "views/#{name}.rb"
35
+ if File.exist?(filename)
36
+ $stderr.puts "#{filename} already exists"
37
+ exit
38
+ end
39
+
40
+ view = <<TEXT
41
+ module #{Waves.application.name}
42
+ module Views
43
+ class #{view_name} < Default
44
+
45
+ end
46
+ end
47
+ end
48
+ TEXT
49
+
50
+ File.write( filename, view )
51
+ end
52
+
53
+ desc 'Generate a new helper, with name=<name>'
54
+ task :helper do |task|
55
+ name = ENV['name']
56
+ helper_name = name.camel_case
57
+ raise "Cannot generate Default yet" if helper_name == 'Default'
58
+
59
+ filename = File.expand_path "helpers/#{name}.rb"
60
+ if File.exist?(filename)
61
+ $stderr.puts "#{filename} already exists"
62
+ exit
63
+ end
64
+
65
+ helper = <<TEXT
66
+ module #{Waves.application.name}
67
+ module Helpers
68
+ module #{helper_name}
69
+ include Waves::Helpers::Default
70
+
71
+ end
72
+ end
73
+ end
74
+ TEXT
75
+
76
+ File.write( filename, helper )
77
+ end
78
+
79
+
80
+ end
@@ -0,0 +1,22 @@
1
+ class Hash
2
+
3
+ def stringify_keys
4
+ inject({}) do |options, (key, value)|
5
+ options[key.to_s] = value
6
+ options
7
+ end
8
+ end
9
+
10
+ # Destructively convert all keys to symbols.
11
+ def symbolize_keys!
12
+ keys.each do |key|
13
+ unless key.is_a?(Symbol)
14
+ self[key.to_sym] = self[key]
15
+ delete(key)
16
+ end
17
+ end
18
+ self
19
+ end
20
+
21
+
22
+ end
@@ -0,0 +1,194 @@
1
+ # Much love to Facets (more specifically English) for this module
2
+ # http://english.rubyforge.org/
3
+ # changed slightly in the hopes of one day implementing a different set
4
+ # of rules for different languages
5
+ # NOTE: this is NOT implemented yet.
6
+ # plural and singular work directly with the English class
7
+
8
+ module Inflect # :nodoc:
9
+ module InflectorMethods
10
+
11
+ # Define a general exception.
12
+ def word(singular, plural=nil)
13
+ plural = singular unless plural
14
+ singular_word(singular, plural)
15
+ plural_word(singular, plural)
16
+ end
17
+
18
+ # Define a singularization exception.
19
+ def singular_word(singular, plural)
20
+ @singular_of[plural] = singular
21
+ end
22
+
23
+ # Define a pluralization exception.
24
+ def plural_word(singular, plural)
25
+ @plural_of[singular] = plural
26
+ end
27
+
28
+ # Define a general rule.
29
+ def rule(singular, plural)
30
+ singular_rule(singular, plural)
31
+ plural_rule(singular, plural)
32
+ end
33
+
34
+ # Define a singularization rule.
35
+ def singular_rule(singular, plural)
36
+ @singular_rules << [singular, plural]
37
+ end
38
+
39
+ # Define a plurualization rule.
40
+ def plural_rule(singular, plural)
41
+ @plural_rules << [singular, plural]
42
+ end
43
+
44
+ # Read prepared singularization rules.
45
+ def singularization_rules
46
+ return @singularization_rules if @singularization_rules
47
+ sorted = @singular_rules.sort_by{ |s, p| "#{p}".size }.reverse
48
+ @singularization_rules = sorted.collect do |s, p|
49
+ [ /#{p}$/, "#{s}" ]
50
+ end
51
+ end
52
+
53
+ # Read prepared pluralization rules.
54
+ def pluralization_rules
55
+ return @pluralization_rules if @pluralization_rules
56
+ sorted = @plural_rules.sort_by{ |s, p| "#{s}".size }.reverse
57
+ @pluralization_rules = sorted.collect do |s, p|
58
+ [ /#{s}$/, "#{p}" ]
59
+ end
60
+ end
61
+
62
+ #
63
+ def plural_of
64
+ @plural_of
65
+ end
66
+
67
+ #
68
+ def singular_of
69
+ @singular_of
70
+ end
71
+
72
+ # Convert an English word from plurel to singular.
73
+ #
74
+ # "boys".singular #=> boy
75
+ # "tomatoes".singular #=> tomato
76
+ #
77
+ def singular(word)
78
+ if result = singular_of[word]
79
+ return result.dup
80
+ end
81
+ result = word.dup
82
+ singularization_rules.each do |(match, replacement)|
83
+ break if result.gsub!(match, replacement)
84
+ end
85
+ return result
86
+ end
87
+
88
+ # Convert an English word from singular to plurel.
89
+ #
90
+ # "boy".plural #=> boys
91
+ # "tomato".plural #=> tomatoes
92
+ #
93
+ def plural(word)
94
+ if result = plural_of[word]
95
+ return result.dup
96
+ end
97
+ #return self.dup if /s$/ =~ self # ???
98
+ result = word.dup
99
+ pluralization_rules.each do |(match, replacement)|
100
+ break if result.gsub!(match, replacement)
101
+ end
102
+ return result
103
+ end
104
+ end
105
+
106
+ class English # :nodoc:
107
+ @singular_of = {}
108
+ @plural_of = {}
109
+
110
+ @singular_rules = []
111
+ @plural_rules = []
112
+
113
+ class << self
114
+ include InflectorMethods
115
+ end
116
+
117
+ # One argument means singular and plural are the same.
118
+ word 'equipment'
119
+ word 'information'
120
+ word 'money'
121
+ word 'species'
122
+ word 'series'
123
+ word 'fish'
124
+ word 'sheep'
125
+ word 'moose'
126
+ word 'hovercraft'
127
+
128
+ # Two arguments defines a singular and plural exception.
129
+ word 'Swiss' , 'Swiss'
130
+ word 'life' , 'lives'
131
+ word 'wife' , 'wives'
132
+ word 'virus' , 'viri'
133
+ word 'octopus' , 'octopi'
134
+ word 'cactus' , 'cacti'
135
+ word 'goose' , 'geese'
136
+ word 'criterion' , 'criteria'
137
+ word 'alias' , 'aliases'
138
+ word 'status' , 'statuses'
139
+ word 'axis' , 'axes'
140
+ word 'crisis' , 'crises'
141
+ word 'testis' , 'testes'
142
+ word 'child' , 'children'
143
+ word 'person' , 'people'
144
+ word 'potato' , 'potatoes'
145
+ word 'tomato' , 'tomatoes'
146
+ word 'buffalo' , 'buffaloes'
147
+ word 'torpedo' , 'torpedoes'
148
+ word 'quiz' , 'quizes'
149
+ word 'matrix' , 'matrices'
150
+ word 'vertex' , 'vetices'
151
+ word 'index' , 'indices'
152
+ word 'ox' , 'oxen'
153
+ word 'mouse' , 'mice'
154
+ word 'louse' , 'lice'
155
+ word 'thesis' , 'theses'
156
+ word 'thief' , 'thieves'
157
+ word 'analysis' , 'analyses'
158
+
159
+ # One-way singularization exception (convert plural to singular).
160
+ singular_word 'cactus', 'cacti'
161
+
162
+ # General rules.
163
+ rule 'hive' , 'hives'
164
+ rule 'rf' , 'rves'
165
+ rule 'af' , 'aves'
166
+ rule 'ero' , 'eroes'
167
+ rule 'man' , 'men'
168
+ rule 'ch' , 'ches'
169
+ rule 'sh' , 'shes'
170
+ rule 'ss' , 'sses'
171
+ rule 'ta' , 'tum'
172
+ rule 'ia' , 'ium'
173
+ rule 'ra' , 'rum'
174
+ rule 'ay' , 'ays'
175
+ rule 'ey' , 'eys'
176
+ rule 'oy' , 'oys'
177
+ rule 'uy' , 'uys'
178
+ rule 'y' , 'ies'
179
+ rule 'x' , 'xes'
180
+ rule 'lf' , 'lves'
181
+ rule 'us' , 'uses'
182
+ rule '' , 's'
183
+
184
+ # One-way singular rules.
185
+ singular_rule 'of' , 'ofs' # proof
186
+ singular_rule 'o' , 'oes' # hero, heroes
187
+ singular_rule 'f' , 'ves'
188
+
189
+ # One-way plural rules.
190
+ plural_rule 'fe' , 'ves' # safe, wife
191
+ plural_rule 's' , 'ses'
192
+ end
193
+ end
194
+