grippy-doozer 0.1.0

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 (72) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +57 -0
  5. data/Rakefile +59 -0
  6. data/VERSION +1 -0
  7. data/bin/doozer +8 -0
  8. data/doozer.gemspec +114 -0
  9. data/lib/doozer/README.rb +40 -0
  10. data/lib/doozer/active_support/array.rb +14 -0
  11. data/lib/doozer/active_support/class.rb +221 -0
  12. data/lib/doozer/active_support/date_time.rb +23 -0
  13. data/lib/doozer/active_support/object.rb +43 -0
  14. data/lib/doozer/active_support/time.rb +32 -0
  15. data/lib/doozer/app.rb +265 -0
  16. data/lib/doozer/configs.rb +131 -0
  17. data/lib/doozer/controller.rb +335 -0
  18. data/lib/doozer/extend.rb +10 -0
  19. data/lib/doozer/initializer.rb +95 -0
  20. data/lib/doozer/lib.rb +32 -0
  21. data/lib/doozer/logger.rb +11 -0
  22. data/lib/doozer/orm/active_record.rb +19 -0
  23. data/lib/doozer/orm/data_mapper.rb +19 -0
  24. data/lib/doozer/orm/sequel.rb +18 -0
  25. data/lib/doozer/partial.rb +99 -0
  26. data/lib/doozer/plugins/paginate/init.rb +2 -0
  27. data/lib/doozer/plugins/paginate/lib/paginate/collection.rb +60 -0
  28. data/lib/doozer/plugins/paginate/lib/paginate/finder.rb +116 -0
  29. data/lib/doozer/plugins/paginate/lib/paginate/view_helpers.rb +37 -0
  30. data/lib/doozer/plugins/paginate/lib/paginate.rb +32 -0
  31. data/lib/doozer/rackup/server.ru +37 -0
  32. data/lib/doozer/rackup/test.rb +19 -0
  33. data/lib/doozer/redirect.rb +12 -0
  34. data/lib/doozer/route.rb +264 -0
  35. data/lib/doozer/scripts/cluster.rb +132 -0
  36. data/lib/doozer/scripts/migrate.rb +108 -0
  37. data/lib/doozer/scripts/task.rb +60 -0
  38. data/lib/doozer/scripts/test.rb +23 -0
  39. data/lib/doozer/version.rb +8 -0
  40. data/lib/doozer/view_helpers.rb +163 -0
  41. data/lib/doozer/watcher.rb +375 -0
  42. data/lib/doozer.rb +30 -0
  43. data/lib/generator/generator.rb +547 -0
  44. data/templates/skeleton/Rakefile +3 -0
  45. data/templates/skeleton/app/controllers/application_controller.rb +2 -0
  46. data/templates/skeleton/app/controllers/index_controller.rb +7 -0
  47. data/templates/skeleton/app/helpers/application_helper.rb +17 -0
  48. data/templates/skeleton/app/views/global/_header.html.erb +7 -0
  49. data/templates/skeleton/app/views/global/_navigation.html.erb +6 -0
  50. data/templates/skeleton/app/views/index/index.html.erb +108 -0
  51. data/templates/skeleton/app/views/layouts/default.html.erb +23 -0
  52. data/templates/skeleton/config/app.yml +31 -0
  53. data/templates/skeleton/config/database.yml +25 -0
  54. data/templates/skeleton/config/environment.rb +13 -0
  55. data/templates/skeleton/config/rack.rb +30 -0
  56. data/templates/skeleton/config/routes.rb +69 -0
  57. data/templates/skeleton/script/cluster +5 -0
  58. data/templates/skeleton/script/migrate +5 -0
  59. data/templates/skeleton/script/task +5 -0
  60. data/templates/skeleton/script/test +4 -0
  61. data/templates/skeleton/static/404.html +16 -0
  62. data/templates/skeleton/static/500.html +16 -0
  63. data/templates/skeleton/static/css/style.css +32 -0
  64. data/templates/skeleton/static/favicon.ico +0 -0
  65. data/templates/skeleton/static/js/application.js +1 -0
  66. data/templates/skeleton/static/js/jquery-1.3.min.js +19 -0
  67. data/templates/skeleton/static/robots.txt +5 -0
  68. data/templates/skeleton/test/fixtures/setup.rb +6 -0
  69. data/templates/skeleton/test/setup.rb +33 -0
  70. data/test/doozer_test.rb +7 -0
  71. data/test/test_helper.rb +10 -0
  72. metadata +126 -0
