mack 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README +43 -0
- data/bin/mack +60 -0
- data/bin/templates/Rakefile.template +6 -0
- data/bin/templates/app/controllers/default_controller.rb.template +7 -0
- data/bin/templates/app/helpers/application_helper.rb.template +2 -0
- data/bin/templates/app/views/default/index.html.erb.template +3 -0
- data/bin/templates/app/views/layouts/application.html.erb.template +15 -0
- data/bin/templates/config/app_config/default.yml.template +7 -0
- data/bin/templates/config/app_config/development.yml.template +0 -0
- data/bin/templates/config/app_config/production.yml.template +0 -0
- data/bin/templates/config/app_config/test.yml.template +0 -0
- data/bin/templates/config/boot.rb.template +6 -0
- data/bin/templates/config/database.yml.template +20 -0
- data/bin/templates/config/routes.rb.template +7 -0
- data/bin/templates/config/thin.ru.template +1 -0
- data/bin/templates/config/thin.yml.template +8 -0
- data/bin/templates/public/favicon.ico +0 -0
- data/bin/templates/public/stylesheets/scaffold.css.template +74 -0
- data/core_extensions/hash.rb +9 -0
- data/core_extensions/module.rb +29 -0
- data/core_extensions/nil.rb +8 -0
- data/core_extensions/object.rb +9 -0
- data/core_extensions/string.rb +28 -0
- data/errors/errors.rb +79 -0
- data/initialize/configuration.rb +99 -0
- data/initialize/configure_logging.rb +24 -0
- data/initialize/configure_orm_support.rb +23 -0
- data/initialize/console.rb +13 -0
- data/initialize/initializer.rb +88 -0
- data/initialize/server/simple_server.rb +21 -0
- data/lib/utils/html.rb +88 -0
- data/lib/utils/server.rb +27 -0
- data/mack.rb +124 -0
- data/mack_tasks.rb +16 -0
- data/routing/route_map.rb +268 -0
- data/routing/urls.rb +54 -0
- data/sea_level/controller_base.rb +293 -0
- data/sea_level/cookie_jar.rb +67 -0
- data/sea_level/filter.rb +63 -0
- data/sea_level/helpers/view_helpers/html_helpers.rb +33 -0
- data/sea_level/helpers/view_helpers/orm_helpers.rb +72 -0
- data/sea_level/request.rb +83 -0
- data/sea_level/response.rb +6 -0
- data/sea_level/session.rb +33 -0
- data/sea_level/view_binder.rb +101 -0
- data/tasks/cachetastic_tasks.rake +69 -0
- data/tasks/log_tasks.rake +9 -0
- data/tasks/mack_tasks.rake +15 -0
- data/tasks/rake_helpers.rb +24 -0
- data/tasks/rake_rules.rake +19 -0
- data/tasks/script_tasks.rake +44 -0
- data/tasks/test_tasks.rake +7 -0
- data/test_extensions/test_assertions.rb +47 -0
- data/test_extensions/test_helpers.rb +84 -0
- metadata +173 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
module Mack
|
2
|
+
# All configuration for the Mack subsystem happens here. Each of the default environments,
|
3
|
+
# production, development, and test have their own default configuration options. These
|
4
|
+
# get merged with overall default options.
|
5
|
+
module Configuration # :nodoc:
|
6
|
+
|
7
|
+
# use local memory and store stuff for 24 hours:
|
8
|
+
# use file for sessions and store them for 4 hours:
|
9
|
+
DEFAULTS_PRODUCTION = {
|
10
|
+
"mack::use_lint" => false,
|
11
|
+
"mack::show_exceptions" => false,
|
12
|
+
"log::level" => "info",
|
13
|
+
"log::detailed_requests" => false,
|
14
|
+
"cachetastic_default_options" => {
|
15
|
+
"debug" => false,
|
16
|
+
"adapter" => "local_memory",
|
17
|
+
"expiry_time" => 86400,
|
18
|
+
"logging" => {
|
19
|
+
"logger_1" => {
|
20
|
+
"type" => "file",
|
21
|
+
"file" => File.join(MACK_ROOT, "log", "cachetastic.log")
|
22
|
+
}
|
23
|
+
}
|
24
|
+
},
|
25
|
+
"cachetastic_caches_mack_session_cache_options" => {
|
26
|
+
"debug" => false,
|
27
|
+
"adapter" => "file",
|
28
|
+
"store_options" =>
|
29
|
+
{"dir" => File.join(MACK_ROOT, "tmp")},
|
30
|
+
"expiry_time" => 14400,
|
31
|
+
"logging" => {
|
32
|
+
"logger_1" => {
|
33
|
+
"type" => "file",
|
34
|
+
"file" => File.join(MACK_ROOT, "log", "cachetastic.log")
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
} unless self.const_defined?("DEFAULTS_PRODUCTION")
|
39
|
+
|
40
|
+
# use local memory and store stuff for 5 minutes:
|
41
|
+
DEFAULTS_DEVELOPMENT = {
|
42
|
+
"mack::cache_classes" => false,
|
43
|
+
"log::level" => "debug",
|
44
|
+
"log::console" => true,
|
45
|
+
"cachetastic_default_options" => {
|
46
|
+
"debug" => false,
|
47
|
+
"adapter" => "local_memory",
|
48
|
+
"expiry_time" => 300,
|
49
|
+
"logging" => {
|
50
|
+
"logger_1" => {
|
51
|
+
"type" => "file",
|
52
|
+
"file" => File.join(MACK_ROOT, "log", "cachetastic.log")
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
} unless self.const_defined?("DEFAULTS_DEVELOPMENT")
|
57
|
+
|
58
|
+
# use local memory and store stuff for 1 hour:
|
59
|
+
DEFAULTS_TEST = {
|
60
|
+
"log::level" => "error",
|
61
|
+
"cachetastic_default_options" => {
|
62
|
+
"debug" => false,
|
63
|
+
"adapter" => "local_memory",
|
64
|
+
"expiry_time" => 3600,
|
65
|
+
"logging" => {
|
66
|
+
"logger_1" => {
|
67
|
+
"type" => "file",
|
68
|
+
"file" => File.join(MACK_ROOT, "log", "cachetastic.log")
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
} unless self.const_defined?("DEFAULTS_TEST")
|
73
|
+
|
74
|
+
unless self.const_defined?("DEFAULTS")
|
75
|
+
DEFAULTS = {
|
76
|
+
"mack::cache_classes" => true,
|
77
|
+
"mack::use_lint" => true,
|
78
|
+
"mack::show_exceptions" => true,
|
79
|
+
"mack::session_id" => "_mack_session_id",
|
80
|
+
"mack::cookie_values" => {
|
81
|
+
"path" => "/"
|
82
|
+
},
|
83
|
+
# "mack::orm" => "activerecord",
|
84
|
+
"log::detailed_requests" => true,
|
85
|
+
"log::level" => "info",
|
86
|
+
"log::console" => false,
|
87
|
+
"log::file" => true,
|
88
|
+
"log::console_format" => "%l:\t[%d]\t%M",
|
89
|
+
"log::file_format" => "%l:\t[%d]\t%M"
|
90
|
+
}.merge(eval("DEFAULTS_#{MACK_ENV.upcase}"))
|
91
|
+
end
|
92
|
+
|
93
|
+
app_config.load_hash(DEFAULTS, "mack_defaults")
|
94
|
+
app_config.load_file(File.join(MACK_CONFIG, "app_config", "default.yml"))
|
95
|
+
app_config.load_file(File.join(MACK_CONFIG, "app_config", "#{MACK_ENV}.yml"))
|
96
|
+
# app_config.reload
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#--
|
2
|
+
# Configure logging
|
3
|
+
#++
|
4
|
+
include Log4r
|
5
|
+
|
6
|
+
log_dir_loc = File.join(MACK_ROOT, "log")
|
7
|
+
FileUtils.mkdir_p(log_dir_loc)
|
8
|
+
|
9
|
+
unless Object.const_defined?("MACK_DEFAULT_LOGGER")
|
10
|
+
log = Log4r::Logger.new('')
|
11
|
+
log.level = Module.instance_eval("Log4r::#{app_config.log.level.to_s.upcase}")
|
12
|
+
# console:
|
13
|
+
if app_config.log.console
|
14
|
+
console_format = PatternFormatter.new(:pattern => app_config.log.console_format)
|
15
|
+
log.add(Log4r::StdoutOutputter.new('console', :formatter => console_format))
|
16
|
+
end
|
17
|
+
# file:
|
18
|
+
if app_config.log.file
|
19
|
+
file_format = PatternFormatter.new(:pattern => app_config.log.file_format)
|
20
|
+
log.add(FileOutputter.new('fileOutputter', :filename => File.join(log_dir_loc, "#{MACK_ENV}.log"), :trunc => false, :formatter => file_format))
|
21
|
+
end
|
22
|
+
|
23
|
+
Object::MACK_DEFAULT_LOGGER = log
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# setup ORM:
|
2
|
+
|
3
|
+
[:activerecord, :data_mapper].each do |orm|
|
4
|
+
eval("def using_#{orm}?; false; end")
|
5
|
+
end
|
6
|
+
|
7
|
+
unless app_config.mack.orm.nil?
|
8
|
+
dbs = YAML::load(ERB.new(IO.read(File.join(MACK_CONFIG, "database.yml"))).result)
|
9
|
+
case app_config.mack.orm
|
10
|
+
when 'activerecord'
|
11
|
+
require 'activerecord'
|
12
|
+
ActiveRecord::Base.establish_connection(dbs[MACK_ENV])
|
13
|
+
eval("def using_activerecord?; true; end")
|
14
|
+
when 'data_mapper'
|
15
|
+
require 'data_mapper'
|
16
|
+
DataMapper::Database.setup(dbs[MACK_ENV])
|
17
|
+
eval("def using_data_mapper?; true; end")
|
18
|
+
else
|
19
|
+
MACK_DEFAULT_LOGGER.warn("Attempted to configure an unknown ORM: #{app_config.mack.orm}")
|
20
|
+
end
|
21
|
+
else
|
22
|
+
MACK_DEFAULT_LOGGER.warn("No ORM has been configured!")
|
23
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# This file gets loaded when you run:
|
2
|
+
# rake console
|
3
|
+
# It loads the following classes to make using the application via the console easier:
|
4
|
+
#
|
5
|
+
# * Mack::TestHelpers
|
6
|
+
# * Mack::Routes::Urls
|
7
|
+
|
8
|
+
fl = File.join(File.dirname(__FILE__), "..")
|
9
|
+
|
10
|
+
require File.join(fl, "test_extensions", "test_helpers")
|
11
|
+
|
12
|
+
self.send(:include, Mack::TestHelpers)
|
13
|
+
self.send(:include, Mack::Routes::Urls)
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rack'
|
3
|
+
require 'digest'
|
4
|
+
require 'ruby_extensions'
|
5
|
+
require 'application_configuration'
|
6
|
+
require 'cachetastic'
|
7
|
+
require 'fileutils'
|
8
|
+
require 'log4r'
|
9
|
+
|
10
|
+
# Set up Mack constants, if they haven't already been set up.
|
11
|
+
unless Object.const_defined?("MACK_ENV")
|
12
|
+
(Object::MACK_ENV = (ENV["MACK_ENV"] ||= "development")).to_sym
|
13
|
+
end
|
14
|
+
(Object::MACK_ROOT = (ENV["MACK_ROOT"] ||= FileUtils.pwd)) unless Object.const_defined?("MACK_ROOT")
|
15
|
+
|
16
|
+
Object::MACK_PUBLIC = File.join(MACK_ROOT, "public") unless Object.const_defined?("MACK_PUBLIC")
|
17
|
+
Object::MACK_APP = File.join(MACK_ROOT, "app") unless Object.const_defined?("MACK_APP")
|
18
|
+
Object::MACK_LIB = File.join(MACK_ROOT, "lib") unless Object.const_defined?("MACK_LIB")
|
19
|
+
Object::MACK_CONFIG = File.join(MACK_ROOT, "config") unless Object.const_defined?("MACK_CONFIG")
|
20
|
+
Object::MACK_VIEWS = File.join(MACK_APP, "views") unless Object.const_defined?("MACK_VIEWS")
|
21
|
+
Object::MACK_LAYOUTS = File.join(MACK_VIEWS, "layouts") unless Object.const_defined?("MACK_LAYOUTS")
|
22
|
+
|
23
|
+
unless Object.const_defined?("MACK_INITIALIZED")
|
24
|
+
puts "Starting application in #{MACK_ENV} mode."
|
25
|
+
|
26
|
+
Object::MACK_INITIALIZED = true
|
27
|
+
|
28
|
+
# Set up 'Rails' constants to allow for easier use of existing gems/plugins like application_configuration.
|
29
|
+
# I would like to take these out eventually, but for right now, it's not doing too much harm.
|
30
|
+
# Object::RAILS_ENV = MACK_ENV unless Object.const_defined?("RAILS_ENV")
|
31
|
+
# Object::RAILS_ROOT = MACK_ROOT unless Object.const_defined?("RAILS_ROOT")
|
32
|
+
|
33
|
+
require File.join(File.dirname(__FILE__), "configuration.rb")
|
34
|
+
|
35
|
+
require File.join(File.dirname(__FILE__), "configure_logging.rb")
|
36
|
+
|
37
|
+
require File.join(File.dirname(__FILE__), "configure_orm_support.rb")
|
38
|
+
|
39
|
+
fl = File.join(File.dirname(__FILE__), "..")
|
40
|
+
|
41
|
+
# Require all the necessary files to make Mack actually work!
|
42
|
+
["errors", "core_extensions", "lib", "test_extensions", "routing", "sea_level", "tasks", "initialize/server"].each do |dir|
|
43
|
+
dir_globs = Dir.glob(File.join(fl, dir, "**/*.rb"))
|
44
|
+
dir_globs.each do |d|
|
45
|
+
require d
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
# ------------------------------------------------------------------------
|
52
|
+
|
53
|
+
# set up application stuff:
|
54
|
+
|
55
|
+
# set up routes:
|
56
|
+
require File.join(MACK_ROOT, "config", "routes")
|
57
|
+
|
58
|
+
# require 'app' files:
|
59
|
+
Dir.glob(File.join(MACK_APP, "**/*.rb")).each do |d|
|
60
|
+
require d
|
61
|
+
end
|
62
|
+
|
63
|
+
# require 'lib' files:
|
64
|
+
Dir.glob(File.join(MACK_LIB, "**/*.rb")).each do |d|
|
65
|
+
require d
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
# ------------------------------------------------------------------------
|
70
|
+
|
71
|
+
# Include ApplicationHelper into all controllers:
|
72
|
+
if Object.const_defined?("ApplicationHelper")
|
73
|
+
ApplicationHelper.include_safely_into(Mack::Controller::Base, Mack::ViewBinder)
|
74
|
+
end
|
75
|
+
# Find other Helpers and include them into their respective controllers.
|
76
|
+
Object.constants.collect {|c| c if c.match(/Controller$/)}.compact.each do |cont|
|
77
|
+
if Object.const_defined?("#{cont}Helper")
|
78
|
+
h = "#{cont}Helper".constantize
|
79
|
+
h.include_safely_into(cont, Mack::ViewBinder)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Find view level Helpers and include them into the Mack::ViewBinder
|
84
|
+
Mack::ViewHelpers.constants.each do |cont|
|
85
|
+
h = "Mack::ViewHelpers::#{cont}".constantize
|
86
|
+
h.include_safely_into(Mack::ViewBinder)
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Mack
|
2
|
+
# Even though it's called, SimpleServer, this might be the only server you need to run
|
3
|
+
# a Mack application.
|
4
|
+
#
|
5
|
+
# $ ruby script/server
|
6
|
+
#
|
7
|
+
# This SimpleServer does not use Thin. But does work with anything that Rack has a handler for.
|
8
|
+
class SimpleServer
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def run(options)
|
13
|
+
r = "Rack::Handler::#{options.handler.camelcase}"
|
14
|
+
puts "Starting app using: #{r} in #{options.environment} mode on port: #{options.port}"
|
15
|
+
eval(r).run(Mack::Utils::Server.build_app, :Port => options.port)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/utils/html.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
module Mack
|
2
|
+
module Utils
|
3
|
+
# Useful utilities for dealing with HTML.
|
4
|
+
class Html
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
# Used in views to create href links. It takes link_text, url, and a Hash that gets added
|
9
|
+
# to the href as options.
|
10
|
+
#
|
11
|
+
# Examples:
|
12
|
+
# Mack::Utils::Html.href("http://www.mackframework.com") # => <a href="http://www.mackframework.com">http://www.mackframework.com</a>
|
13
|
+
# Mack::Utils::Html.href("Mack", "http://www.mackframework.com") # => <a href="http://www.mackframework.com">Mack</a>
|
14
|
+
# Mack::Utils::Html.href("Mack", "http://www.mackframework.com", :target => "_blank") # => <a href="http://www.mackframework.com" target="_blank">Mack</a>
|
15
|
+
# Mack::Utils::Html.href("Mack", "http://www.mackframework.com", :target => "_blank", :rel => :nofollow) # => <a href="http://www.mackframework.com" target="_blank" rel="nofollow">Mack</a>
|
16
|
+
# If you pass in :method as an option it will be a JavaScript form that will post to the specified link with the
|
17
|
+
# methd specified.
|
18
|
+
# Mack::Utils::Html.href("Mack", "http://www.mackframework.com", :method => :delete)
|
19
|
+
# If you use the :method option you can also pass in a :confirm option. The :confirm option will generate a
|
20
|
+
# javascript confirmation window. If 'OK' is selected the the form will submit. If 'cancel' is selected, then
|
21
|
+
# nothing will happen. This is extremely useful for 'delete' type of links.
|
22
|
+
# Mack::Utils::Html.href("Mack", "http://www.mackframework.com", :method => :delete, :confirm => "Are you sure?")
|
23
|
+
def href(link_text, url = link_text, html_options = {})
|
24
|
+
if html_options[:method]
|
25
|
+
meth = nil
|
26
|
+
confirm = nil
|
27
|
+
|
28
|
+
meth = %{var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', '_method'); s.setAttribute('value', '#{html_options[:method]}'); f.appendChild(s);f.submit()}
|
29
|
+
html_options.delete(:method)
|
30
|
+
|
31
|
+
if html_options[:confirm]
|
32
|
+
confirm = %{if (confirm('#{html_options[:confirm]}'))}
|
33
|
+
html_options.delete(:confirm)
|
34
|
+
end
|
35
|
+
|
36
|
+
html_options[:onclick] = (confirm ? (confirm + " { ") : "") << meth << (confirm ? (" } ") : "") << ";return false;"
|
37
|
+
end
|
38
|
+
|
39
|
+
html = "<a href=" << '"' << url
|
40
|
+
html << '"'
|
41
|
+
html << " " << html_options.join("%s=\"%s\"", " ") unless html_options.empty?
|
42
|
+
html << ">" << link_text
|
43
|
+
html << "</a>"
|
44
|
+
html
|
45
|
+
end
|
46
|
+
|
47
|
+
alias_method :a, :href
|
48
|
+
|
49
|
+
# Wraps the content_tag method.
|
50
|
+
#
|
51
|
+
# Examples:
|
52
|
+
# Mack::Utils::Html.b("hello") # => <b>hello</b>
|
53
|
+
# Mack::Utils::Html.div("hello world!", :class => :foo)) # => <div class="foo">hello world!</div>
|
54
|
+
def method_missing(sym, *args)
|
55
|
+
ags = args.from_args
|
56
|
+
|
57
|
+
tag = sym
|
58
|
+
content = nil
|
59
|
+
options = {}
|
60
|
+
|
61
|
+
if ags.is_a?(Array)
|
62
|
+
content = ags[0] if ags[0].is_a?(String)
|
63
|
+
options = ags[1] if ags[1].is_a?(Hash)
|
64
|
+
elsif ags.is_a?(String)
|
65
|
+
content = ags
|
66
|
+
elsif ags.is_a?(Hash)
|
67
|
+
options = ags
|
68
|
+
end
|
69
|
+
|
70
|
+
content = yield if block_given?
|
71
|
+
|
72
|
+
content_tag(tag, content, options)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Builds an HTML tag.
|
76
|
+
#
|
77
|
+
# Examples:
|
78
|
+
# content_tag(:b, "hello") # => <b>hello</b>
|
79
|
+
# content_tag("div", "hello world!", :class => :foo) # => <div class="foo">hello world!</div>
|
80
|
+
def content_tag(tag, content, options = {})
|
81
|
+
html = "<#{tag} #{options.join("%s=\"%s\"", " ")}>#{content}</#{tag}>"
|
82
|
+
end
|
83
|
+
|
84
|
+
end # self
|
85
|
+
|
86
|
+
end # Html
|
87
|
+
end # Utils
|
88
|
+
end # Mack
|
data/lib/utils/server.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Mack
|
2
|
+
module Utils
|
3
|
+
module Server
|
4
|
+
|
5
|
+
# This method wraps all the necessary components of the Rack system around
|
6
|
+
# Mack::Runner. This can be used build your own server around the Mack framework.
|
7
|
+
def self.build_app
|
8
|
+
# Mack framework:
|
9
|
+
app = Mack::Runner.new
|
10
|
+
# Any urls listed will go straight to the public directly and will not be served up via the app:
|
11
|
+
app = Rack::Static.new(app, :urls => ["/css", "/images", "/files", "/images", "/stylesheets", "/javascripts", "/media"], :root => "public")
|
12
|
+
app = Rack::Lint.new(app) if app_config.mack.use_lint
|
13
|
+
app = Rack::ShowStatus.new(app)
|
14
|
+
app = Rack::ShowExceptions.new(app) if app_config.mack.show_exceptions
|
15
|
+
app = Rack::Recursive.new(app)
|
16
|
+
# This will reload any edited classes if the cache_classes config setting is set to true.
|
17
|
+
app = Rack::Reloader.new(app, 1) unless app_config.mack.cache_classes
|
18
|
+
# TODO: Not sure about this logger, investigate better ones.
|
19
|
+
# TODO: Depends on MACK_DEFAULT_LOGGER already being configured.
|
20
|
+
# This makes it a drag run this 'standalone' in another Ruby program.
|
21
|
+
# app = Rack::CommonLogger.new(app, MACK_DEFAULT_LOGGER)
|
22
|
+
app
|
23
|
+
end
|
24
|
+
|
25
|
+
end # Server
|
26
|
+
end # Utils
|
27
|
+
end # Mack
|
data/mack.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "initialize", "initializer")
|
2
|
+
|
3
|
+
module Mack
|
4
|
+
# This is the heart and soul of the Mack framework! This class interfaces with the Rack framework.
|
5
|
+
# It handles all the dispatching back and forth between the Rack framework and a Mack application.
|
6
|
+
class Runner
|
7
|
+
include Mack::Routes::Urls
|
8
|
+
|
9
|
+
attr_reader :response # :nodoc:
|
10
|
+
attr_reader :request # :nodoc:
|
11
|
+
attr_reader :cookies # :nodoc:
|
12
|
+
# This method needs to be defined as part of the Rack framework. As is noted for the Mack::Runner
|
13
|
+
# class, this is where the center of the Mack framework lies.
|
14
|
+
def call(env)
|
15
|
+
begin
|
16
|
+
setup(env) do
|
17
|
+
begin
|
18
|
+
route = Mack::Routes::RouteMap.instance.get_route_from_request(self.request)
|
19
|
+
if route[:redirect_to]
|
20
|
+
# because the route is specified to be a redirect, let's do that:
|
21
|
+
redirect_to(route)
|
22
|
+
else
|
23
|
+
# let's handle a normal request:
|
24
|
+
c = "#{route[:controller].to_s.camelcase}Controller".constantize.new(self.request, self.response, self.cookies)
|
25
|
+
self.response.write(c.run)
|
26
|
+
end
|
27
|
+
rescue Mack::Errors::ResourceNotFound, Mack::Errors::UndefinedRoute => e
|
28
|
+
return try_to_find_resource(env, self.request.path_info, e)
|
29
|
+
end
|
30
|
+
end # setup
|
31
|
+
rescue Exception => e
|
32
|
+
MACK_DEFAULT_LOGGER.error(e)
|
33
|
+
raise e
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def log_request
|
39
|
+
s_time = Time.now
|
40
|
+
x = yield
|
41
|
+
e_time = Time.now
|
42
|
+
p_time = e_time - s_time
|
43
|
+
if app_config.log.detailed_requests
|
44
|
+
msg = "\n\t[#{@request.request_method.upcase}] '#{@request.path_info}'\n"
|
45
|
+
msg << "\tSession ID: #{@request.session.id}\n"
|
46
|
+
msg << "\tParameters: #{@request.all_params.inspect}\n"
|
47
|
+
msg << "\tCompleted in #{p_time} (#{(1 / p_time).round} reqs/sec) | #{@response.status} [#{@request.full_host}]"
|
48
|
+
else
|
49
|
+
msg = "[#{@request.request_method.upcase}] '#{@request.path_info}' (#{p_time})"
|
50
|
+
end
|
51
|
+
MACK_DEFAULT_LOGGER.info(msg)
|
52
|
+
x
|
53
|
+
end
|
54
|
+
|
55
|
+
# Setup the request, response, cookies, session, etc...
|
56
|
+
# yield up, and then clean things up afterwards.
|
57
|
+
def setup(env)
|
58
|
+
log_request do
|
59
|
+
@request = Mack::Request.new(env)
|
60
|
+
@response = Mack::Response.new
|
61
|
+
@cookies = Mack::CookieJar.new(self.request, self.response)
|
62
|
+
session do
|
63
|
+
yield
|
64
|
+
end
|
65
|
+
self.response.finish
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def session
|
70
|
+
sess_id = self.cookies[app_config.mack.session_id]
|
71
|
+
unless sess_id
|
72
|
+
sess_id = create_new_session
|
73
|
+
else
|
74
|
+
sess = Cachetastic::Caches::MackSessionCache.get(sess_id)
|
75
|
+
if sess
|
76
|
+
self.request.session = sess
|
77
|
+
else
|
78
|
+
# we couldn't find it in the store, so we need to create it:
|
79
|
+
sess_id = create_new_session
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
yield
|
84
|
+
|
85
|
+
Cachetastic::Caches::MackSessionCache.set(sess_id, self.request.session)
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_new_session
|
89
|
+
id = String.randomize(40).downcase
|
90
|
+
self.cookies[app_config.mack.session_id] = {:value => id, :expires => nil}
|
91
|
+
sess = Mack::Session.new(id)
|
92
|
+
self.request.session = sess
|
93
|
+
Cachetastic::Caches::MackSessionCache.set(id, sess)
|
94
|
+
end
|
95
|
+
|
96
|
+
def try_to_find_resource(env, path_info, exception)
|
97
|
+
# we can't find a route for this, so let's try and see if it's in the public directory:
|
98
|
+
if File.extname(path_info).blank?
|
99
|
+
path_info << ".html"
|
100
|
+
end
|
101
|
+
if File.exists?(File.join(MACK_PUBLIC, path_info))
|
102
|
+
return Rack::File.new(File.join(MACK_PUBLIC)).call(env)
|
103
|
+
else
|
104
|
+
raise exception
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# This will redirect the request to the specified url. A default status of
|
109
|
+
# 302, Moved Temporarily, is set if no status is specified. A simple HTML
|
110
|
+
# page is rendered in case the redirect does not occur.
|
111
|
+
def redirect_to(route)
|
112
|
+
status = route[:status] || 302
|
113
|
+
url = route[:redirect_to]
|
114
|
+
options = self.request.all_params
|
115
|
+
options.merge!(route)
|
116
|
+
options - [:controller, :action, :redirect_to, :method, :status]
|
117
|
+
url = url_for_pattern(url, options)
|
118
|
+
self.response.status = status
|
119
|
+
self.response[:location] = url
|
120
|
+
self.response.write(redirect_html(self.request.path_info, url, status))
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|