mack 0.7.1.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +32 -0
- data/bin/gem_load_path.rb +1 -1
- data/bin/mackery +0 -1
- data/bin/mackery-server +5 -1
- data/lib/mack/assets/asset_helpers.rb +51 -0
- data/lib/mack/assets/assets_mgr.rb +165 -0
- data/lib/mack/controller/controller.rb +4 -4
- data/lib/mack/controller/cookie_jar.rb +1 -1
- data/lib/mack/controller/request.rb +13 -3
- data/lib/mack/controller/response.rb +12 -0
- data/lib/mack/core_extensions/kernel.rb +69 -0
- data/lib/mack/core_extensions/symbol.rb +4 -0
- data/lib/mack/errors/errors.rb +5 -1
- data/lib/mack/generators/controller_generator/manifest.yml +2 -2
- data/lib/mack/generators/controller_helper_generator/manifest.yml +2 -2
- data/lib/mack/generators/mack_application_generator/manifest.yml +10 -2
- data/lib/mack/generators/mack_application_generator/templates/config/{app_config/default.yml.template → configatron/default.rb.template} +10 -15
- data/lib/mack/generators/mack_application_generator/templates/config/{app_config/development.yml.template → configatron/development.rb.template} +1 -1
- data/lib/mack/generators/mack_application_generator/templates/config/{app_config/production.yml.template → configatron/production.rb.template} +0 -0
- data/lib/mack/generators/mack_application_generator/templates/config/{app_config/test.yml.template → configatron/test.rb.template} +1 -1
- data/lib/mack/generators/mack_application_generator/templates/public/404.html.template +15 -0
- data/lib/mack/generators/mack_application_generator/templates/public/500.html.template +15 -0
- data/lib/mack/generators/view_helper_generator/manifest.yml +2 -2
- data/lib/mack/initialization/application.rb +9 -5
- data/lib/mack/initialization/boot_loader.rb +2 -104
- data/lib/mack/initialization/configuration.rb +72 -69
- data/lib/mack/initialization/console.rb +1 -1
- data/lib/mack/initialization/helpers.rb +1 -6
- data/lib/mack/initialization/logging/basic_layout.rb +14 -0
- data/lib/mack/initialization/logging/color_layout.rb +23 -0
- data/lib/mack/initialization/logging/filter.rb +45 -0
- data/lib/mack/initialization/logging.rb +33 -89
- data/lib/mack/initialization/plugins.rb +1 -1
- data/lib/mack/rendering/engine/builder.rb +3 -0
- data/lib/mack/rendering/engine/erubis.rb +28 -16
- data/lib/mack/rendering/type/file_base.rb +1 -1
- data/lib/mack/rendering/type/url.rb +3 -3
- data/lib/mack/rendering/view_template.rb +4 -7
- data/lib/mack/routing/resource_proxy.rb +33 -0
- data/lib/mack/routing/route_map.rb +122 -288
- data/lib/mack/routing/route_object.rb +88 -0
- data/lib/mack/routing/routes.rb +169 -0
- data/lib/mack/routing/urls.rb +39 -5
- data/lib/mack/runner.rb +65 -32
- data/lib/mack/runner_helpers/request_logger.rb +3 -3
- data/lib/mack/runner_helpers/session.rb +4 -4
- data/lib/mack/sessions/cookie_session_store.rb +3 -3
- data/lib/mack/sessions/session.rb +1 -1
- data/lib/mack/sessions/session_store_base.rb +1 -1
- data/lib/mack/tasks/gem_tasks.rake +156 -1
- data/lib/mack/tasks/mack_dump_tasks.rake +1 -1
- data/lib/mack/tasks/mack_update_tasks.rake +85 -1
- data/lib/mack/tasks/rake_rules.rake +6 -0
- data/lib/mack/tasks/test_tasks.rake +4 -4
- data/lib/mack/testing/helpers.rb +13 -6
- data/lib/mack/testing/rspec.rb +27 -9
- data/lib/mack/testing/test_case.rb +1 -1
- data/lib/mack/utils/ansi/ansi_color.rb +4 -1
- data/lib/mack/utils/forgery_detector.rb +3 -3
- data/lib/mack/utils/http_status_codes.rb +19 -0
- data/lib/mack/utils/http_status_codes.yml +55 -0
- data/lib/mack/utils/paths.rb +32 -32
- data/lib/mack/utils/reloader.rb +60 -0
- data/lib/mack/utils/server.rb +3 -3
- data/lib/mack/version.rb +1 -1
- data/lib/mack/view_helpers/all_helpers.rb +7 -0
- data/lib/mack/view_helpers/date_time_helpers.rb +16 -10
- data/lib/mack/view_helpers/form_helpers.rb +1 -1
- data/lib/mack/view_helpers/html_helpers.rb +22 -1
- data/lib/mack/view_helpers/link_helpers.rb +51 -10
- data/lib/mack/view_helpers/string_helpers.rb +1 -1
- data/lib/mack.rb +0 -1
- data/lib/mack_core.rb +8 -8
- data/lib/mack_tasks.rb +1 -1
- metadata +27 -15
- data/lib/mack/view_helpers/asset_helpers.rb +0 -50
@@ -0,0 +1,169 @@
|
|
1
|
+
module Mack
|
2
|
+
# Routes are the back bone of the Mack framework. They are used to map incoming urls to controllers.
|
3
|
+
#
|
4
|
+
# === Defining Routes:
|
5
|
+
# Example:
|
6
|
+
# Mack::Routes.build do |r|
|
7
|
+
#
|
8
|
+
# # Connects "/" to the HomeController and the '/' action.
|
9
|
+
# r.connect "/", :controller => :home
|
10
|
+
#
|
11
|
+
# # Connects "/foo", to the HomeController and the 'foo' action.
|
12
|
+
# r.connect "/foo", :controller => :home, :action => :foo
|
13
|
+
#
|
14
|
+
# # Connects "/blog" to the BlogController and the 'list' action.
|
15
|
+
# r.connect "/blog", :controller => :blog, :action => :list
|
16
|
+
#
|
17
|
+
# # Connects "/blog/:id" to the BlogController and the 'index' action.
|
18
|
+
# # It will also take the second half of the url and map it to a parameter called :id.
|
19
|
+
# # Example:
|
20
|
+
# # '/blog/1' # => goes to the BlogController, 'index' action, and has an :id parameter == 1.
|
21
|
+
# r.connect "/blog/:id", :controller => :blog, :action => :index
|
22
|
+
#
|
23
|
+
# # Connects "/blog/create" to the BlogController and the 'create' action.
|
24
|
+
# # It also insists that the HTTP method be 'post'. If it's not 'post' it will not match this route.
|
25
|
+
# r.connect "/blog/create", :controller => :blog, :action => :create, :method => :post
|
26
|
+
#
|
27
|
+
# # Connects "/comment/destroy/:id" to the CommentController and the 'destroy' action.
|
28
|
+
# # It also insists that the HTTP method be 'delete'. If it's not 'delete' it will not match this route.
|
29
|
+
# # It will also create an :id parameter.
|
30
|
+
# r.connect "/comment/destroy/:id", :controller => :comment, :action => :destroy, :method => :delete
|
31
|
+
#
|
32
|
+
# # This will create 'RESTful' routes. Unlike Rails, it doesn't generate a mixture of singular/plural
|
33
|
+
# # routes. It uses whatever you pass in to it. This will also create named routes in Mack::Routes::Urls.
|
34
|
+
# # Examples:
|
35
|
+
# # '/users' # => {:controller => 'users', :action => :index, :method => :get}
|
36
|
+
# # # => users_index_url
|
37
|
+
# # # => users_index_full_url
|
38
|
+
# # '/users' # => {:controller => 'users', :action => :create, :method => :post}
|
39
|
+
# # # => users_create_url
|
40
|
+
# # # => users_create_full_url
|
41
|
+
# # '/users/new' # => {:controller => 'users', :action => :new, :method => :get}
|
42
|
+
# # # => users_new_url
|
43
|
+
# # # => users_new_full_url
|
44
|
+
# # '/users/:id' # => {:controller => 'users', :action => :show, :method => :get}
|
45
|
+
# # # => users_show_url
|
46
|
+
# # # => users_show_full_url
|
47
|
+
# # '/users/:id/:edit # => {:controller => 'users', :action => :edit, :method => :get}
|
48
|
+
# # # => users_edit_url
|
49
|
+
# # # => users_edit_full_url
|
50
|
+
# # '/users/:id # => {:controller => 'users', :action => :update, :method => :put}
|
51
|
+
# # # => users_update_url
|
52
|
+
# # # => users_update_full_url
|
53
|
+
# # '/users/:id # => {:controller => 'users', :action => :delete, :method => :delete}
|
54
|
+
# # # => users_delete_url
|
55
|
+
# # # => users_delete_full_url
|
56
|
+
# r.resource :users
|
57
|
+
#
|
58
|
+
# # This will redirect '/old_users/show/:id' to '/users/:id' with a status of 302, 'Moved Temporarily'.
|
59
|
+
# # Examples:
|
60
|
+
# # '/old_users/show/1' # => '/users/1' (status of 302)
|
61
|
+
# # '/old_users/show/1?foo=bar' # => '/users/1?foo=bar' (status of 302)
|
62
|
+
# r.connect '/old_users/show/:id', :redirect_to => "/users/:id"
|
63
|
+
#
|
64
|
+
# # This will redirect '/old_blog' to '/blog' with a status of 301, 'Moved Permanently'.
|
65
|
+
# # Examples:
|
66
|
+
# # '/old_blog' # => '/blog' (status of 301)
|
67
|
+
# # '/old_blog?foo=bar' # => '/blogfoo=bar' (status of 301)
|
68
|
+
# r.connect '/old_blog', :redirect_to => "/blog", :status => 301
|
69
|
+
#
|
70
|
+
# # Connects "/comment/update/:id" to the CommentController and the 'update' action.
|
71
|
+
# # It will also create an :id parameter.
|
72
|
+
# # It will also create a named route in Mack::Routes::Urls called, 'c_u_url'.
|
73
|
+
# # In a controller or a view this: c_u_url(:id => 1) would return '/comment/update/1'.
|
74
|
+
# # It will also create a named route in Mack::Routes::Urls called, 'c_u_full_url'.
|
75
|
+
# # In a controller or a view this: c_u_full_url(:id => 1) would return 'http://example.org/comment/update/1'.
|
76
|
+
# r.c_u "/comment/update/:id", {:controller => :comment, :action => :update}
|
77
|
+
#
|
78
|
+
# # This creates 'Rails' style routes.
|
79
|
+
# # Any requests that come in that aren't found by explicit routes, will fall into these routes.
|
80
|
+
# # '/:controller/:action'
|
81
|
+
# # '/:controller/:action/:id'
|
82
|
+
# #
|
83
|
+
# # Example:
|
84
|
+
# # '/comment/show/1' # => Goes to CommentController, the 'show' action, with a parameter of 1.
|
85
|
+
# r.defaults
|
86
|
+
#
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# === Named Routes:
|
90
|
+
# Mack::Routes.build do |r|
|
91
|
+
# r.resource :users
|
92
|
+
# end
|
93
|
+
# See above in 'Defining Routes' to see what fully gets created when you map a resource, but let's look
|
94
|
+
# at the named route stuff that gets generated. In particular let's look at one example:
|
95
|
+
# '/users/:id' # => {:controller => 'users', :action => :show, :method => :get}
|
96
|
+
# # => users_show_url
|
97
|
+
# # => users_show_full_url
|
98
|
+
# The following can be used in controllers, views, and tests:
|
99
|
+
# users_show_url(:id => 1) # => '/users/1'
|
100
|
+
# # The following can only be used when there is a @request (Mack::Request) instance variable around:
|
101
|
+
# users_show_full_url(:id => 1) # => 'http://example.org/users/1'
|
102
|
+
#
|
103
|
+
# Mack::Routes.build do |r|
|
104
|
+
# r.hello_world "/", :controller => :home_page, :action => :hello
|
105
|
+
# end
|
106
|
+
# This will give you the following two methods:
|
107
|
+
# hello_world_url # => "/"
|
108
|
+
# hello_world_full_url # => "http://example.org/"
|
109
|
+
# These methods act just like the ones created when you use the resource method.
|
110
|
+
#
|
111
|
+
# === Exception Routes:
|
112
|
+
# You can define a route that will catch exceptions that are raised in other controllers.
|
113
|
+
#
|
114
|
+
# Mack::Routes.build do |r|
|
115
|
+
# r.handle_error Mack::ResourceNotFound, :controller => :oops, :action => :404
|
116
|
+
# r.handle_error HollyCrapError, :controller => :oops, :action => :500
|
117
|
+
# end
|
118
|
+
# In the example if an action raises a Mack::ResourceNotFound it will be caught and rendered
|
119
|
+
# using the OopsController and the 404 action.
|
120
|
+
# If A HollyCrapError is thrown it will be caught and rendered using the OopsController and the 500 action.
|
121
|
+
# You can catch all exceptions using Exception.
|
122
|
+
module Routes
|
123
|
+
include Extlib::Hook
|
124
|
+
|
125
|
+
class << self
|
126
|
+
|
127
|
+
# This method yields up Mack::Routes::RouteMap and allows for the creation of routes in the system.
|
128
|
+
def build
|
129
|
+
yield Mack::Routes::RouteMap.instance
|
130
|
+
Mack::Routes::Urls.include_safely_into(Mack::Controller,
|
131
|
+
Mack::Rendering::ViewTemplate,
|
132
|
+
Test::Unit::TestCase)
|
133
|
+
end
|
134
|
+
|
135
|
+
def any?
|
136
|
+
Mack::Routes::RouteMap.instance.any?
|
137
|
+
end
|
138
|
+
|
139
|
+
def empty?
|
140
|
+
Mack::Routes::RouteMap.instance.empty?
|
141
|
+
end
|
142
|
+
|
143
|
+
def reset!
|
144
|
+
Mack::Routes::RouteMap.instance.reset!
|
145
|
+
end
|
146
|
+
|
147
|
+
# Pass in a request or a String and it will try and give you back a Hash representing the
|
148
|
+
# options for that route. IE: controller, action, verb, etc...
|
149
|
+
# If there are embedded options they added to the Hash. These parameters are
|
150
|
+
# also added to the 'params' object in the request.
|
151
|
+
# If the route can not be found a Mack::Errors::UndefinedRoute exception is raised.
|
152
|
+
def retrieve(url_or_request, verb = :get)
|
153
|
+
Mack::Routes::RouteMap.instance.retrieve(url_or_request, verb)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Given an error class name it will return a routing options Hash, or nil, if one
|
157
|
+
# has not been mapped.
|
158
|
+
def retrieve_from_error(error)
|
159
|
+
Mack::Routes::RouteMap.instance.retrieve_from_error(error)
|
160
|
+
end
|
161
|
+
|
162
|
+
def inspect # :nodoc:
|
163
|
+
Mack::Routes::RouteMap.instance.inspect
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end # Routes
|
169
|
+
end # Mack
|
data/lib/mack/routing/urls.rb
CHANGED
@@ -20,11 +20,20 @@ module Mack
|
|
20
20
|
u = "/" if url.blank?
|
21
21
|
unused_params = []
|
22
22
|
format = nil
|
23
|
+
host_options = {:host => options[:host], :port => options[:port], :scheme => options[:scheme]}
|
24
|
+
options - [:host, :port, :scheme]
|
23
25
|
options.each_pair do |k, v|
|
24
26
|
unless k.to_sym == :format
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
if u.match(/\*#{k}/)
|
28
|
+
vp = [v].flatten.collect {|c| Rack::Utils.escape(c.to_param)}
|
29
|
+
if u.gsub!("*#{k}", File.join(vp)).nil?
|
30
|
+
unused_params << "#{Rack::Utils.escape(k)}=#{vp}"
|
31
|
+
end
|
32
|
+
else
|
33
|
+
vp = Rack::Utils.escape(v.to_param)
|
34
|
+
if u.gsub!(":#{k}", vp).nil?
|
35
|
+
unused_params << "#{Rack::Utils.escape(k)}=#{vp}"
|
36
|
+
end
|
28
37
|
end
|
29
38
|
else
|
30
39
|
format = v
|
@@ -36,13 +45,14 @@ module Mack
|
|
36
45
|
unless unused_params.empty?
|
37
46
|
u << "?" << unused_params.sort.join("&")
|
38
47
|
end
|
39
|
-
u
|
48
|
+
File.join(build_full_host_from_options(host_options), u)
|
49
|
+
# u
|
40
50
|
end
|
41
51
|
|
42
52
|
# Builds a simple HTML page to be rendered when a redirect occurs.
|
43
53
|
# Hopefully no one sees the HTML, but in case the browser won't do the
|
44
54
|
# redirect it's nice to let people know what's happening.
|
45
|
-
def redirect_html(original_path, new_path, status)
|
55
|
+
def redirect_html(original_path, new_path, status) # :nodoc:
|
46
56
|
%{
|
47
57
|
<!DOCTYPE HTML PUBLIC
|
48
58
|
"-//IETF//DTD HTML 2.0//EN">
|
@@ -58,6 +68,30 @@ module Mack
|
|
58
68
|
}
|
59
69
|
end
|
60
70
|
|
71
|
+
def self.create_method(sym, &block) # :nodoc:
|
72
|
+
define_method(sym, &block)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def build_full_host_from_options(options = {})
|
77
|
+
scheme = options[:scheme]
|
78
|
+
host = options[:host]
|
79
|
+
port = options[:port]
|
80
|
+
return '' if host.blank? && scheme.blank? && port.nil?
|
81
|
+
if @request
|
82
|
+
scheme = @request.scheme if scheme.nil?
|
83
|
+
port = @request.port if port.nil?
|
84
|
+
host = @request.host if host.nil?
|
85
|
+
end
|
86
|
+
port = 80 if port.nil?
|
87
|
+
port = case port.to_i
|
88
|
+
when 80, 443
|
89
|
+
else
|
90
|
+
":#{port}"
|
91
|
+
end
|
92
|
+
return "#{scheme.downcase}://#{host.downcase}#{port}"
|
93
|
+
end
|
94
|
+
|
61
95
|
end # Urls
|
62
96
|
end # Routes
|
63
97
|
end # Mack
|
data/lib/mack/runner.rb
CHANGED
@@ -16,10 +16,11 @@ module Mack
|
|
16
16
|
# This method needs to be defined as part of the Rack framework. As is noted for the Mack::Runner
|
17
17
|
# class, this is where the center of the Mack framework lies.
|
18
18
|
def call(env)
|
19
|
+
env["rack.errors"] = StringIO.new # Send Rack errors nowhere fast!
|
19
20
|
begin
|
20
21
|
setup(env)
|
21
22
|
begin
|
22
|
-
route = Mack::Routes
|
23
|
+
route = Mack::Routes.retrieve(self.request)
|
23
24
|
if route[:redirect_to]
|
24
25
|
# because the route is specified to be a redirect, let's do that:
|
25
26
|
redirect_to(route)
|
@@ -29,48 +30,70 @@ module Mack
|
|
29
30
|
@original_action = route[:action]
|
30
31
|
run_controller(route)
|
31
32
|
end
|
32
|
-
|
33
|
-
# return try_to_find_resource(env, e)
|
33
|
+
# return teardown
|
34
34
|
rescue Exception => e
|
35
|
-
|
36
|
-
|
37
|
-
self.request.all_params[:original_action] = @original_action
|
35
|
+
# There was an exception, let's see if there's a handler for this error in routes:
|
36
|
+
route = Mack::Routes.retrieve_from_error(e.class)
|
38
37
|
unless route.nil?
|
38
|
+
self.request.all_params[:original_controller] = @original_controller
|
39
|
+
self.request.all_params[:original_action] = @original_action
|
40
|
+
# There is a handler, let's try running that:
|
39
41
|
run_controller(route, e)
|
40
42
|
else
|
41
|
-
|
43
|
+
# If we can't find the resource, or there's no route, let's check the public directory:
|
44
|
+
case e
|
45
|
+
when Mack::Errors::ResourceNotFound, Mack::Errors::UndefinedRoute
|
42
46
|
return try_to_find_resource(env, e)
|
43
47
|
else
|
48
|
+
# Re-raise the exception
|
44
49
|
raise e
|
45
50
|
end
|
46
51
|
end
|
52
|
+
# return teardown
|
47
53
|
end
|
48
|
-
|
54
|
+
# Capture all the Exceptions for this call:
|
49
55
|
rescue Exception => e
|
50
|
-
Mack.logger.error
|
51
|
-
|
56
|
+
Mack.logger.error e
|
57
|
+
case e
|
58
|
+
when Mack::Errors::ResourceNotFound, Mack::Errors::UndefinedRoute
|
59
|
+
handle_error(404, 'Page Not Found!', e)
|
60
|
+
# If it's any other type of exception render the 500.html page:
|
61
|
+
else
|
62
|
+
handle_error(500, 'Server Error!', e)
|
63
|
+
end
|
64
|
+
# return teardown
|
65
|
+
ensure
|
66
|
+
teardown
|
52
67
|
end
|
68
|
+
return self.response.finish
|
53
69
|
end
|
54
70
|
|
55
71
|
#private
|
56
72
|
def run_controller(route, e = nil)
|
57
|
-
|
58
|
-
|
59
|
-
cont = "#{route[:controller].to_s.camelcase}Controller".constantize
|
60
|
-
rescue NameError => e
|
61
|
-
raise Mack::Errors::ResourceNotFound.new(self.request.path_info)
|
62
|
-
end
|
63
|
-
self.request.all_params[:controller] = route[:controller]
|
64
|
-
self.request.all_params[:action] = route[:action]
|
65
|
-
self.request.instance_variable_set("@params_controller", nil)
|
66
|
-
self.request.instance_variable_set("@params_action", nil)
|
73
|
+
runner_block = route[:runner_block]
|
74
|
+
route - :runner_block
|
67
75
|
|
68
|
-
|
69
|
-
|
70
|
-
|
76
|
+
self.request.params = self.request.all_params.merge(route)
|
77
|
+
self.response.content_type = Mack::Utils::MimeTypes[self.request.params[:format]]
|
78
|
+
catch(:finished) do
|
79
|
+
if runner_block
|
80
|
+
runner_block.call(self.request, self.response, self.cookies)
|
81
|
+
end
|
82
|
+
|
83
|
+
# let's handle a normal request:
|
84
|
+
begin
|
85
|
+
cont = "#{route[:controller].to_s.camelcase}Controller".constantize
|
86
|
+
rescue NameError => e
|
87
|
+
raise Mack::Errors::ResourceNotFound.new(self.request.path_info)
|
88
|
+
end
|
89
|
+
|
90
|
+
c = cont.new
|
91
|
+
c.configure_controller(self.request, self.response, self.cookies)
|
92
|
+
c.caught_exception = e unless e.nil?
|
71
93
|
|
72
|
-
|
73
|
-
|
94
|
+
self.response.controller = c
|
95
|
+
return self.response.write(c.run)
|
96
|
+
end
|
74
97
|
end
|
75
98
|
|
76
99
|
# Setup the request, response, cookies, session, etc...
|
@@ -91,17 +114,16 @@ module Mack
|
|
91
114
|
self.runner_helpers.reverse.each do |help|
|
92
115
|
help.complete(self.request, self.response, self.cookies)
|
93
116
|
end
|
94
|
-
self.response.finish
|
117
|
+
# self.response.finish
|
95
118
|
end
|
96
119
|
|
97
120
|
def try_to_find_resource(env, exception)
|
98
|
-
env = env.dup
|
99
121
|
# we can't find a route for this, so let's try and see if it's in the public directory:
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
if File.exists?(Mack::Paths.public(
|
104
|
-
return Rack::File.new(Mack::Paths.public).call(
|
122
|
+
path = env["PATH_INFO"].dup
|
123
|
+
path << ".html" if File.extname(path).blank?
|
124
|
+
|
125
|
+
if File.exists?(Mack::Paths.public(path))
|
126
|
+
return Rack::File.new(Mack::Paths.public).call(Rack::MockRequest.env_for(path))
|
105
127
|
else
|
106
128
|
raise exception
|
107
129
|
end
|
@@ -122,5 +144,16 @@ module Mack
|
|
122
144
|
self.response.write(redirect_html(self.request.path_info, url, status))
|
123
145
|
end
|
124
146
|
|
147
|
+
private
|
148
|
+
def handle_error(status, body, e)
|
149
|
+
self.response.status = status
|
150
|
+
raise e if configatron.mack.show_exceptions
|
151
|
+
path = Mack::Paths.public("#{status}.html")
|
152
|
+
if File.exists?(path)
|
153
|
+
body = File.read(path)
|
154
|
+
end
|
155
|
+
self.response.write(body)
|
156
|
+
end
|
157
|
+
|
125
158
|
end
|
126
159
|
end
|
@@ -16,11 +16,11 @@ module Mack
|
|
16
16
|
@end_time = Time.now
|
17
17
|
@total_time = @end_time - @start_time
|
18
18
|
@requests_per_second = (1 / @total_time).round
|
19
|
-
if
|
19
|
+
if configatron.mack.log.detailed_requests
|
20
20
|
msg = "\n\t[#{request.params[:method].to_s.upcase}] '#{request.path_info}'\n"
|
21
|
-
msg << "\tSession ID: #{request.session.id}\n" if
|
21
|
+
msg << "\tSession ID: #{request.session.id}\n" if configatron.mack.use_sessions
|
22
22
|
msg << "\tParameters: #{request.all_params}\n"
|
23
|
-
msg << Mack::Utils::Ansi::Color.wrap(
|
23
|
+
msg << Mack::Utils::Ansi::Color.wrap(configatron.mack.log.colors.completed, "\tCompleted in #{@total_time} (#{@requests_per_second} reqs/sec) | #{response.status} (#{Mack::Utils::HttpStatusCodes.get(response.status)}) [#{request.full_host}]")
|
24
24
|
else
|
25
25
|
msg = "[#{request.request_method.upcase}] '#{request.path_info}' (#{total_time})"
|
26
26
|
end
|
@@ -6,7 +6,7 @@ module Mack
|
|
6
6
|
attr_accessor :sess_id
|
7
7
|
|
8
8
|
def start(request, response, cookies)
|
9
|
-
if
|
9
|
+
if configatron.mack.use_sessions
|
10
10
|
self.sess_id = retrieve_session_id(request, response, cookies)
|
11
11
|
unless self.sess_id
|
12
12
|
self.sess_id = create_new_session(request, response, cookies)
|
@@ -23,7 +23,7 @@ module Mack
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def complete(request, response, cookies)
|
26
|
-
if
|
26
|
+
if configatron.mack.use_sessions
|
27
27
|
unless response.redirection?
|
28
28
|
request.session.delete(:tell)
|
29
29
|
end
|
@@ -33,12 +33,12 @@ module Mack
|
|
33
33
|
|
34
34
|
private
|
35
35
|
def retrieve_session_id(request, response, cookies)
|
36
|
-
cookies[
|
36
|
+
cookies[configatron.mack.session_id]
|
37
37
|
end
|
38
38
|
|
39
39
|
def create_new_session(request, response, cookies)
|
40
40
|
id = String.randomize(40).downcase
|
41
|
-
cookies[
|
41
|
+
cookies[configatron.mack.session_id] = {:value => id, :expires => nil}
|
42
42
|
sess = Mack::Session.new(id)
|
43
43
|
request.session = sess
|
44
44
|
Mack::SessionStore.set(request.session.id, request, response, cookies)
|
@@ -4,9 +4,9 @@ module Mack
|
|
4
4
|
# Stores session information in the user's cookie.
|
5
5
|
# The session information is encrypted using the mack-encryption library.
|
6
6
|
# This is the default session store for Mack applications.
|
7
|
-
# To set the expiry time for this session store use the following
|
7
|
+
# To set the expiry time for this session store use the following configatron setting:
|
8
8
|
# cookie_session_store::expiry_time: <%= 4.hours %>
|
9
|
-
# It is recommend that you set the
|
9
|
+
# It is recommend that you set the configatron setting 'default_secret_key' to
|
10
10
|
# something, otherwise it will generate a random one each time you start your application,
|
11
11
|
# which could make decrypting cookies a bit of a pain. :)
|
12
12
|
class Cookie < Mack::SessionStore::Base
|
@@ -29,7 +29,7 @@ module Mack
|
|
29
29
|
|
30
30
|
# Encrypts the session and places it into the cookie.
|
31
31
|
def set(id, request, response, cookies)
|
32
|
-
cookies[id] = {:value => YAML.dump(request.session).encrypt, :expires => (Time.now +
|
32
|
+
cookies[id] = {:value => YAML.dump(request.session).encrypt, :expires => (Time.now + configatron.mack.cookie_session_store.expiry_time)}
|
33
33
|
end
|
34
34
|
|
35
35
|
# Deletes the cookie.
|
@@ -2,7 +2,7 @@ module Mack
|
|
2
2
|
|
3
3
|
# A holder for the session information. This objects gets stored using the Cachetastic system.
|
4
4
|
# For more information about how Cachetastic works see the RDoc for that gem.
|
5
|
-
# The session cookie name defaults to: _mack_session_id but can be changed using the
|
5
|
+
# The session cookie name defaults to: _mack_session_id but can be changed using the configatron
|
6
6
|
# system like such:
|
7
7
|
# mack::session_id: _my_cool_app_sess_id
|
8
8
|
class Session
|
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
namespace :gems do
|
2
3
|
|
3
4
|
desc "lists all the gem required for this application."
|
@@ -17,4 +18,158 @@ namespace :gems do
|
|
17
18
|
end
|
18
19
|
end # install
|
19
20
|
|
20
|
-
|
21
|
+
task :freeze do
|
22
|
+
Mack::Utils::GemManager.instance.required_gem_list.each do |g|
|
23
|
+
version = g.version? ? g.version : '> 0.0.0'
|
24
|
+
ENV['gem_name'] = g.name.to_s
|
25
|
+
ENV['version'] = version
|
26
|
+
ENV['source'] = g.source? ? g.source : 'http://gems.rubyforge.org'
|
27
|
+
sh('rake gems:install_and_freeze')
|
28
|
+
end
|
29
|
+
end # freeze
|
30
|
+
|
31
|
+
task :install_and_freeze do
|
32
|
+
require 'rubygems/gem_runner'
|
33
|
+
add_dependencies = ENV['INCLUDE_DEPENDENCIES'] || ENV['include_dependencies'] || false
|
34
|
+
add_dependencies = false if add_dependencies.to_s.downcase == 'false'
|
35
|
+
version = ENV['version'] || ENV['VERSION'] || ENV['ver'] || ENV['VER'] || '> 0.0.0'
|
36
|
+
source = ENV['source'] || ENV['SOURCE'] || 'http://gems.rubyforge.org'
|
37
|
+
gem_name = ENV['gem_name']
|
38
|
+
|
39
|
+
dep_msg = "and its dependencies" if add_dependencies
|
40
|
+
puts "\nTask: freezing #{gem_name} #{dep_msg} to #{local_gem_dir}."
|
41
|
+
puts "Phase 1: Collecting information..."
|
42
|
+
if add_dependencies
|
43
|
+
collect_dependencies(gem_name, version)
|
44
|
+
else
|
45
|
+
version = source_index.find_name(gem_name, version).last.version.to_s
|
46
|
+
processed_gems << LocalGem.new(gem_name, version)
|
47
|
+
end
|
48
|
+
puts "\nPhase 2: Checking installation states..."
|
49
|
+
check_installation(source)
|
50
|
+
puts "\nPhase 3: Freezing Gems and Specs..."
|
51
|
+
freeze_gems
|
52
|
+
puts "\nPhase 4: validating data..."
|
53
|
+
validate
|
54
|
+
puts "\nTotal of #{processed_gems.size} gems frozen to #{local_gem_dir}"
|
55
|
+
end # install_and_freeze
|
56
|
+
end # gem
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def local_gem_dir
|
61
|
+
dir = Mack::Paths.vendor('gems')
|
62
|
+
mkdir(dir) if !File.exists?(dir)
|
63
|
+
return dir
|
64
|
+
end
|
65
|
+
|
66
|
+
def processed_gems
|
67
|
+
@gem_list ||= []
|
68
|
+
return @gem_list
|
69
|
+
end
|
70
|
+
|
71
|
+
def source_index
|
72
|
+
@src_index ||= Gem::SourceIndex.from_installed_gems
|
73
|
+
return @src_index
|
74
|
+
end
|
75
|
+
|
76
|
+
def collect_dependencies(gem_name, version)
|
77
|
+
# normalize the version
|
78
|
+
version = source_index.find_name(gem_name, version).last.version.to_s
|
79
|
+
gem = LocalGem.new(gem_name, version)
|
80
|
+
|
81
|
+
if !processed_gems.include?gem
|
82
|
+
processed_gems << gem
|
83
|
+
do_dependencies(gem_name, version) do |dep_gem|
|
84
|
+
collect_dependencies(dep_gem.name, dep_gem.version_requirements.to_s)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def validate
|
90
|
+
processed_gems.each do |gem|
|
91
|
+
file_name = File.join(local_gem_dir, gem.name + "-" + gem.version)
|
92
|
+
if !File.exists?file_name
|
93
|
+
puts " ** Warning: #{gem.name} was skipped"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_installation(source = 'http://gems.rubyforge.org')
|
99
|
+
processed_gems.each do |gem|
|
100
|
+
res = Gem.cache.search(/^#{gem.name}$/i, gem.version)
|
101
|
+
if !res or res.empty?
|
102
|
+
msg " ** #{gem.name} not installed. Installing #{gem.name} - #{gem.version}"
|
103
|
+
params = ["install", gem.name]
|
104
|
+
params << "--version=#{gem.version}"
|
105
|
+
params << "--source=#{source}"
|
106
|
+
sh "sudo gem #{params.join(" ")}"
|
107
|
+
else
|
108
|
+
msg " ** #{gem.name} has been installed."
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def freeze_gems
|
114
|
+
processed_gems.each do |gem|
|
115
|
+
file_name = File.join(local_gem_dir, gem.name + "-" + gem.version)
|
116
|
+
if File.exists?file_name
|
117
|
+
msg " ** #{gem.name} is already frozen, skipping it."
|
118
|
+
else
|
119
|
+
chdir(local_gem_dir) do
|
120
|
+
begin
|
121
|
+
Gem::GemRunner.new.run(["unpack", gem.name, "--version", gem.version])
|
122
|
+
spec = source_index.find_name(gem.name, gem.version).last
|
123
|
+
spec_file = File.join(file_name, "spec.yaml")
|
124
|
+
File.open(spec_file, "w") { |f| f.write(spec.to_yaml) }
|
125
|
+
rescue Exception => ex
|
126
|
+
puts ex
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def do_dependencies(gem_name, version = "> 0.0.0", &block)
|
134
|
+
raise "Block expected!" if !block_given?
|
135
|
+
source_indexes = Gem::SourceIndex.from_installed_gems
|
136
|
+
# get the last item in the 'found list'. That's the latest version. If user passed in specific version, then there's only 1 in the list
|
137
|
+
deps = source_indexes.find_name(gem_name, version).last.dependencies
|
138
|
+
msg " ** Found #{deps.size} dependencies for #{gem_name}-#{version}"
|
139
|
+
deps.each do |dep_gem|
|
140
|
+
yield(dep_gem)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def msg(msg)
|
145
|
+
verbose = ENV['VERBOSE'] || ENV['verbose'] || false
|
146
|
+
verbose = false if verbose.to_s.downcase == 'false'
|
147
|
+
puts msg if verbose
|
148
|
+
print "." if !verbose
|
149
|
+
end
|
150
|
+
|
151
|
+
class LocalGem
|
152
|
+
attr_accessor :name
|
153
|
+
attr_accessor :version
|
154
|
+
|
155
|
+
def initialize(name, version)
|
156
|
+
self.name = name
|
157
|
+
self.version = version
|
158
|
+
end
|
159
|
+
|
160
|
+
def to_s
|
161
|
+
"#{name}-#{version}"
|
162
|
+
end
|
163
|
+
|
164
|
+
def ==(other)
|
165
|
+
other.to_s == self.to_s
|
166
|
+
end
|
167
|
+
|
168
|
+
def eql?(other)
|
169
|
+
other.to_s == self.to_s
|
170
|
+
end
|
171
|
+
|
172
|
+
def hash
|
173
|
+
self.to_s.hash
|
174
|
+
end
|
175
|
+
end
|