mack 0.7.1.1 → 0.8.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.
- 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
|