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.
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