mack 0.5.5.4 → 0.6.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 (68) hide show
  1. data/CHANGELOG +34 -0
  2. data/README +1 -1
  3. data/bin/mack +7 -2
  4. data/lib/controller/controller.rb +371 -0
  5. data/lib/controller/cookie_jar.rb +2 -1
  6. data/lib/controller/filter.rb +3 -2
  7. data/lib/controller/request.rb +30 -26
  8. data/lib/controller/session.rb +5 -0
  9. data/lib/distributed/utils/rinda.rb +1 -1
  10. data/lib/errors/errors.rb +5 -3
  11. data/lib/generators/mack_application_generator/mack_application_generator.rb +4 -0
  12. data/lib/generators/mack_application_generator/manifest.yml +40 -7
  13. data/lib/generators/mack_application_generator/templates/Rakefile.template +5 -1
  14. data/lib/generators/mack_application_generator/templates/app/controllers/default_controller.rb.template +2 -1
  15. data/lib/generators/mack_application_generator/templates/app/helpers/controllers/default_controller_helper.rb.template +7 -0
  16. data/lib/generators/mack_application_generator/templates/app/helpers/views/application_helper.rb.template +7 -0
  17. data/lib/generators/mack_application_generator/templates/config/app_config/default.yml.template +2 -1
  18. data/lib/generators/mack_application_generator/templates/config/database.yml.template +11 -10
  19. data/lib/generators/mack_application_generator/templates/test/functional/default_controller_spec.rb.template +9 -0
  20. data/lib/generators/mack_application_generator/templates/test/functional/default_controller_test.rb.template +10 -0
  21. data/lib/generators/mack_application_generator/templates/test/spec.opts.template +2 -0
  22. data/lib/generators/mack_application_generator/templates/test/spec_helper.rb.template +8 -0
  23. data/lib/generators/mack_application_generator/templates/test/test_helper.rb.template +2 -1
  24. data/lib/initialization/application.rb +46 -0
  25. data/lib/initialization/configuration.rb +23 -38
  26. data/lib/initialization/console.rb +5 -2
  27. data/lib/initialization/helpers.rb +31 -0
  28. data/lib/initialization/logging.rb +69 -15
  29. data/lib/initialization/orm_support.rb +10 -4
  30. data/lib/initialization/plugins.rb +1 -1
  31. data/lib/mack.rb +18 -76
  32. data/lib/mack_tasks.rb +4 -1
  33. data/lib/rendering/engine/erubis.rb +1 -1
  34. data/lib/rendering/engine/registry.rb +5 -5
  35. data/lib/rendering/type/action.rb +3 -2
  36. data/lib/rendering/type/base.rb +1 -1
  37. data/lib/rendering/type/layout.rb +2 -2
  38. data/lib/rendering/type/partial.rb +1 -1
  39. data/lib/rendering/type/public.rb +1 -1
  40. data/lib/rendering/type/template.rb +1 -1
  41. data/lib/rendering/type/url.rb +4 -4
  42. data/lib/rendering/type/xml.rb +3 -2
  43. data/lib/rendering/view_template.rb +7 -7
  44. data/lib/routing/route_map.rb +27 -5
  45. data/lib/routing/urls.rb +1 -0
  46. data/lib/runner.rb +52 -17
  47. data/lib/tasks/cachetastic_tasks.rake +2 -2
  48. data/lib/tasks/mack_server_tasks.rake +2 -4
  49. data/lib/tasks/mack_update_tasks.rake +26 -0
  50. data/lib/tasks/rake_rules.rake +6 -2
  51. data/lib/tasks/test_tasks.rake +28 -10
  52. data/lib/testing/helpers.rb +187 -0
  53. data/lib/testing/response.rb +49 -0
  54. data/lib/testing/rspec.rb +20 -0
  55. data/lib/testing/test_assertions.rb +55 -0
  56. data/lib/{test_extensions → testing}/test_case.rb +9 -7
  57. data/lib/utils/crypt/keeper.rb +1 -1
  58. data/lib/utils/server.rb +2 -2
  59. data/lib/view_helpers/html_helpers.rb +4 -0
  60. metadata +26 -40
  61. data/lib/controller/base.rb +0 -345
  62. data/lib/generators/mack_application_generator/templates/app/helpers/application_helper.rb.template +0 -2
  63. data/lib/generators/mack_application_generator/templates/config/thin.ru.template +0 -1
  64. data/lib/generators/mack_application_generator/templates/config/thin.yml.template +0 -8
  65. data/lib/rendering/engine/haml.rb +0 -18
  66. data/lib/rendering/engine/markaby.rb +0 -28
  67. data/lib/test_extensions/test_assertions.rb +0 -55
  68. data/lib/test_extensions/test_helpers.rb +0 -192
