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.
Files changed (76) hide show
  1. data/CHANGELOG +32 -0
  2. data/bin/gem_load_path.rb +1 -1
  3. data/bin/mackery +0 -1
  4. data/bin/mackery-server +5 -1
  5. data/lib/mack/assets/asset_helpers.rb +51 -0
  6. data/lib/mack/assets/assets_mgr.rb +165 -0
  7. data/lib/mack/controller/controller.rb +4 -4
  8. data/lib/mack/controller/cookie_jar.rb +1 -1
  9. data/lib/mack/controller/request.rb +13 -3
  10. data/lib/mack/controller/response.rb +12 -0
  11. data/lib/mack/core_extensions/kernel.rb +69 -0
  12. data/lib/mack/core_extensions/symbol.rb +4 -0
  13. data/lib/mack/errors/errors.rb +5 -1
  14. data/lib/mack/generators/controller_generator/manifest.yml +2 -2
  15. data/lib/mack/generators/controller_helper_generator/manifest.yml +2 -2
  16. data/lib/mack/generators/mack_application_generator/manifest.yml +10 -2
  17. data/lib/mack/generators/mack_application_generator/templates/config/{app_config/default.yml.template → configatron/default.rb.template} +10 -15
  18. data/lib/mack/generators/mack_application_generator/templates/config/{app_config/development.yml.template → configatron/development.rb.template} +1 -1
  19. data/lib/mack/generators/mack_application_generator/templates/config/{app_config/production.yml.template → configatron/production.rb.template} +0 -0
  20. data/lib/mack/generators/mack_application_generator/templates/config/{app_config/test.yml.template → configatron/test.rb.template} +1 -1
  21. data/lib/mack/generators/mack_application_generator/templates/public/404.html.template +15 -0
  22. data/lib/mack/generators/mack_application_generator/templates/public/500.html.template +15 -0
  23. data/lib/mack/generators/view_helper_generator/manifest.yml +2 -2
  24. data/lib/mack/initialization/application.rb +9 -5
  25. data/lib/mack/initialization/boot_loader.rb +2 -104
  26. data/lib/mack/initialization/configuration.rb +72 -69
  27. data/lib/mack/initialization/console.rb +1 -1
  28. data/lib/mack/initialization/helpers.rb +1 -6
  29. data/lib/mack/initialization/logging/basic_layout.rb +14 -0
  30. data/lib/mack/initialization/logging/color_layout.rb +23 -0
  31. data/lib/mack/initialization/logging/filter.rb +45 -0
  32. data/lib/mack/initialization/logging.rb +33 -89
  33. data/lib/mack/initialization/plugins.rb +1 -1
  34. data/lib/mack/rendering/engine/builder.rb +3 -0
  35. data/lib/mack/rendering/engine/erubis.rb +28 -16
  36. data/lib/mack/rendering/type/file_base.rb +1 -1
  37. data/lib/mack/rendering/type/url.rb +3 -3
  38. data/lib/mack/rendering/view_template.rb +4 -7
  39. data/lib/mack/routing/resource_proxy.rb +33 -0
  40. data/lib/mack/routing/route_map.rb +122 -288
  41. data/lib/mack/routing/route_object.rb +88 -0
  42. data/lib/mack/routing/routes.rb +169 -0
  43. data/lib/mack/routing/urls.rb +39 -5
  44. data/lib/mack/runner.rb +65 -32
  45. data/lib/mack/runner_helpers/request_logger.rb +3 -3
  46. data/lib/mack/runner_helpers/session.rb +4 -4
  47. data/lib/mack/sessions/cookie_session_store.rb +3 -3
  48. data/lib/mack/sessions/session.rb +1 -1
  49. data/lib/mack/sessions/session_store_base.rb +1 -1
  50. data/lib/mack/tasks/gem_tasks.rake +156 -1
  51. data/lib/mack/tasks/mack_dump_tasks.rake +1 -1
  52. data/lib/mack/tasks/mack_update_tasks.rake +85 -1
  53. data/lib/mack/tasks/rake_rules.rake +6 -0
  54. data/lib/mack/tasks/test_tasks.rake +4 -4
  55. data/lib/mack/testing/helpers.rb +13 -6
  56. data/lib/mack/testing/rspec.rb +27 -9
  57. data/lib/mack/testing/test_case.rb +1 -1
  58. data/lib/mack/utils/ansi/ansi_color.rb +4 -1
  59. data/lib/mack/utils/forgery_detector.rb +3 -3
  60. data/lib/mack/utils/http_status_codes.rb +19 -0
  61. data/lib/mack/utils/http_status_codes.yml +55 -0
  62. data/lib/mack/utils/paths.rb +32 -32
  63. data/lib/mack/utils/reloader.rb +60 -0
  64. data/lib/mack/utils/server.rb +3 -3
  65. data/lib/mack/version.rb +1 -1
  66. data/lib/mack/view_helpers/all_helpers.rb +7 -0
  67. data/lib/mack/view_helpers/date_time_helpers.rb +16 -10
  68. data/lib/mack/view_helpers/form_helpers.rb +1 -1
  69. data/lib/mack/view_helpers/html_helpers.rb +22 -1
  70. data/lib/mack/view_helpers/link_helpers.rb +51 -10
  71. data/lib/mack/view_helpers/string_helpers.rb +1 -1
  72. data/lib/mack.rb +0 -1
  73. data/lib/mack_core.rb +8 -8
  74. data/lib/mack_tasks.rb +1 -1
  75. metadata +27 -15
  76. 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(app_config.mack.render_url_timeout || 5) do
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(app_config.mack.render_url_timeout || 5) do
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"] = "#{app_config.mack.session_id}=#{request.session.id};" if env["HTTP_COOKIE"].nil?
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
- # This method yields up Mack::Routes::RouteMap and allows for the creation of routes in the system.
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
- @routes_list = []
142
- @default_routes_list = []
143
- @handle_error_routes = {}
10
+ reset!
144
11
  end
