grippy-doozer 0.1.3 → 0.1.4

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 (51) hide show
  1. data/VERSION +1 -1
  2. data/doozer.gemspec +40 -3
  3. data/lib/doozer.rb +6 -1
  4. data/lib/doozer/app.rb +28 -19
  5. data/lib/doozer/configs.rb +18 -12
  6. data/lib/doozer/controller.rb +2 -2
  7. data/lib/doozer/exceptions.rb +12 -0
  8. data/lib/doozer/initializer.rb +8 -6
  9. data/lib/doozer/logger.rb +2 -1
  10. data/lib/doozer/partial.rb +3 -3
  11. data/lib/doozer/rackup/test.rb +2 -1
  12. data/lib/doozer/redirect.rb +1 -1
  13. data/lib/doozer/route.rb +34 -6
  14. data/lib/doozer/scripts/cluster.rb +9 -10
  15. data/lib/doozer/version.rb +1 -1
  16. data/lib/doozer/view_helpers.rb +100 -12
  17. data/lib/generator/generator.rb +0 -2
  18. data/templates/skeleton/config/environment.rb +1 -1
  19. data/templates/skeleton/config/routes.rb +2 -2
  20. data/test/doozer_test.rb +1 -1
  21. data/test/project/Rakefile +3 -0
  22. data/test/project/app/controllers/application_controller.rb +2 -0
  23. data/test/project/app/controllers/index_controller.rb +7 -0
  24. data/test/project/app/helpers/application_helper.rb +17 -0
  25. data/test/project/app/views/global/_header.html.erb +7 -0
  26. data/test/project/app/views/global/_navigation.html.erb +6 -0
  27. data/test/project/app/views/index/index.html.erb +108 -0
  28. data/test/project/app/views/layouts/default.html.erb +23 -0
  29. data/test/project/config/app.yml +31 -0
  30. data/test/project/config/database.yml +25 -0
  31. data/test/project/config/environment.rb +11 -0
  32. data/test/project/config/rack.rb +30 -0
  33. data/test/project/config/routes.rb +72 -0
  34. data/test/project/script/cluster +6 -0
  35. data/test/project/script/console +15 -0
  36. data/test/project/script/migrate +6 -0
  37. data/test/project/script/task +6 -0
  38. data/test/project/script/test +6 -0
  39. data/test/project/static/404.html +16 -0
  40. data/test/project/static/500.html +16 -0
  41. data/test/project/static/css/style.css +32 -0
  42. data/test/project/static/favicon.ico +0 -0
  43. data/test/project/static/js/application.js +1 -0
  44. data/test/project/static/js/jquery-1.3.min.js +19 -0
  45. data/test/project/static/robots.txt +5 -0
  46. data/test/project/test/fixtures/setup.rb +6 -0
  47. data/test/project/test/setup.rb +33 -0
  48. data/test/routing_test.rb +66 -0
  49. data/test/test_helper.rb +18 -2
  50. metadata +40 -3
  51. data/lib/doozer/README.rb +0 -40
@@ -11,7 +11,6 @@
11
11
  require 'optparse'
12
12
 
13
13
  APP_PATH = Dir.pwd if APP_PATH.nil?
14
-
15
14
  config = Doozer::Configs.symbolize_keys( YAML.load(File.read(File.join(APP_PATH,'config/app.yml'))) )
16
15
  clusters = Doozer::Configs.symbolize_keys(config[:clusters])
17
16
 
@@ -32,7 +31,7 @@ end
32
31
  # Automatically starts a test instance of your appserver on http://localhost:5000. (No -E flag is required for this command).
33
32
  def test
34
33
  cmd = "rackup #{@test_config}"
35
- p "Command: #{cmd} -p 5000 -E test -o 127.0.0.1"
34
+ printf "Command: #{cmd} -p 5000 -E test -o 127.0.0.1\n"
36
35
  system(cmd)
37
36
  end
38
37
 
@@ -40,23 +39,23 @@ end
40
39
  #