data/CHANGELOG CHANGED
@@ -1,3 +1,37 @@
1
+ ===0.6.0
2
+ * INCOMPATIBILITY NOTICE: Moved Mack::Configuration.root to Mack.root
3
+ * INCOMPATIBILITY NOTICE: Moved Mack::Configuration.env to Mack.env
4
+ * INCOMPATIBILITY NOTICE: Mack::Configuration.* path methods no longer exist. Use mack-paths instead.
5
+ * INCOMPATIBILITY NOTICE: Dropped mack_ruby_core_extensions in favor or mack-facets
6
+ * INCOMPATIBILITY NOTICE: Mack::Controller::Base is now Mack::Controller (and it's now a module)
7
+ * INCOMPATIBILITY NOTICE: Haml renderer is now part of mack-more.
8
+ * INCOMPATIBILITY NOTICE: Markaby renderer is now part of mack-more.
9
+ * INCOMPATIBILITY NOTICE: Changed request param's accessor routine, from params(key) to params[key]
10
+ * INCOMPATIBILITY NOTICE: Test::Unit::TestCase is no longer the default testing framework, RSpec is. If you wish to use
11
+ Test::Unit::TestCase add the following config parameter to your config/app_config/default.yml file:
12
+ mack::testing_framework: test_case
13
+ * INCOMPATIBILITY NOTICE: ENV["_mack_env"] and ENV["_mack_root"] are no longer supported, please use ENV["MACK_ENV"] and ENV["MACK_ROOT"], or just Mack.env and Mack.root
14
+ * INCOMPATIBILITY NOTICE: MACK_DEFAULT_LOGGER constant is no longer available. Please use Mack.logger instead.
15
+ * INCOMPATIBILITY NOTICE: The ApplicationHelper module is now deprecated. Please move view level helpers into Mack::ViewHelpers::* and controller helpers into Mack::ControllerHelpers::<controller_name>
16
+ * thin.ru and thin.yml are no longer needed, you may delete them.
17
+ * RSpec assertions are now automatically added.
18
+ * Added a Mack::Testing::Response class to make testing of responses easier.
19
+ * moved test_extensions to testing and added the module Testing to the files in it.
20
+ * Added a dependency on mack-more
21
+ * Added a set of Rake tasks to update existing Mack applications.
22
+ * [#30] Added Mack::Logging::Filter to filter out unwanted parameters from the logs.
23
+ * In routing you can now define a route that will catch an Exception from another controller.
24
+ * ORM will not be initialized if the app never specify which ORM to use.
25
+ * All Mack unit tests are now written using rspec-1.1.4.
26
+ * mack command now takes an optional -t flag to determine which testing framework to use--value could be test_case or rspec [default]
27
+ * new setting added to app_config: testing_framework
28
+ * gem: cachetastic 1.7.2
29
+ * gem: application_configuration 1.5.0
30
+ * gem: erubis 2.6.2
31
+ * gem: genosaurus 1.2.1
32
+ * gem: thin 0.8.2
33
+ * gem: rspec 1.1.4
34
+
1
35
  ===0.5.5.4
2
36
  * Fixed the damn Lint error some people were facing!
3
37
 
data/README CHANGED
@@ -20,7 +20,7 @@ It will try and run the app using the following servers in this order:
20
20
  * WEBrick
21
21
 
22
22
  rake script:server takes the following options:
23
- $ rake script:server PORT=<port> Mack::Configuration.env=<environment> HANDLER=<rack_handler>
23
+ $ rake script:server PORT=<port> Mack.env=<environment> HANDLER=<rack_handler>
24
24
 
25
25
  The port and rack_handler flags don't apply if you're using Thin[http://code.macournoyer.com/thin] to run the app, which is the default if it is installed. Use the thin.yml file in your application's config directory to configure Thin. The rack_handler one will allow you to switch which server is used to run the app. See Rack for more Rack::Handlers.
26
26
 
data/bin/mack CHANGED
@@ -13,7 +13,8 @@ raise "You must specify a name for this application!" if app.nil?
13
13
 
14
14
  options = OpenStruct.new
15
15
  options.orm = "data_mapper"
16
- options.version = "0.5.5.4"
16
+ options.testing_framework = "rspec"
17
+ options.version = "0.6.0"
17
18
 
18
19
  opts = OptionParser.new do |opts|
19
20
  opts.banner = "Usage: mack <application_name> [options]"
@@ -22,8 +23,12 @@ opts = OptionParser.new do |opts|
22
23
  options.orm = v
23
24
  end
24
25
 
26
+ opts.on("-t [rspec|test_case]") do |v|
27
+ options.testing_framework = v
28
+ end
29
+
25
30
  end
26
31
 
27
32
  opts.parse!(ARGV)
28
33
 
29
- MackApplicationGenerator.run({"version" => options.version, "app" => app, "orm" => options.orm})
34
+ MackApplicationGenerator.run({"version" => options.version, "app" => app, "orm" => options.orm, "testing_framework" => options.testing_framework})
@@ -0,0 +1,371 @@
1
+ module Mack
2
+ module Controller # :nodoc:
3
+ # All controllers in a Mack application have to include this module. I'll be honest, if they don't extend this class
4
+ # then, well, things just won't work very well!
5
+ #
6
+ # Example:
7
+ # class MyAwesomeController
8
+ # include Mack::Controller
9
+ #
10
+ # def index
11
+ # render(:text, "Hello World!")
12
+ # end
13
+ # end
14
+
15
+ # See Mack::Request for more information.
16
+ attr_reader :request
17
+ # See Mack::Response for more information.
18
+ attr_reader :response
19
+ # The 'underscore' version of the controller requested. Example: 'my_awesome_controller'
20
+ attr_reader :controller_name
21
+ # The name of the action being requested.
22
+ attr_reader :action_name
23
+ # See Mack::CookieJar for more information.
24
+ attr_reader :cookies
25
+ # If an exception was thrown by a request this represents that error.
26
+ attr_accessor :caught_exception
27
+
28
+ def initialize(request, response, cookies)
29
+ @request = request
30
+ @response = response
31
+ @render_options = {}
32
+ @render_performed = false
33
+ @controller_name = params[:controller]
34
+ @action_name = params[:action]
35
+ @cookies = cookies
36
+ @wants_list = []
37
+ end
38
+
39
+ # Gives access to all the parameters for this request.
40
+ def params
41
+ self.request
42
+ end
43
+
44
+ # Gives access to the session. See Mack::Session for more information.
45
+ def session
46
+ self.request.session
47
+ end
48
+
49
+ # This does the heavy lifting for controllers. It calls the action, and then completes the rendering
50
+ # of the action to a String to send back to Rack.
51
+ def run
52
+ begin
53
+ run_filters(:before)
54
+ # check to see if this controller responds to this action.
55
+ # only run public methods!
56
+ if self.public_methods.include?(self.action_name)
57
+ # call the action and capture the results to a variable.
58
+ self.send(self.action_name)
59
+ else
60
+ # there is no action on this controller, so call the render method
61
+ # which will check the view directory and run action.html.erb if it exists.
62
+ render(:action, self.action_name)
63
+ end
64
+ run_filters(:after)
65
+ # do the work of rendering.
66
+ @final_rendered_action = do_render
67
+ run_filters(:after_render)
68
+ return @final_rendered_action
69
+ rescue Mack::Errors::FilterChainHalted => e
70
+ if render_performed?
71
+ run_filters(:after)
72
+ # do the work of rendering.
73
+ @final_rendered_action = do_render
74
+ run_filters(:after_render)
75
+ return @final_rendered_action
76
+ else
77
+ raise e
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ # This will redirect the request to the specified url. A default status of
84
+ # 302, Moved Temporarily, is set if no status is specified. A simple HTML
85
+ # page is rendered in case the redirect does not occur. A server side
86
+ # redirect is also possible by using the option :server_side => true.
87
+ # When a server side redirect occurs the url must be a 'local' url, not an
88
+ # external url. The 'original' url of the request will NOT change.
89
+ def redirect_to(url, options = {})
90
+ options = {:status => 302}.merge(options)
91
+ raise Rack::ForwardRequest.new(url) if options[:server_side]
92
+ response.status = options[:status]
93
+ response[:location] = url
94
+ render(:text, redirect_html(request.path_info, url, options[:status]))
95
+ end
96
+
97
+ # In an action wants will run blocks of code based on the content type that has
98
+ # been requested.
99
+ #
100
+ # Examples:
101
+ # class MyAwesomeController
102
+ # include Mack::Controller
103
+ #
104
+ # def hello
105
+ # wants(:html) do
106
+ # render(:text, "<html>Hello World</html>")
107
+ # end
108
+ # wants(:xml) do
109
+ # render(:text, "<xml><greeting>Hello World</greeting></xml>")
110
+ # end
111
+ # end
112
+ # end
113
+ #
114
+ # If you were to go to: /my_awesome/hello you would get:
115
+ # "<html>Hello World</html>"
116
+ #
117
+ # If you were to go to: /my_awesome/hello.html you would get:
118
+ # "<html>Hello World</html>"
119
+ #
120
+ # If you were to go to: /my_awesome/hello.xml you would get:
121
+ # "<xml><greeting>Hello World</greeting></xml>"
122
+ def wants(header_type, &block)
123
+ header_type = header_type.to_sym
124
+ if header_type == params[:format].to_sym
125
+ yield
126
+ end
127
+ end
128
+
129
+ # Returns true/false depending on whether the render action has been called yet.
130
+ def render_performed?
131
+ @render_performed
132
+ end
133
+
134
+ # Gives access to the Mack.logger.
135
+ def logger
136
+ Mack.logger
137
+ end
138
+
139
+ # This method can be called from within an action. This 'registers' the render that you
140
+ # would like to happen once the action is completed.
141
+ #
142
+ # It's important to note that calling render in an action does NOT end the processing of
143
+ # the action. The action will continue to process unless you explicity put 'return' before the
144
+ # render call.
145
+ #
146
+ # If you call render twice in an action then a Mack::Errors::DoubleRender error will be thrown.
147
+ #
148
+ # An implicit render will happen if one is not specified in the action.
149
+ #
150
+ # Only :action and :text will get layouts wrapped around them.
151
+ #
152
+ # You can also specify the response status code as part of the options hash.
153
+ #
154
+ # Examples:
155
+ # class MyAwesomeController
156
+ # include Mack::Controller
157
+ #
158
+ # # This will render the text 'Hello World!' to the screen.
159
+ # def index
160
+ # render(:text, "Hello World!")
161
+ # end
162
+ #
163
+ # # This will render Mack.root/views/my_awesome_controller/foo.html.erb
164
+ # def show
165
+ # render(:action, :foo)
166
+ # end
167
+ #
168
+ # # This will raise a Mack::Errors::DoubleRender error.
169
+ # def edit
170
+ # render(:text, "Hello World!")
171
+ # render(:action, :foo)
172
+ # end
173
+ #
174
+ # # This will render Mack.root/views/my_awesome_controller/delete.html.erb
175
+ # def delete
176
+ # end
177
+ #
178
+ # # This will render the text 'Hello World!' to the screen. Assuming that
179
+ # # there is no file: Mack.root/views/my_awesome_controller/update.html.erb
180
+ # # The reason for this is if the view for the action doesn't exist, and the
181
+ # # last thing returned from the action is a String, that string will be returned.
182
+ # def update
183
+ # "Hello World!"
184
+ # end
185
+ #
186
+ # # This will raise a Mack::Errors::InvalidRenderType error. Assuming that
187
+ # # there is no file: Mack.root/views/my_awesome_controller/create.html.erb
188
+ # def create
189
+ # @user = User.find(1)
190
+ # end
191
+ #
192
+ # # This will raise a Errno::ENOENT error. Assuming that
193
+ # # there is no file: Mack.root/views/my_awesome_controller/bar.html.erb
194
+ # def bar
195
+ # render(:action, "bar")
196
+ # end
197
+ #
198
+ # # This will render a file from the public directory. Files served from the
199
+ # # public directory do NOT get layouts. The default file extension for files
200
+ # # served from the public directory is .html. This can be overridden with the
201
+ # # :ext => ".<ext>" option.
202
+ # def show_public_file
203
+ # render(:public, "my/files/foo")
204
+ # end
205
+ #
206
+ # # This will render a file from the public directory. Files served from the
207
+ # # public directory do NOT get layouts. The default file extension for files
208
+ # # served from the public directory is .html. This can be overridden with the
209
+ # # :ext => ".<ext>" option.
210
+ # def show_public_xml_file
211
+ # render(:public, "my/files/foo", :ext => ".xml")
212
+ # end
213
+ #
214
+ # # This will render a partial. In this case it will look for:
215
+ # # Mack.root/views/my_awesome_controller/_latest_news.html.erb
216
+ # # Partials do NOT get wrapped in layouts.
217
+ # def latest_news
218
+ # render(:partial, :latest_news)
219
+ # end
220
+ #
221
+ # # This will render a partial. In this case it will look for:
222
+ # # Mack.root/views/some_other/_old_news.html.erb
223
+ # # Partials do NOT get wrapped in layouts.
224
+ # def latest_news
225
+ # render(:partial, "some_other/old_news")
226
+ # end
227
+ #
228
+ # # This will render a url. If the url does not return a status code of '200',
229
+ # # an empty string will be returned by default. The default method for rendering
230
+ # # urls is a get.
231
+ # def yahoo
232
+ # render(:url, "http://www.yahoo.com")
233
+ # end
234
+ #
235
+ # # This will render a url. If the url does not return a status code of '200',
236
+ # # a Mack::Errors::UnsuccessfulRenderUrl exception will be raised.
237
+ # def idontexist
238
+ # render(:url, "http://www.idontexist.com", :raise_exception => true)
239
+ # end
240
+ #
241
+ # # This will render a url with a post.
242
+ # def post_to_somewhere
243
+ # render(:url, "http://www.mackframework.com/post_to_me", :method => :post,
244
+ # :parameters => {:id => 1, :user => "markbates"})
245
+ # end
246
+ #
247
+ # # This will render a 'local' url. If a domain is not present render url will
248
+ # # reach out for the config parameter "mack::site_domain" and prepend that
249
+ # # to the url. This can be overridden locally with the :domain option.
250
+ # def get_index
251
+ # render(:url, "/")
252
+ # end
253
+ #
254
+ # # This will render 'application/404' and set the response status code to 404
255
+ # def to_the_unknown
256
+ # return render(:action, '/application/404', :status => 404)
257
+ # end
258
+ #
259
+ # end
260
+ def render(render_type = :action, render_value = self.action_name, options = {})
261
+ raise Mack::Errors::DoubleRender.new if render_performed?
262
+ response.status = options[:status] unless options[:status].nil?
263
+ options = {:content_type => Mack::Utils::MimeTypes[params[:format]], :layout => layout}.merge(options)
264
+ response["Content-Type"] = options[:content_type]
265
+ options.delete(:content_type)
266
+ @view_template = Mack::Rendering::ViewTemplate.new(render_type, render_value,
267
+ {:format => params[:format].to_sym, :controller => self}.merge(options))
268
+ @render_performed = true
269
+ end
270
+
271
+ private
272
+ def do_render
273
+ render unless @view_template
274
+ @rendered_action = @view_template.compile_and_render
275
+ end
276
+
277
+ def layout
278
+ :application
279
+ end
280
+
281
+ def run_filters(type)
282
+ filters = self.class.controller_filters[type]
283
+ return true if filters.empty?
284
+ filters.each do |filter|
285
+ if filter.run?(self.action_name.to_sym)
286
+ r = self.send(filter.filter_method)
287
+ raise Mack::Errors::FilterChainHalted.new(filter.filter_method) unless r
288
+ end
289
+ end
290
+ end
291
+
292
+ public
293
+ module ClassMethods
294
+ # See Mack::Controller::Filter for more information.
295
+ def before_filter(meth, options = {})
296
+ add_filter(:before, meth, options)
297
+ end
298
+
299
+ # See Mack::Controller::Filter for more information.
300
+ def after_filter(meth, options = {})
301
+ add_filter(:after, meth, options)
302
+ end
303
+
304
+ # See Mack::Controller::Filter for more information.
305
+ def after_render_filter(meth, options = {})
306
+ add_filter(:after_render, meth, options)
307
+ end
308
+
309
+ def add_filter(type, meth, options) # :nodoc:
310
+ controller_filters[type.to_sym] << Mack::Controller::Filter.new(meth, self, options)
311
+ end
312
+
313
+ def controller_filters # :nodoc:
314
+ unless @controller_filters
315
+ @controller_filters = {:before => [], :after => [], :after_render => []}
316
+ # inherit filters from the superclass, if any, to this parent
317
+ sc = self.superclass
318
+ if sc.class_is_a?(Mack::Controller)
319
+ ch = sc.controller_filters
320
+ [:before, :after, :after_render].each do |v|
321
+ @controller_filters[v] << ch[v]
322
+ @controller_filters[v].flatten!
323
+ @controller_filters[v].uniq!
324
+ end
325
+ end
326
+ end
327
+ @controller_filters
328
+ end
329
+
330
+ # Sets a layout to be used by a particular controller.
331
+ #
332
+ # Example:
333
+ # class MyAwesomeController
334
+ # include Mack::Controller
335
+ #
336
+ # # Sets all actions to use: "#{Mack.root}/app/views/layouts/dark.html.erb" as they're layout.
337
+ # layout :dark
338
+ #
339
+ # def index
340
+ # # Sets this action to use: "#{Mack.root}/app/views/layouts/bright.html.erb" as it's layout.
341
+ # render(:text, "Welcome...", :layout => :bright)
342
+ # end
343
+ #
344
+ # def index
345
+ # # This will no use a layout.
346
+ # render(:text, "Welcome...", :layout => false)
347
+ # end
348
+ # end
349
+ #
350
+ # The default layout is "#{Mack.root}/app/views/layouts/application.html.erb".
351
+ #
352
+ # If a layout is specified, and it doesn't exist a Mack::Errors::UnknownLayout error will be raised.
353
+ def layout(lay)
354
+ self.class_eval do
355
+ define_method(:layout) do
356
+ lay
357
+ end
358
+ end
359
+ end # layout
360
+
361
+ end # module ClassMethods
362
+
363
+ #
364
+ # Make sure that all the class level methods got included into the receiver's class
365
+ #
366
+ def self.included(base)
367
+ base.extend(ClassMethods)
368
+ end
369
+
370
+ end # Controller
371
+ end # Mack
@@ -1,7 +1,8 @@
1
1
  module Mack
2
2
 
3
3
  # Examples:
4
- # class MyAwesomeController < Mack::Controller::Base
4
+ # class MyAwesomeController
5
+ # include Mack::Controller
5
6
  # def index
6
7
  # cookies[:id] = 1
7
8
  # render(:text, "Hello!")