145
12
 
146
- # Creates 'Rails' style default mappings:
147
- # "/:controller/:action/:id"
148
- # "/:controller/:action"
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
- # Connects a url pattern to a controller, an action, and an HTTP verb.
159
- def connect(pattern, options = {})
160
- route = build_route(pattern, options)
161
- routes_list << route
162
- return route
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
- # Sets up mappings and named routes for a resource.
166
- def resource(controller)
167
- connect_with_named_route("#{controller}_index", "/#{controller}", {:controller => controller, :action => :index, :method => :get})
168
- connect_with_named_route("#{controller}_create", "/#{controller}", {:controller => controller, :action => :create, :method => :post})
169
- connect_with_named_route("#{controller}_new", "/#{controller}/new", {:controller => controller, :action => :new, :method => :get})
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 handle_error(error, options = {})
177
- @handle_error_routes[error] = options
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 method_missing(sym, *args) # :nodoc:
181
- connect_with_named_route(sym, args.first, args.last)
72
+ def retrieve_from_error(error) # :nodoc:
73
+ @_route_map[:errors][error]
182
74
  end
183
75
 
184
- # Pass in a request and it will try and give you back a Hash representing the
185
- # options for that route. IE: controller, action, verb, etc...
186
- # If there are embedded options they added to the Hash. These parameters are
187
- # also added to the 'params' object in the request.
188
- # If the route can not be found a Mack::Errors::UndefinedRoute exception is raised.
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
- # Can't find the route!
212
- raise Mack::Errors::UndefinedRoute.new(req)
213
- end # get
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
- attr_reader :routes_list # :nodoc:
87
+ def method_missing(sym, *args, &block) # :nodoc:
88
+ connect_with_name(sym, *args, &block)
89
+ end
222
90
 
223
- private
224
- def build_route(pattern, options = {})
225
- # set the default options:
226
- options = {:action => :index, :method => :get}.merge(options)
227
- meth = options[:method].to_sym
228
- # if the pattern doesn't start with /, then add it.
229
- pattern = "/" << pattern unless pattern.match(/^\//)
230
- pt = pattern.downcase
231
- route = Route.new(pt, regex_from_pattern(pt), meth, options)
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 connect_with_named_route(n_route, pattern, options = {})
236
- n_route = n_route.methodize
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
- def regex_from_pattern(pattern)
254
- pattern.chop! if pattern.match(/\/$/)
255
- segs = []
256
- sections = pattern.split("/")
257
- sections.each_with_index do |sec, ind|
258
- if sec.match(/\A:/)
259
- segs << "[^/]+"
260
- else
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
- s = segs.join("/")
265
- s = "/" if s.blank?
266
- if s.match(".:format")
267
- s.gsub!(/\.:format/, "(\\..+|$)")
268
- else
269
- s << "(\\..+|$)"
270
- end
271
-
272
- rx = /^#{s}$/
273
- rx
274
- end # regex_from_pattern
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
- class Route # :nodoc:
277
- attr_accessor :regex_pattern
278
- attr_accessor :method
279
- attr_accessor :original_pattern
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
- def initialize(original_pattern, regex_pattern, method, options)
284
- self.original_pattern = original_pattern
285
- self.regex_pattern = regex_pattern
286
- self.method = method
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
- def options_with_embedded_parameters(uri)
298
- opts = {:format => :html}.merge(self.options)
299
- m = uri.match(/\..+$/)
300
- if m
301
- m = m.to_s
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
- [:controller, :action].each do |key|
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
- end # Route
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