41
40
  # <b>deployment</b>: Automatically starts a new instance of your appserver for each defined cluster address:port
42
41
  def start
43
- p "Starting clusters..."
42
+ printf "Starting clusters...\n"
44
43
  for app in @apps
45
44
  if @env == :deployment
46
45
  #need to check if application has a pid file so we don't start
47
46
  pid_file = "#{APP_PATH}/log/doozer.#{app[:port]}.pid"
48
47
  raise "pid file already exists for #{pid_file}" if File.exist?(pid_file)
49
48
  cmd = "rackup #{@config} -p #{app[:port]} -E #{@env.to_s} -s #{@server} -o #{app[:ip]} #{@daemonize} -P #{pid_file}"
50
- p "Command: #{cmd}"
49
+ printf "Command: #{cmd}\n"
51
50
  system(cmd)
52
51
  else
53
52
  cmd = "rackup #{@config} -p #{app[:port]} -E #{@env.to_s} -s #{@server} -o #{app[:ip]}"
54
- p "Command: #{cmd}"
53
+ printf "Command: #{cmd}\n"
55
54
  system(cmd)
56
55
  break
57
56
  end
58
57
  end
59
- p "Did they start?"
58
+ printf "Did they start?\n"
60
59
  system("ps -aux | grep rackup")
61
60
  end
62
61
 
@@ -71,21 +70,21 @@ end
71
70
  # <b>deployment</b>: Automatically stops all instances of your appserver for each defined cluster address:port
72
71
  def stop
73
72
  system("ps -aux | grep rackup")
74
- p "Stoping clusters..."
73
+ printf "Stoping clusters...\n"
75
74
  for app in @apps
76
75
  if @env == :deployment
77
76
  pid_file = "#{APP_PATH}/log/doozer.#{app[:port]}.pid"
78
- p "Reading pid from #{pid_file}"
77
+ printf "Reading pid from #{pid_file}\n"
79
78
  if File.exist?(pid_file)
80
79
  File.open(pid_file, 'r'){ | f |
81
80
  pid = f.gets.to_i
82
- p "Shutting down process #{pid}"
81
+ printf "Shutting down process #{pid}\n"
83
82
  system("kill -9 #{pid}")
84
83
 
85
84
  }
86
85
  File.delete(pid_file)
87
86
  else
88
- p "pid file doesn't exist"
87
+ printf "pid file doesn't exist\n"
89
88
  end
90
89
  end
91
90
  end
@@ -2,7 +2,7 @@ module Doozer
2
2
  module Version
3
3
  MAJOR=0
4
4
  MINOR=1
5
- PATCH=3
5
+ PATCH=4
6
6
  STRING=[MAJOR, MINOR, PATCH].join('.')
7
7
  end
8
8
  end
@@ -1,8 +1,22 @@
1
1
  require 'digest/sha1'
2
2
 
3
3
  module Doozer
4
+
5
+ # ViewHelpers which are included in Controllers and Partials
4
6
  module ViewHelpers
5
-
7
+
8
+ # Returns a url from a hash of options. Expects option keys as symbols.
9
+ #
10
+ # :name - the route.name to parse additional options with
11
+ #
12
+ # :base_url - the base url of the request
13
+ #
14
+ # => route tokens are replace the key/values pairs in the options. if a route token is found in the options it is replaced with a 'MISSING-key' string.
15
+ #
16
+ # => all remaining options are added as key=value query string parameters
17
+ #
18
+ # You can also pass a opt as a string which just passed it through.
19
+ #
6
20
  def url(opt)
7
21
  url = ''
8
22
  if opt.kind_of? Hash
@@ -14,8 +28,10 @@ module Doozer
14
28
  return "MISSING-ROUTE-for-name-#{name}" if route .nil?
15
29
  url = "#{route.path}"
16
30
 