@@ -0,0 +1,132 @@
1
+ #= start/stop/restart webserver(s)
2
+ # This file is required in script/cluster.
3
+ #
4
+ # Navigate to your app root and run it with the following commands.
5
+ #
6
+ # script/cluster
7
+ # -C command (start || stop || restart || test)
8
+ # -E environment (default: development || deployment)
9
+ # -D (daemonize) - This is automatically initialized in deployment mode. There should be no need to pass this unless you want to test it out in development mode.
10
+ # -h Hellllpppp!!!
11
+
12
+ require 'rubygems'
13
+ require 'optparse'
14
+
15
+ APP_PATH = Dir.pwd if APP_PATH.nil?
16
+
17
+ config = Doozer::Configs.symbolize_keys( YAML.load(File.read(File.join(APP_PATH,'/config/app.yml'))) )
18
+ clusters = Doozer::Configs.symbolize_keys(config[:clusters])
19
+
20
+ @command = nil
21
+ @env = :development
22
+ @daemonize = ''
23
+ @server = clusters[:server]
24
+ @config = DOOZER_PATH + '/doozer/rackup/server.ru'
25
+ @test_config = DOOZER_PATH + '/doozer/rackup/test.rb'
26
+ @apps = []
27
+
28
+ for app in clusters[:apps]
29
+ ip = app.split(':')[0]
30
+ port = app.split(':')[1]
31
+ @apps.push({:ip=>ip, :port=>port})
32
+ end
33
+
34
+ # Automatically starts a test instance of your appserver on http://localhost:5000. (No -E flag is required for this command).
35
+ def test
36
+ cmd = "rackup #{@test_config}"
37
+ p "Command: #{cmd} -p 5000 -E test -o 127.0.0.1"
38
+ system(cmd)
39
+ end
40
+
41
+ # <b>development</b>: Only starts the first configured (if more then one) address:port
42
+ #
43
+ # <b>deployment</b>: Automatically starts a new instance of your appserver for each defined cluster address:port
44
+ def start
45
+ p "Starting clusters..."
46
+ for app in @apps
47
+ if @env == :deployment
48
+ #need to check if application has a pid file so we don't start
49
+ pid_file = "#{APP_PATH}/log/doozer.#{app[:port]}.pid"
50
+ raise "pid file already exists for #{pid_file}" if File.exist?(pid_file)
51
+ cmd = "rackup #{@config} -p #{app[:port]} -E #{@env.to_s} -s #{@server} -o #{app[:ip]} #{@daemonize} -P #{pid_file}"
52
+ p "Command: #{cmd}"
53
+ system(cmd)
54
+ else
55
+ cmd = "rackup #{@config} -p #{app[:port]} -E #{@env.to_s} -s #{@server} -o #{app[:ip]}"
56
+ p "Command: #{cmd}"
57
+ system(cmd)
58
+ break
59
+ end
60
+ end
61
+ p "Did they start?"
62
+ system("ps -aux | grep rackup")
63
+ end
64
+
65
+ # Calls stop() and then start()
66
+ def restart
67
+ stop
68
+ start
69
+ end
70
+
71
+ # <b>development</b>: Only stops the first configured (if more then one) address:port
72
+ #
73
+ # <b>deployment</b>: Automatically stops all instances of your appserver for each defined cluster address:port
74
+ def stop
75
+ system("ps -aux | grep rackup")
76
+ p "Stoping clusters..."
77
+ for app in @apps
78
+ if @env == :deployment
79
+ pid_file = "#{APP_PATH}/log/doozer.#{app[:port]}.pid"
80
+ p "Reading pid from #{pid_file}"
81
+ if File.exist?(pid_file)
82
+ File.open(pid_file, 'r'){ | f |
83
+ pid = f.gets.to_i
84
+ p "Shutting down process #{pid}"
85
+ system("kill -9 #{pid}")
86
+
87
+ }
88
+ File.delete(pid_file)
89
+ else
90
+ p "pid file doesn't exist"
91
+ end
92
+ end
93
+ end
94
+ system("ps | grep rackup")
95
+ end
96
+
97
+ opts = OptionParser.new("", 24, ' ') { |opts|
98
+ opts.banner = "Usage: script/clusters -C [command] -E [environment] -h"
99
+
100
+ opts.separator ""
101
+ opts.separator "Command options:"
102
+ opts.on("-C", "--command COMMAND", "start, stop, restart, or test") { | c |
103
+ @command = c.downcase.to_sym
104
+ }
105
+
106
+ opts.on("-E", "--env ENVIRONMENT", "default: development || deployment") { | e |
107
+ @env = e.downcase.to_sym
108
+ }
109
+
110
+ opts.on_tail("-h", "--help", "Show this message") do
111
+ puts opts
112
+ exit
113
+ end
114
+
115
+ opts.parse! ARGV
116
+ }
117
+
118
+ @daemonize = '-D' if @env == :deployment
119
+
120
+ case @command
121
+ when :start
122
+ start()
123
+ when :restart
124
+ restart()
125
+ when :stop
126
+ stop()
127
+ when :test
128
+ test()
129
+ end
130
+
131
+
132
+
@@ -0,0 +1,108 @@
1
+ #= Migrations
2
+ # This file is required in script/migrate. It loads the specified migration from the project/db directory and runs the migration with the specified direction.
3
+ # Navigate to your project root and run it with the following commands.
4
+ #
5
+ # script/migrate
6
+ # -V version:direction (example: 1:up || 1:down)
7
+ # -E environment (default: development || deployment)
8
+ # -h Hellllpppp!!!
9
+ #
10
+ #== Examples
11
+ #
12
+ # Suppose you have this file db/001_initial_schema.rb
13
+ #
14
+ #== Example for ActiveRecord
15
+ #
16
+ # class InitialSchema < ActiveRecord::Migration
17
+ # def self.up
18
+ # end
19
+ # def self.down
20
+ # end
21
+ # end
22
+ #
23
+ #
24
+ #== Example for DataMapper
25
+ #
26
+ # require 'dm-more'
27
+ # class CreateUser
28
+ # def self.up
29
+ # end
30
+ # def self.down
31
+ # end
32
+ # end
33
+ #
34
+ #== Example for Sequel
35
+ #
36
+ # class InitialSchema
37
+ # def self.db
38
+ # Doozer::Configs.db
39
+ # end
40
+ # def self.up
41
+ # db.create_table :examples do
42
+ # end
43
+ # end
44
+ # def self.down
45
+ # db.drop_table :examples
46
+ # end
47
+ # end
48
+
49
+ require 'optparse'
50
+ @env = :development
51
+ @version = nil
52
+ @direction = nil
53
+
54
+ opts = OptionParser.new("", 24, ' ') { |opts|
55
+ opts.banner = "Usage: script/migrate -V number:direction -E (default: development || deployment)"
56
+ opts.separator ""
57
+ opts.separator "Command options:"
58
+
59
+ opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development || deployment)") { |e|
60
+ @env = e.to_sym
61
+ }
62
+
63
+ opts.on("-V", "--version VERSION", "use VERSION to upgrade or downgrade to the correct version number") { | v |
64
+ if v.index(":up")
65
+ @direction = :up
66
+ elsif v.index(":down")
67
+ @direction = :down
68
+ else
69
+ raise "Missing direction. Must be -V (num:up || num:down)"
70
+ end
71
+ @version = v.split(":")[0].to_i
72
+ }
73
+ opts.on_tail("-h", "--help", "Show this message") do
74
+ puts opts
75
+ exit
76
+ end
77
+
78
+ opts.parse! ARGV
79
+ }
80
+
81
+ raise "Missing Version and Direction in form of version:direction" if @version.nil? or @direction.nil?
82
+
83
+ #--boot it up
84
+ Doozer::Initializer.boot(@env)
85
+
86
+ # need to grab all the current migrations. assumes there isn't a migration with 000_*_.rb
87
+ migrations = [nil].concat( Dir.glob(File.join(APP_PATH,'db/*_*.rb')) )
88
+
89
+ p "Loading migration files"
90
+ p "Version: #{@version}"
91
+ p "Direction: #{@direction}"
92
+
93
+ if @version > 0
94
+ file = migrations[@version]
95
+ raise "Can't find file for this migration" if file.nil?
96
+ require file
97
+ p "Migrating #{file}"
98
+ klass = file.split("/").last.gsub(/\.rb/,"").split('_')
99
+ klass = Doozer::Lib.classify(klass.slice(1, klass.length).join('_'))
100
+ obj = Object.const_get(klass)
101
+
102
+ case @direction
103
+ when :up
104
+ obj.up
105
+ when :down
106
+ obj.down
107
+ end
108
+ end
@@ -0,0 +1,60 @@
1
+ #= Tasks
2
+ # This file is required in script/task.
3
+ # Add files to /tasks where the specified task_name contains a class with TaskName and a 'run' class method.
4
+ # Running a task automatically loads Doozer::Config and the specified ORM. You must require all other files your tasks require beyond these.
5
+ # Navigate to your app root and run it with the following commands.
6
+ #
7
+ # script/clusters
8
+ # -T task_name
9
+ # -E environment (default: development || deployment)
10
+ # -h Hellllpppp!!!
11
+ #
12
+ #== Example
13
+ # Suppose you have this file tasks/who_rocks.rb
14
+ #
15
+ # class WhoRocks
16
+ # def self.run
17
+ # p "You Do!"
18
+ # end
19
+ # end
20
+ #
21
+ # run: script/task -T who_rocks
22
+ require 'optparse'
23
+ @env = :development
24
+ @task = nil
25
+
26
+ opts = OptionParser.new("", 24, ' ') { |opts|
27
+ opts.banner = "Usage: script/task -T task_name -E (default: development || deployment || test)"
28
+ opts.separator ""
29
+ opts.separator "Command options:"
30
+
31
+ opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development || deployment || test)") { |e|
32
+ @env = e.to_sym
33
+ }
34
+
35
+ opts.on("-T", "--task TASK", "run task_name") { | t |
36
+ @task = t
37
+ }
38
+
39
+ opts.on_tail("-h", "--help", "Show this message") do
40
+ puts opts
41
+ exit
42
+ end
43
+
44
+ opts.parse! ARGV
45
+ }
46
+
47
+ raise "Missing task_name" if @task.nil?
48
+
49
+ #--boot it up
50
+ Doozer::Initializer.boot(@env)
51
+
52
+ if @task
53
+ file = File.join(APP_PATH, "tasks/#{@task}.rb")
54
+ raise "Can't find this task file #{@task}" if file.nil?
55
+ p "Running #{@task}"
56
+ klass = file.split("/").last
57
+ require file
58
+ klass = Doozer::Lib.classify(klass.gsub(/\.rb/,""))
59
+ Object.const_get(klass).run
60
+ end
@@ -0,0 +1,23 @@
1
+ # #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ @command = nil
4
+
5
+ opts = OptionParser.new("", 24, ' ') { |opts|
6
+ opts.banner = "Usage: script/test [command]"
7
+
8
+ opts.separator ""
9
+ opts.separator "Command options:"
10
+ opts.on("-C", "--command COMMAND", "setup (not implemented yet: unit, functional)") { | c |
11
+ @command = c.downcase.to_sym if c
12
+ }
13
+ opts.on_tail("-h", "--help", "Show this message") do
14
+ puts opts
15
+ exit
16
+ end
17
+ opts.parse! ARGV
18
+ }
19
+
20
+ case @command
21
+ when :setup
22
+ require 'test/setup'
23
+ end
@@ -0,0 +1,8 @@
1
+ module Doozer
2
+ module Version
3
+ MAJOR=0
4
+ MINOR=1
5
+ PATCH=0
6
+ STRING=[MAJOR, MINOR, PATCH].join('.')
7
+ end
8
+ end
@@ -0,0 +1,163 @@
1
+ require 'digest/sha1'
2
+
3
+ module Doozer
4
+ module ViewHelpers
5
+
6
+ def url(opt)
7
+ url = ''
8
+ if opt.kind_of? Hash
9
+ # name (if present) trumps controller/action (if present)
10
+ if opt[:name]
11
+ # TODO: this needs to be only in dev mode
12
+ name = opt.delete(:name)
13
+ route = Doozer::Routing::Routes::get_by_name(name)
14
+ return "MISSING-ROUTE-for-name-#{name}" if route .nil?
15
+ url = "#{route.path}"
16
+
17
+ # we need to swap out the tokens here...
18
+ route.tokens.each {|token|
19
+ val = opt[token.to_sym]
20
+ if val
21
+ opt.delete(token.to_sym)
22
+ else
23
+ val = "MISSING-#{token}"
24
+ end
25
+ url.gsub!(/:#{token}/, val.to_s)
26
+ }
27
+ end
28
+
29
+ # set base _url
30
+ host = ""
31
+ if opt[:base_url]
32
+ host = opt.delete(:base_url)
33
+ end
34
+ # add qs pairs
35
+ if not opt.empty?
36
+ url += "?#{hash_to_qs(opt)}"
37
+ end
38
+ url = "#{host}#{url}"
39
+ elsif opt.kind_of? String
40
+ url = "#{opt}"
41
+ end
42
+ return url
43
+ end
44
+
45
+ def link(text='', opt={}, prop={})
46
+ "<a href=\"#{url(opt)}\"#{hash_to_props(prop)}>#{text}</a>"
47
+ end
48
+
49
+ def img(path, prop={})
50
+ path = timestamp_path(path)
51
+ "<img src=\"#{path}\"#{hash_to_props(prop)} />"
52
+ end
53
+
54
+ def stylesheet(path, prop={})
55
+ #<link rel="stylesheet" type="text/css" media="all" href="/css/style.css" />
56
+ path = timestamp_path(path)
57
+ prop[:rel] = 'stylesheet' if prop[:rel].nil?
58
+ prop[:type] = 'text/css' if prop[:type].nil?
59
+ prop[:media] = 'all' if prop[:media].nil?
60
+ "<link #{hash_to_props(prop)} href=\"#{path}\" />"
61
+ end
62
+
63
+ def javascript(path, prop={})
64
+ path = timestamp_path(path)
65
+ prop[:type] = 'text/javascript' if prop[:type].nil?
66
+ "<script #{hash_to_props(prop)} src=\"#{path}\"></script>"
67
+ end
68
+
69
+ def metatags
70
+ #loop all metatags here...
71
+ out=[]
72
+ @view[:meta].each{ | key, value |
73
+ out.push("""<meta name=\"#{key.to_s}\" content=\"#{h(value)}\" />
74
+ """)
75
+ }
76
+ out.join("")
77
+ end
78
+
79
+ def hash_to_props(opt={})
80
+ props=[]
81
+ opt.each { | key, value |
82
+ props.push("#{key.to_s}=\"#{value}\"")
83
+ }
84
+ return " #{props.join(" ")}" if props.length > 0
85
+ return ""
86
+ end
87
+
88
+ def hash_to_qs(opt={})
89
+ props=[]
90
+ opt.each { | key, value |
91
+ props.push("#{key.to_s}=#{CGI::escape(value.to_s)}")
92
+ }
93
+ props.join("&")
94
+ end
95
+
96
+ def h(s)
97
+ s.gsub!(/</,'&lt;')
98
+ s.gsub!(/>/,'&gt;')
99
+ return s
100
+ end
101
+
102
+ def base_url
103
+ Doozer::Configs.base_url
104
+ end
105
+
106
+ def rack_env
107
+ Doozer::Configs.rack_env
108
+ end
109
+
110
+ def app_name
111
+ Doozer::Configs.app_name
112
+ end
113
+
114
+ def ip
115
+ if addr = @env['HTTP_X_FORWARDED_FOR']
116
+ addr.split(',').last.strip
117
+ else
118
+ @env['REMOTE_ADDR']
119
+ end
120
+ end
121
+
122
+ def server_name
123
+ @env['SERVER_NAME']
124
+ end
125
+
126
+ def path
127
+ @env['REQUEST_PATH']
128
+ end
129
+
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...
136
+ def session?
137
+ @session.empty?
138
+ end
139
+
140
+ private
141
+ def timestamp_path(path)
142
+ # p Doozer::Configs.rack_env
143
+ return path if Doozer::Configs.rack_env == :deployment
144
+ if path.index('?').nil?
145
+ path = "#{path}?#{@bust_key}"
146
+ else
147
+ path = "#{path}&#{@bust_key}"
148
+ end
149
+ end
150
+
151
+ ## check to see if form authtoken matches the one expected
152
+ ## phrase defaults to 'sid' which the default used for form authtokens
153
+ def authtoken_matches?(token, phrase=nil)
154
+ phrase = @request.cookies['sid'] if phrase.nil?
155
+ token == generate_authtoken(phrase)
156
+ end
157
+
158
+ def generate_authtoken(phrase)
159
+ Digest::SHA1.hexdigest("--#{app_name}--#{phrase}--")
160
+ end
161
+
162
+ end
163
+ end