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
@@ -63,7 +63,7 @@ module Mack
|
|
63
63
|
|
64
64
|
private
|
65
65
|
def do_render_remote_url(url, options)
|
66
|
-
Timeout::timeout(
|
66
|
+
Timeout::timeout(configatron.mack.retrieve(:render_url_timeout, 5)) do
|
67
67
|
uri = URI.parse(url)
|
68
68
|
response = yield uri, options
|
69
69
|
if response.code == "200"
|
@@ -79,7 +79,7 @@ module Mack
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def do_render_local_url(url, options)
|
82
|
-
Timeout::timeout(
|
82
|
+
Timeout::timeout(configatron.mack.retrieve(:render_url_timeout, 5)) do
|
83
83
|
cooks = {}
|
84
84
|
self.view_template.cookies.all.each do |c,v|
|
85
85
|
cooks[c] = v[:value]
|
@@ -89,7 +89,7 @@ module Mack
|
|
89
89
|
env = request.env.dup
|
90
90
|
env - ["rack.input", "rack.errors", "PATH_INFO", "REQUEST_PATH", "REQUEST_URI", "REQUEST_METHOD"]
|
91
91
|
env["rack.request.query_hash"] = options[:parameters] || {}
|
92
|
-
env["HTTP_COOKIE"] = "#{
|
92
|
+
env["HTTP_COOKIE"] = "#{configatron.mack.session_id}=#{request.session.id};" if env["HTTP_COOKIE"].nil?
|
93
93
|
options = env.merge(options)
|
94
94
|
# Mack.logger.debug "NEW OPTIONS: #{options.inspect}"
|
95
95
|
# Mack.logger.debug "url: #{url}"
|
@@ -15,6 +15,10 @@ module Mack
|
|
15
15
|
self.options = options
|
16
16
|
@_yield_to_cache = {}
|
17
17
|
Thread.current[:view_template] = self
|
18
|
+
# Define methods for :locals
|
19
|
+
(self.options[:locals] || {}).each do |k,v|
|
20
|
+
define_instance_method(k) {v}
|
21
|
+
end
|
18
22
|
end
|
19
23
|
|
20
24
|
# Allows access to the current Mack::Controller object.
|
@@ -37,13 +41,6 @@ module Mack
|
|
37
41
|
self.controller.cookies
|
38
42
|
end
|
39
43
|
|
40
|
-
# If a method can not be found then the :locals key of
|
41
|
-
# the options is used to find the variable.
|
42
|
-
def method_missing(sym, *args)
|
43
|
-
raise NoMethodError.new(sym.to_s) unless self.options[:locals]
|
44
|
-
self.options[:locals][sym]
|
45
|
-
end
|
46
|
-
|
47
44
|
# Maps to the controller's param method. See also Mack::Controller::Base params.
|
48
45
|
def params
|
49
46
|
self.controller.params
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Mack
|
2
|
+
module Routes
|
3
|
+
|
4
|
+
private
|
5
|
+
class ResourceProxy # :nodoc:
|
6
|
+
|
7
|
+
attr_accessor :controller
|
8
|
+
attr_accessor :routes
|
9
|
+
|
10
|
+
def initialize(controller)
|
11
|
+
self.controller = controller
|
12
|
+
self.routes = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(sym, *args)
|
16
|
+
connect(sym, *args)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def connect(name, path, options = {})
|
21
|
+
route = {}
|
22
|
+
route[:name] = name.to_s.gsub(/^#{self.controller}/, '')
|
23
|
+
route[:options] = {:controller => self.controller, :action => route[:name].to_sym, :method => :get}.merge(options)
|
24
|
+
paths = path.split('/')
|
25
|
+
paths.insert(0, self.controller.to_s)
|
26
|
+
route[:path] = paths.reject{|m| m.blank?}.uniq.join('/')
|
27
|
+
routes << route
|
28
|
+
end
|
29
|
+
|
30
|
+
end # ResourceProxy
|
31
|
+
|
32
|
+
end # Routes
|
33
|
+
end # Mack
|
@@ -1,326 +1,160 @@
|
|
1
1
|
module Mack
|
2
|
-
|
3
2
|
module Routes
|
4
|
-
include Extlib::Hook
|
5
3
|
|
6
|
-
|
7
|
-
#
|
8
|
-
# See Mack::Routes::RouteMap for more information.
|
9
|
-
def self.build
|
10
|
-
yield Mack::Routes::RouteMap.instance
|
11
|
-
Mack::Routes::Urls.include_safely_into(Mack::Controller,
|
12
|
-
Mack::Rendering::ViewTemplate,
|
13
|
-
Test::Unit::TestCase)
|
14
|
-
end
|
15
|
-
|
16
|
-
# Routes are the back bone of the Mack framework. They are used to map incoming urls to controllers.
|
17
|
-
#
|
18
|
-
# === Defining Routes:
|
19
|
-
# Example:
|
20
|
-
# Mack::Routes.build do |r|
|
21
|
-
#
|
22
|
-
# # Connects "/" to the HomeController and the '/' action.
|
23
|
-
# r.connect "/", :controller => :home
|
24
|
-
#
|
25
|
-
# # Connects "/foo", to the HomeController and the 'foo' action.
|
26
|
-
# r.connect "/foo", :controller => :home, :action => :foo
|
27
|
-
#
|
28
|
-
# # Connects "/blog" to the BlogController and the 'list' action.
|
29
|
-
# r.connect "/blog", :controller => :blog, :action => :list
|
30
|
-
#
|
31
|
-
# # Connects "/blog/:id" to the BlogController and the 'index' action.
|
32
|
-
# # It will also take the second half of the url and map it to a parameter called :id.
|
33
|
-
# # Example:
|
34
|
-
# # '/blog/1' # => goes to the BlogController, 'index' action, and has an :id parameter == 1.
|
35
|
-
# r.connect "/blog/:id", :controller => :blog, :action => :index
|
36
|
-
#
|
37
|
-
# # Connects "/blog/create" to the BlogController and the 'create' action.
|
38
|
-
# # It also insists that the HTTP method be 'post'. If it's not 'post' it will not match this route.
|
39
|
-
# r.connect "/blog/create", :controller => :blog, :action => :create, :method => :post
|
40
|
-
#
|
41
|
-
# # Connects "/comment/destroy/:id" to the CommentController and the 'destroy' action.
|
42
|
-
# # It also insists that the HTTP method be 'delete'. If it's not 'delete' it will not match this route.
|
43
|
-
# # It will also create an :id parameter.
|
44
|
-
# r.connect "/comment/destroy/:id", :controller => :comment, :action => :destroy, :method => :delete
|
45
|
-
#
|
46
|
-
# # This will create 'RESTful' routes. Unlike Rails, it doesn't generate a mixture of singular/plural
|
47
|
-
# # routes. It uses whatever you pass in to it. This will also create named routes in Mack::Routes::Urls.
|
48
|
-
# # Examples:
|
49
|
-
# # '/users' # => {:controller => 'users', :action => :index, :method => :get}
|
50
|
-
# # # => users_index_url
|
51
|
-
# # # => users_index_full_url
|
52
|
-
# # '/users' # => {:controller => 'users', :action => :create, :method => :post}
|
53
|
-
# # # => users_create_url
|
54
|
-
# # # => users_create_full_url
|
55
|
-
# # '/users/new' # => {:controller => 'users', :action => :new, :method => :get}
|
56
|
-
# # # => users_new_url
|
57
|
-
# # # => users_new_full_url
|
58
|
-
# # '/users/:id' # => {:controller => 'users', :action => :show, :method => :get}
|
59
|
-
# # # => users_show_url
|
60
|
-
# # # => users_show_full_url
|
61
|
-
# # '/users/:id/:edit # => {:controller => 'users', :action => :edit, :method => :get}
|
62
|
-
# # # => users_edit_url
|
63
|
-
# # # => users_edit_full_url
|
64
|
-
# # '/users/:id # => {:controller => 'users', :action => :update, :method => :put}
|
65
|
-
# # # => users_update_url
|
66
|
-
# # # => users_update_full_url
|
67
|
-
# # '/users/:id # => {:controller => 'users', :action => :delete, :method => :delete}
|
68
|
-
# # # => users_delete_url
|
69
|
-
# # # => users_delete_full_url
|
70
|
-
# r.resource :users
|
71
|
-
#
|
72
|
-
# # This will redirect '/old_users/show/:id' to '/users/:id' with a status of 302, 'Moved Temporarily'.
|
73
|
-
# # Examples:
|
74
|
-
# # '/old_users/show/1' # => '/users/1' (status of 302)
|
75
|
-
# # '/old_users/show/1?foo=bar' # => '/users/1?foo=bar' (status of 302)
|
76
|
-
# r.connect '/old_users/show/:id', :redirect_to => "/users/:id"
|
77
|
-
#
|
78
|
-
# # This will redirect '/old_blog' to '/blog' with a status of 301, 'Moved Permanently'.
|
79
|
-
# # Examples:
|
80
|
-
# # '/old_blog' # => '/blog' (status of 301)
|
81
|
-
# # '/old_blog?foo=bar' # => '/blogfoo=bar' (status of 301)
|
82
|
-
# r.connect '/old_blog', :redirect_to => "/blog", :status => 301
|
83
|
-
#
|
84
|
-
# # Connects "/comment/update/:id" to the CommentController and the 'update' action.
|
85
|
-
# # It will also create an :id parameter.
|
86
|
-
# # It will also create a named route in Mack::Routes::Urls called, 'c_u_url'.
|
87
|
-
# # In a controller or a view this: c_u_url(:id => 1) would return '/comment/update/1'.
|
88
|
-
# # It will also create a named route in Mack::Routes::Urls called, 'c_u_full_url'.
|
89
|
-
# # In a controller or a view this: c_u_full_url(:id => 1) would return 'http://example.org/comment/update/1'.
|
90
|
-
# r.c_u "/comment/update/:id", {:controller => :comment, :action => :update}
|
91
|
-
#
|
92
|
-
# # This creates 'Rails' style routes.
|
93
|
-
# # Any requests that come in that aren't found by explicit routes, will fall into these routes.
|
94
|
-
# # '/:controller/:action'
|
95
|
-
# # '/:controller/:action/:id'
|
96
|
-
# #
|
97
|
-
# # Example:
|
98
|
-
# # '/comment/show/1' # => Goes to CommentController, the 'show' action, with a parameter of 1.
|
99
|
-
# r.defaults
|
100
|
-
#
|
101
|
-
# end
|
102
|
-
#
|
103
|
-
# === Named Routes:
|
104
|
-
# Mack::Routes.build do |r|
|
105
|
-
# r.resource :users
|
106
|
-
# end
|
107
|
-
# See above in 'Defining Routes' to see what fully gets created when you map a resource, but let's look
|
108
|
-
# at the named route stuff that gets generated. In particular let's look at one example:
|
109
|
-
# '/users/:id' # => {:controller => 'users', :action => :show, :method => :get}
|
110
|
-
# # => users_show_url
|
111
|
-
# # => users_show_full_url
|
112
|
-
# The following can be used in controllers, views, and tests:
|
113
|
-
# users_show_url(:id => 1) # => '/users/1'
|
114
|
-
# # The following can only be used when there is a @request (Mack::Request) instance variable around:
|
115
|
-
# users_show_full_url(:id => 1) # => 'http://example.org/users/1'
|
116
|
-
#
|
117
|
-
# Mack::Routes.build do |r|
|
118
|
-
# r.hello_world "/", :controller => :home_page, :action => :hello
|
119
|
-
# end
|
120
|
-
# This will give you the following two methods:
|
121
|
-
# hello_world_url # => "/"
|
122
|
-
# hello_world_full_url # => "http://example.org/"
|
123
|
-
# These methods act just like the ones created when you use the resource method.
|
124
|
-
#
|
125
|
-
# === Exception Routes:
|
126
|
-
# You can define a route that will catch exceptions that are raised in other controllers.
|
127
|
-
#
|
128
|
-
# Mack::Routes.build do |r|
|
129
|
-
# r.handle_error Mack::ResourceNotFound, :controller => :oops, :action => :404
|
130
|
-
# r.handle_error HollyCrapError, :controller => :oops, :action => :500
|
131
|
-
# end
|
132
|
-
# In the example if an action raises a Mack::ResourceNotFound it will be caught and rendered
|
133
|
-
# using the OopsController and the 404 action.
|
134
|
-
# If A HollyCrapError is thrown it will be caught and rendered using the OopsController and the 500 action.
|
135
|
-
# You can catch all exceptions using Exception.
|
4
|
+
private
|
5
|
+
# See Mack::Routes for more information.
|
136
6
|
class RouteMap
|
137
|
-
include Extlib::Hook
|
138
7
|
include Singleton
|
139
8
|
|
140
9
|
def initialize # :nodoc:
|
141
|
-
|
142
|
-
@default_routes_list = []
|
143
|
-
@handle_error_routes = {}
|
10
|
+
reset!
|
144
11
|
end
|
145
12
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
# These get created for each of the 4 HTTP verbs.
|
150
|
-
def defaults
|
151
|
-
@default_routes_list = []
|
152
|
-
[:get, :post, :put, :delete].each do |verb|
|
153
|
-
@default_routes_list << build_route("/:controller/:action/:id", :method => verb)
|
154
|
-
@default_routes_list << build_route("/:controller/:action", :method => verb)
|
155
|
-
end
|
13
|
+
def reset! # :nodoc:
|
14
|
+
@_default_routes = []
|
15
|
+
@_route_map = {:get => [], :post => [], :put => [], :delete => [], :errors => {}}
|
156
16
|
end
|
157
17
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
return
|
18
|
+
def any? # :nodoc:
|
19
|
+
@_route_map.each do |k, v|
|
20
|
+
return true if v.any?
|
21
|
+
end
|
22
|
+
return false
|
163
23
|
end
|
164
24
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
connect_with_named_route("#{controller}_show", "/#{controller}/:id", {:controller => controller, :action => :show, :method => :get})
|
171
|
-
connect_with_named_route("#{controller}_edit", "/#{controller}/:id/edit", {:controller => controller, :action => :edit, :method => :get})
|
172
|
-
connect_with_named_route("#{controller}_update", "/#{controller}/:id", {:controller => controller, :action => :update, :method => :put})
|
173
|
-
connect_with_named_route("#{controller}_delete", "/#{controller}/:id", {:controller => controller, :action => :delete, :method => :delete})
|
25
|
+
def empty? # :nodoc:
|
26
|
+
@_route_map.each do |k, v|
|
27
|
+
return false if v.any?
|
28
|
+
end
|
29
|
+
return true
|
174
30
|
end
|
175
31
|
|
176
|
-
def
|
177
|
-
|
32
|
+
def retrieve(url_or_request, verb = :get) # :nodoc:
|
33
|
+
path = url_or_request
|
34
|
+
host = nil
|
35
|
+
scheme = nil
|
36
|
+
port = nil
|
37
|
+
if url_or_request.is_a?(Mack::Request)
|
38
|
+
path = url_or_request.path_info
|
39
|
+
host = url_or_request.host
|
40
|
+
scheme = url_or_request.scheme
|
41
|
+
port = url_or_request.port
|
42
|
+
verb = (url_or_request.params["_method"] || url_or_request.request_method.downcase).to_sym
|
43
|
+
end
|
44
|
+
path = path.dup
|
45
|
+
format = (File.extname(path).blank? ? '.html' : File.extname(path))
|
46
|
+
format = format[1..format.length]
|
47
|
+
routes = @_route_map[verb]
|
48
|
+
routes.each do |route|
|
49
|
+
if route.options[:host]
|
50
|
+
next unless route.options[:host].downcase == host
|
51
|
+
end
|
52
|
+
if route.options[:scheme]
|
53
|
+
next unless route.options[:scheme].downcase == scheme
|
54
|
+
end
|
55
|
+
if route.options[:port]
|
56
|
+
next unless route.options[:port].to_i == port.to_i
|
57
|
+
end
|
58
|
+
if route.match?(path)
|
59
|
+
ret_val = route.options_with_parameters(path)
|
60
|
+
return ret_val
|
61
|
+
end
|
62
|
+
end
|
63
|
+
@_default_routes.each do |route|
|
64
|
+
if route.match?(path) && route.options[:method] == verb
|
65
|
+
ret_val = route.options_with_parameters(path)
|
66
|
+
return ret_val
|
67
|
+
end
|
68
|
+
end
|
69
|
+
raise Mack::Errors::UndefinedRoute.new(path)
|
178
70
|
end
|
179
71
|
|
180
|
-
def
|
181
|
-
|
72
|
+
def retrieve_from_error(error) # :nodoc:
|
73
|
+
@_route_map[:errors][error]
|
182
74
|
end
|
183
75
|
|
184
|
-
#
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
def get_route_from_request(req)
|
190
|
-
orig_pattern = req.path_info.dup
|
191
|
-
pattern = req.path_info.downcase
|
192
|
-
unless pattern == "/"
|
193
|
-
pattern.chop! if pattern.match(/\/$/)
|
194
|
-
end
|
195
|
-
meth = (req.params["_method"] || req.request_method.downcase).to_sym
|
196
|
-
rt = routes_list.dup
|
197
|
-
rt << @default_routes_list.dup
|
198
|
-
rt.flatten!
|
199
|
-
begin
|
200
|
-
rt.each do |route|
|
201
|
-
if pattern.match(route.regex_pattern) && route.method == meth
|
202
|
-
r = route
|
203
|
-
opts = r.options_with_embedded_parameters(orig_pattern)
|
204
|
-
req.merge_params(opts)
|
205
|
-
return opts
|
206
|
-
end
|
207
|
-
end
|
208
|
-
rescue Exception => e
|
209
|
-
raise e
|
76
|
+
# Connects a url pattern to a controller, an action, and an HTTP verb.
|
77
|
+
def connect(path, options = {}, &block)
|
78
|
+
options = handle_options(options, &block)
|
79
|
+
if path.is_a?(String)
|
80
|
+
path = "/#{path}" unless path.match(/^\//)
|
210
81
|
end
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
# Given an error class name it will return a routing options Hash, or nil, if one
|
216
|
-
# has not been mapped.
|
217
|
-
def get_route_from_error(error)
|
218
|
-
@handle_error_routes[error]
|
82
|
+
route = RouteObject.new(path, options)
|
83
|
+
@_route_map[options[:method]] << route
|
84
|
+
route
|
219
85
|
end
|
220
86
|
|
221
|
-
|
87
|
+
def method_missing(sym, *args, &block) # :nodoc:
|
88
|
+
connect_with_name(sym, *args, &block)
|
89
|
+
end
|
222
90
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
route
|
91
|
+
# Creates 'Rails' style default mappings:
|
92
|
+
# "/:controller/:action/:id"
|
93
|
+
# "/:controller/:action"
|
94
|
+
# These get created for each of the 4 HTTP verbs.
|
95
|
+
def defaults
|
96
|
+
[:get, :post, :put, :delete].each do |verb|
|
97
|
+
@_default_routes << RouteObject.new("/:controller/:action/:id", :method => verb)
|
98
|
+
@_default_routes << RouteObject.new("/:controller/:action", :method => verb)
|
99
|
+
end
|
233
100
|
end
|
234
101
|
|
235
|
-
def
|
236
|
-
|
237
|
-
route = connect(pattern, options)
|
238
|
-
|
239
|
-
url = %{
|
240
|
-
def #{n_route}_url(options = {})
|
241
|
-
url_for_pattern("#{route.original_pattern}", options)
|
242
|
-
end
|
243
|
-
|
244
|
-
def #{n_route}_full_url(options = {})
|
245
|
-
u = #{n_route}_url(options)
|
246
|
-
"\#{@request.full_host}\#{u}"
|
247
|
-
end
|
248
|
-
}
|
249
|
-
|
250
|
-
Mack::Routes::Urls.class_eval(url)
|
102
|
+
def handle_error(error, options)
|
103
|
+
@_route_map[:errors][error] = options
|
251
104
|
end
|
252
105
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
segs << sec
|
106
|
+
# Sets up mappings and named routes for a resource.
|
107
|
+
def resource(controller, &block)
|
108
|
+
# yield up to add other resources:
|
109
|
+
if block_given?
|
110
|
+
proxy = ResourceProxy.new(controller)
|
111
|
+
yield proxy
|
112
|
+
proxy.routes.each do |route|
|
113
|
+
connect_with_name("#{controller}_#{route[:name]}", route[:path], route[:options])
|
262
114
|
end
|
263
115
|
end
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
116
|
+
# connect the default resources:
|
117
|
+
connect_with_name("#{controller}_index", "/#{controller}", {:controller => controller, :action => :index, :method => :get})
|
118
|
+
connect_with_name("#{controller}_create", "/#{controller}", {:controller => controller, :action => :create, :method => :post})
|
119
|
+
connect_with_name("#{controller}_new", "/#{controller}/new", {:controller => controller, :action => :new, :method => :get})
|
120
|
+
connect_with_name("#{controller}_show", "/#{controller}/:id", {:controller => controller, :action => :show, :method => :get})
|
121
|
+
connect_with_name("#{controller}_edit", "/#{controller}/:id/edit", {:controller => controller, :action => :edit, :method => :get})
|
122
|
+
connect_with_name("#{controller}_update", "/#{controller}/:id", {:controller => controller, :action => :update, :method => :put})
|
123
|
+
connect_with_name("#{controller}_delete", "/#{controller}/:id", {:controller => controller, :action => :delete, :method => :delete})
|
124
|
+
end
|
125
|
+
|
126
|
+
def inspect # :nodoc:
|
127
|
+
@_route_map.inspect
|
128
|
+
end
|
275
129
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
attr_accessor :options
|
281
|
-
attr_accessor :embedded_parameters
|
130
|
+
private
|
131
|
+
def connect_with_name(name, path, options = {}, &block)
|
132
|
+
n_route = name.methodize
|
133
|
+
route = connect(path, {:action => n_route.to_sym}.merge(options), &block)
|
282
134
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
self.options = options
|
288
|
-
self.embedded_parameters = []
|
289
|
-
# find out where the embedded_parameters are:
|
290
|
-
original_pattern.split("/").each_with_index do |seg, ind|
|
291
|
-
if seg.match(/^:/)
|
292
|
-
self.embedded_parameters[ind] = seg[1..seg.length].to_sym
|
293
|
-
end
|
294
|
-
end
|
135
|
+
Mack::Routes::Urls.create_method("#{n_route}_url") do |*options|
|
136
|
+
options = *options
|
137
|
+
options = {} if options.nil? || !options.is_a?(Hash)
|
138
|
+
url_for_pattern(route.path, (route.options.reject{|k,v| k.to_sym == :action || k.to_sym == :controller || k.to_sym == :method}).merge(options))
|
295
139
|
end
|
296
140
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
if
|
301
|
-
|
302
|
-
opts[:format]= m[1..m.size].to_sym
|
303
|
-
uri.gsub!(/\..+$/, "")
|
304
|
-
end
|
305
|
-
split_uri = uri.split("/")
|
306
|
-
self.embedded_parameters.each_with_index do |val, ind|
|
307
|
-
unless val.nil?
|
308
|
-
opts[val] = split_uri[ind]
|
309
|
-
end
|
141
|
+
Mack::Routes::Urls.create_method("#{n_route}_full_url") do |*options|
|
142
|
+
options = *options
|
143
|
+
options = {} if options.nil? || !options.is_a?(Hash)
|
144
|
+
if @request
|
145
|
+
options = {:host => @request.host, :scheme => @request.scheme, :port => @request.port}.merge(options)
|
310
146
|
end
|
311
|
-
|
312
|
-
if opts[key]
|
313
|
-
opts[key] = opts[key].to_s.downcase.to_sym
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
opts
|
147
|
+
self.send("#{n_route}_url", options)
|
318
148
|
end
|
319
|
-
|
320
|
-
|
149
|
+
end
|
150
|
+
|
151
|
+
def handle_options(opts, &block)
|
152
|
+
opts = {:method => :get}.merge(opts.symbolize_keys)
|
153
|
+
opts[:runner_block] = block if block_given?
|
154
|
+
opts
|
155
|
+
end
|
321
156
|
|
322
157
|
end # RouteMap
|
323
|
-
|
158
|
+
|
324
159
|
end # Routes
|
325
|
-
|
326
|
-
end # Mack
|
160
|
+
end # Mack
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Mack
|
2
|
+
module Routes
|
3
|
+
|
4
|
+
private
|
5
|
+
class RouteObject # :nodoc:
|
6
|
+
attr_accessor :options
|
7
|
+
attr_accessor :path
|
8
|
+
attr_accessor :regex_pattern
|
9
|
+
attr_accessor :embedded_parameters
|
10
|
+
attr_accessor :wildcard
|
11
|
+
|
12
|
+
def initialize(path, options = {})
|
13
|
+
self.path = path
|
14
|
+
self.options = {:action => :index}.merge(options)
|
15
|
+
self.embedded_parameters = []
|
16
|
+
build_regex_pattern
|
17
|
+
end
|
18
|
+
|
19
|
+
def ==(other)
|
20
|
+
self.options == other
|
21
|
+
end
|
22
|
+
|
23
|
+
def match?(url)
|
24
|
+
if url.downcase.match(self.regex_pattern)
|
25
|
+
if self.options[:format]
|
26
|
+
format = (File.extname(url).blank? ? '.html' : File.extname(url))
|
27
|
+
format = format[1..format.length]
|
28
|
+
return format.to_sym == self.options[:format]
|
29
|
+
end
|
30
|
+
return true
|
31
|
+
end
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
|
35
|
+
def options_with_parameters(url)
|
36
|
+
format = (File.extname(url).blank? ? '.html' : File.extname(url))
|
37
|
+
format = format[1..format.length]
|
38
|
+
opts = self.options.merge(:format => format)
|
39
|
+
url = url.gsub(/\.#{format}$/, '')
|
40
|
+
if self.embedded_parameters.any?
|
41
|
+
url.split('/').each_with_index do |seg, i|
|
42
|
+
ep = self.embedded_parameters[i]
|
43
|
+
unless ep.nil?
|
44
|
+
opts[ep.to_sym] = seg
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
if self.wildcard
|
49
|
+
caps = url.match(self.regex_pattern).captures
|
50
|
+
if caps
|
51
|
+
opts[self.wildcard.to_sym] = caps.first.split('/')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
opts
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def build_regex_pattern
|
60
|
+
if self.path.is_a?(Regexp)
|
61
|
+
self.regex_pattern = self.path
|
62
|
+
elsif self.path.is_a?(String)
|
63
|
+
reg = []
|
64
|
+
if self.path == '/'
|
65
|
+
self.regex_pattern = /^\/$/
|
66
|
+
else
|
67
|
+
self.path.split('/').each_with_index do |seg, i|
|
68
|
+
if seg.match(/^:/)
|
69
|
+
self.embedded_parameters[i] = seg.gsub(':', '')
|
70
|
+
reg << '[^/]+'
|
71
|
+
elsif seg.match(/^\*/)
|
72
|
+
self.wildcard = seg.gsub('*', '')
|
73
|
+
reg << '(.+)'
|
74
|
+
else
|
75
|
+
reg << seg.downcase
|
76
|
+
end
|
77
|
+
end
|
78
|
+
self.regex_pattern = /^#{reg.join('/') + '(\..+$|$)'}/
|
79
|
+
end
|
80
|
+
else
|
81
|
+
raise ArgumentError.new("'#{self.path}' is a #{self.path.class} and it should be either a String or Regexp!")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end # RouteObject
|
86
|
+
|
87
|
+
end # Routes
|
88
|
+
end # Mack
|