17
- # we need to swap out the tokens here...
18
- route.tokens.each {|token|
31
+ # we need to swap out the tokens here and account for formats on the end of the path
32
+ tokens = route.tokens
33
+ tokens.last.gsub!(Regexp.compile("\.#{route.format.to_s}$"), '') if route.format != :html if not route.tokens.empty?
34
+ tokens.each { |token|
19
35
  val = opt[token.to_sym]
20
36
  if val
21
37
  opt.delete(token.to_sym)
@@ -26,7 +42,7 @@ module Doozer
26
42
  }
27
43
  end
28
44
 
29
- # set base _url
45
+ # set base_url
30
46
  host = ""
31
47
  if opt[:base_url]
32
48
  host = opt.delete(:base_url)
@@ -42,15 +58,34 @@ module Doozer
42
58
  return url
43
59
  end
44
60
 
61
+ # Creates an html anchor tag.
62
+ #
63
+ # text - the text of the anchor tag
64
+ #
65
+ # opt - a hash of options which are passed to url(opt)
66
+ #
67
+ # prop - a hash of anchor tag attributes to add to the link
45
68
  def link(text='', opt={}, prop={})
46
69
  "<a href=\"#{url(opt)}\"#{hash_to_props(prop)}>#{text}</a>"
47
70
  end
48
-
71
+
72
+ # Creates an img tag.
73
+ #
74
+ # path - the src of the image tag
75
+ #
76
+ # prop - a hash of image tag attributes
49
77
  def img(path, prop={})
50
78
  path = timestamp_path(path)
51
79
  "<img src=\"#{path}\"#{hash_to_props(prop)} />"
52
80
  end
53
81
 
82
+ # Creates a stylesheet link tag.
83
+ #
84
+ # path - the href of the link tag
85
+ #
86
+ # prop - a hash of link tag attributes.
87
+ #
88
+ # => Defaults to :rel=>'stylesheet', :type=>'text/css', :media=>'all'
54
89
  def stylesheet(path, prop={})
55
90
  #<link rel="stylesheet" type="text/css" media="all" href="/css/style.css" />
56
91
  path = timestamp_path(path)
@@ -60,12 +95,33 @@ module Doozer
60
95
  "<link #{hash_to_props(prop)} href=\"#{path}\" />"
61
96
  end
62
97
 
98
+ # Creates a link tag for feeds.
99
+ #
100
+ # opt - a hash of options which are passed to url(opt)
101
+ #
102
+ # prop - a hash of link tag attributes.
103
+ #
104
+ # => Example: :rel=>'alternate', :type=>'application/rss+', :media=>'all'
105
+ def feed(opt={}, prop={})
106
+ "<link #{hash_to_props(prop)} href=\"#{url(opt)}\" />"
107
+ end
108
+
109
+ # Creates a script tag.
110
+ #
111
+ # path - the src of the javascript tag
112
+ #
113
+ # prop - a hash of script tag attributes.
114
+ #
115
+ # => Defaults to: :type=>'text/javascript'
63
116
  def javascript(path, prop={})
64
117
  path = timestamp_path(path)
65
118
  prop[:type] = 'text/javascript' if prop[:type].nil?
66
119
  "<script #{hash_to_props(prop)} src=\"#{path}\"></script>"
67
120
  end
68
121
 
122
+ # Creates metatags
123
+ #
124
+ # retuns a differnt metatag for each key/value added to @view[:meta] hash. See Doozer::Controller#meta for adding examples.
69
125
  def metatags
70
126
  #loop all metatags here...
71
127
  out=[]
@@ -75,7 +131,20 @@ module Doozer
75
131
  }
76
132
  out.join("")
77
133
  end
