mack 0.5.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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!")