78
-
134
+
135
+ # Creates an authtoken form element
136
+ #
137
+ # By default, all post requests expect this value to be present unless overrided with Doozer::Controller#after_initialize
138
+ #
139
+ # You can customize the elemement id by passing arg[:id] to the method.
140
+ #
141
+ # The value contains an checksum of the app_name and cookie sid
142
+ def authtoken(args={})
143
+ id = args[:id] if args[:id]
144
+ "<input type=\"hidden\" id=\"#{id}_authtoken\" name=\"_authtoken\" value=\"#{generate_authtoken(@request.cookies['sid'])}\" />"
145
+ end
146
+
147
+ # Turns a hash of key/value pairs in to a key1="value1" key2="value2" key3="value3"
79
148
  def hash_to_props(opt={})
80
149
  props=[]
81
150
  opt.each { | key, value |
@@ -85,6 +154,9 @@ module Doozer
85
154
  return ""
86
155
  end
87
156
 
157
+ # Turns a hash of key/value pairs in querystring like key1=value%201&key2=value2&key3=value3
158
+ #
159
+ # All values are CGI.escaped for output
88
160
  def hash_to_qs(opt={})
89
161
  props=[]
90
162
  opt.each { | key, value |
@@ -93,24 +165,41 @@ module Doozer
93
165
  props.join("&")
94
166
  end
95
167
 
168
+ # Safe encodes a string by entity encodes all less then and greater then signs
169
+ #
96
170
  def h(s)
97
171
  s.gsub!(/</,'&lt;')
98
172
  s.gsub!(/>/,'&gt;')
99
173
  return s
100
174
  end
101
175
 
176
+ # Returns the base url configured in app.yml
177
+ #
102
178
  def base_url
103
179
  Doozer::Configs.base_url
104
180
  end
105
181
 
182
+ # Returns the env setting the application was loaded under (:development, :deployment, or :test)
183
+ #
106
184
  def rack_env
107
185
  Doozer::Configs.rack_env
108
186
  end
109
187
 
188
+ # Returns the app name configured in app.yml
189
+ #
110
190
  def app_name
111
191
  Doozer::Configs.app_name
112
192
  end
113
193
 
194
+ # Returns the app path the application was loaded in. This defaults to the path all scripts were executed from. In general, this is the root of your project directory unless specified otherwise.
195
+ #
196
+ def app_path
197
+ Doozer::Configs.app_path
198
+ end
199
+
200
+ # Returns the ip address of the server
201
+ #
202
+ # Automatically accounts for proxied requests and returns HTTP_X_FORWARDED_FOR if present.
114
203
  def ip
115
204
  if addr = @env['HTTP_X_FORWARDED_FOR']
116
205
  addr.split(',').last.strip
@@ -119,20 +208,19 @@ module Doozer
119
208
  end
120
209
  end
121
210
 
211
+ # Returns the domain name of the request
212
+ #
122
213
  def server_name
123
214
  @env['SERVER_NAME']
124
215
  end
125
216
 
217
+ # Returns the request path
218
+ #
126
219
  def path
127
220
  @env['REQUEST_PATH']
128
221
  end
129
222
 
130
- def authtoken(args={})
131
- id = args[:id] if args[:id]
132
- "<input type=\"hidden\" id=\"#{id}_authtoken\" name=\"_authtoken\" value=\"#{generate_authtoken(@request.cookies['sid'])}\" />"
133
- end
134
-
135
- # test if this person has a session with keys in it...
223
+ # Test if this person has a session with keys in it...
136
224
  def session?
137
225
  @session.empty?
138
226
  end
@@ -167,7 +167,6 @@ end
167
167
  }
168
168
  end
169
169
 
170
-
171
170
  def self.migrate(orm, name)
172
171
  return if help?(name, :migrate)
173
172
 
@@ -305,7 +304,6 @@ end
305
304
  end
306
305
  return false
307
306
  end
308
-
309
307
  def self.help(action=nil)
310
308
  h = ""
311
309
  case action
@@ -1,6 +1,6 @@
1
1
  # This file is loaded right after orm is initialized and right before app, controllers and models
2
2
  # place code here which is used throughout the application
3
- printf "Loading Environment..."
3
+ printf "Loading Environment... \n"
4
4
 
5
5
  Doozer::Initializer.after_orm do | config |
6
6
  # require 'doozer/plugins/paginate/init'
@@ -19,7 +19,7 @@ Formats
19
19
  Adding formats symbolzes automatically creates new routes for the formats symbols provided.
20
20
  The appropriate content-type is returned with the response.
21
21
  You can access the format with @format in your controllers.
22
- Supported formats are: :json, :js, :xml, :rss
22
+ Supported formats are: :json, :js, :xml, :rss, :atom
23
23
  All routes default to :html format
24
24
 
25
25
  Example:
@@ -32,7 +32,7 @@ Example:
32
32
  map.add :format_example, '/format_example', {:controller=>'index', :action=>'format_example', :status=>200}
33
33
  :json format
34
34
  map.add :format_example_json, '/format_example.json', {:controller=>'index', :action=>'format_example', :status=>200}
35
- :xml formate
35
+ :xml format
36
36
  map.add :format_example_xml, '/format_example.xml', {:controller=>'index', :action=>'format_example', :status=>200}
37
37
 
38
38
 
data/test/doozer_test.rb CHANGED
@@ -2,6 +2,6 @@ require 'test_helper'
2
2
 
3
3
  class DoozerTest < Test::Unit::TestCase
4
4
  should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
5
+ # flunk "hey buddy, you should probably rename this file and start testing for real"
6
6
  end
7
7
  end
@@ -0,0 +1,3 @@
1
+ require 'rake'
2
+ Dir['tasks/**/*.rake'].each { |t| load t }
3
+ task :default => :spec
@@ -0,0 +1,2 @@
1
+ class ApplicationController < Doozer::Controller
2
+ end
@@ -0,0 +1,7 @@
1
+ class IndexController < ApplicationController
2
+
3
+ def index
4
+ meta({:description=>"meta description goes here"})
5
+ end
6
+
7
+ end
@@ -0,0 +1,17 @@
1
+ # This is the default ApplicationHelper.
2
+ # Place methods here which are global to your application.
3
+ # By default all controllers include this file.
4
+ #
5
+ # To load a helper file into a controller:
6
+ #
7
+ # Example:
8
+ #
9
+ # -files: app_root/app/helpers/helper1_helper.rb, app_root/app/helpers/helper2_helper.rb
10
+ #
11
+ # -declare inside controller: self.require_view_helpers=[:helper1, :helper2]
12
+ #
13
+ # By default all helpers are automatically included into the base partial class.
14
+ # Be care to avoid methods with the same names between helper modules.
15
+ # The helpers are included alphabetically by file name
16
+ module ApplicationHelper
17
+ end
@@ -0,0 +1,7 @@
1
+ <div id="hdr">
2
+ <%=partial('global/navigation')%>
3
+ <span class="big"><%=link('Home', {:name=>:index})%></span>
4
+ </div>
5
+ <%#=img("/images/doozers.jpg", {:class=>'img'})%>
6
+
7
+
@@ -0,0 +1,6 @@
1
+ <div class="nav">
2
+ <p>
3
+ <span><%#=link('about us', {:name=>:about_us})%></span> |
4
+ <span><%#=link('contact', {:name=>:contact})%></span> |
5
+ </p>
6
+ </div>
@@ -0,0 +1,108 @@
1
+ <h2><span>Project Details</span></h2>
2
+ <p><span>Doozer is a <%=link('Rackup', 'http://rack.rubyforge.org/') %> application.</span></p>
3
+
4
+ <ul>
5
+ <li><span>Bare bones, lightweight, MVC framework.</span></li>
6
+ <li><span>Map routes to controller actions or completely separate applications.</span></li>
7
+ <li><span>ORM agnostic. use activerecord, data mapper, or sequel</span></li>
8
+ <li><span>Easy to define static directories</span></li>
9
+ <li><span>View Helpers for controllers</span></li>
10
+ <li><span>Layouts and Partials</span></li>
11
+ </ul>
12
+
13
+ <h3>Intro</h3>
14
+ <h4>Inspiration</h4>
15
+
16
+ <h3>Requirements</h3>
17
+ <h4>Rackup</h4>
18
+ <p>Rackup and its dependencies:</p>
19
+
20
+ <h3>File Structure</h3>
21
+ <p>This should look similar to rails</p>
22
+ <h4>Layout</h4>
23
+
24
+ <h3>Configs</h3>
25
+ <h4>Static</h4>
26
+ <h4>ORM</h4>
27
+ <h4>Clusters</h4>
28
+ <p>This needs to change names to something better. Maybe Server?</p>
29
+ <h3>Environment</h3>
30
+ <h4>Load Hooks</h4>
31
+ <h4>Settings</h4>
32
+
33
+ <h3>Load Order</h3>
34
+
35
+ <h3>Routes</h3>
36
+ <h4>Parameters</h4>
37
+ <h4>Magic</h4>
38
+ <p>A magic route is similar to "/:controller/:action" in rails.</p>
39
+ <p>Right now, these are tuned off in favor of explicitly having to declare them. Formats aren't extended to them yet. :()</p>
40
+ <h4>Bypassing Controllers</h4>
41
+ <p>You can declare a Rackup compatible app to call instead of a Doozer::Controller.</p>
42
+ <p>See config/routes.rb for more info.</p>
43
+ <h4>Layouts</h4>
44
+ <p>By default all html routes use the default.html.erb layout generated with the initial scaffolding.</p>
45
+ <p>Declare a route layout of :layout=>:view_name to override the default behavior.</p>
46
+
47
+
48
+ <h3>App</h3>
49
+ <h4>Security</h4>
50
+ <h5>Post Requests</h5>
51
+ <h6>Authenticity Token</h6>
52
+
53
+ <h4>Model</h4>
54
+ <h4>View</h4>
55
+ <h5>Route Tokens</h5>
56
+ <h4>Controller</h4>
57
+ <h5>Callbacks</h5>
58
+ As a controller is initialized, rendered, and finalized, you have the ability to influence the call stack.
59
+
60
+ <h6>after_initialize</h6>
61
+ <p>This is called after the controller is matched to the route and intialized.
62
+ <p>Use this hook to customize which actions shouldn't call before_filter and after_filter.</p>
63
+ <code>
64
+ @before_filter={:exclude=>[:action1, :action2]}
65
+ @after_filter={:exclude=>[:action1, :action2]}
66
+ </code>
67
+ <h6>before_filter</h6>
68
+ <p>By default all actions call this method. You can override it in your controller class by declaring:</p>
69
+ <code>
70
+ def before_filter
71
+ #code goes here....
72
+ end
73
+ </code>
74
+ <h6>after_filter</h6>
75
+ <p>By default all actions call this method. You can override it in your controller class by declaring:</p>
76
+ <code>
77
+ def after_filter
78
+ #code goes here....
79
+ end
80
+ </code>
81
+ <h5>Params</h5>
82
+ <h5>Route Tokens</h5>
83
+ <p>All route tokens are available as instance variables.</p>
84
+ <p>A route token of :id is available in an action and it's view as @id. You must pass this variable into a partial as a local variable.</p>
85
+
86
+ <h3>View Helpers</h3>
87
+ <h4>Redirects</h4>
88
+ <h4>Flash</h4>
89
+ <h4>Partial</h4>
90
+ <h4>Layout</h4>
91
+ <h4>Session</h4>
92
+
93
+ <h3>Generators</h3>
94
+ <h4>MVC Files</h4>
95
+
96
+ <h3>Scaffold</h3>
97
+ <h4>Building Project</h4>
98
+
99
+ <h3>Static</h3>
100
+
101
+ <h3>Testing</h3>
102
+
103
+ <h3>Tasks</h3>
104
+
105
+ <h3>App Start</h3>
106
+ <h4>Config</h4>
107
+ <h4>Start Command</h4>
108
+ <h5>Environments</h5>