merb 0.3.7 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. data/README +25 -26
  2. data/Rakefile +48 -36
  3. data/app_generators/merb/USAGE +5 -0
  4. data/app_generators/merb/merb_generator.rb +107 -0
  5. data/app_generators/merb/templates/Rakefile +99 -0
  6. data/{examples/skeleton/dist → app_generators/merb/templates}/app/controllers/application.rb +1 -1
  7. data/app_generators/merb/templates/app/controllers/exceptions.rb +13 -0
  8. data/{examples/skeleton/dist → app_generators/merb/templates}/app/helpers/global_helper.rb +0 -0
  9. data/{examples/skeleton/dist/app/mailers → app_generators/merb/templates/app/mailers/views}/layout/application.erb +0 -0
  10. data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +207 -0
  11. data/app_generators/merb/templates/app/views/exceptions/not_acceptable.html.erb +38 -0
  12. data/app_generators/merb/templates/app/views/exceptions/not_found.html.erb +40 -0
  13. data/app_generators/merb/templates/app/views/layout/application.html.erb +11 -0
  14. data/app_generators/merb/templates/config/boot.rb +11 -0
  15. data/app_generators/merb/templates/config/dependencies.rb +41 -0
  16. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/development.rb +0 -0
  17. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/production.rb +0 -0
  18. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/test.rb +0 -0
  19. data/app_generators/merb/templates/config/merb.yml +64 -0
  20. data/app_generators/merb/templates/config/merb_init.rb +16 -0
  21. data/app_generators/merb/templates/config/plugins.yml +1 -0
  22. data/app_generators/merb/templates/config/router.rb +32 -0
  23. data/{lib/merb/core_ext/merb_array.rb → app_generators/merb/templates/config/upload.conf} +0 -0
  24. data/app_generators/merb/templates/public/images/merb.jpg +0 -0
  25. data/app_generators/merb/templates/public/merb.fcgi +6 -0
  26. data/app_generators/merb/templates/public/stylesheets/master.css +119 -0
  27. data/app_generators/merb/templates/script/destroy +28 -0
  28. data/app_generators/merb/templates/script/generate +28 -0
  29. data/{examples/skeleton → app_generators/merb/templates}/script/stop_merb +0 -0
  30. data/app_generators/merb/templates/script/win_script.cmd +1 -0
  31. data/app_generators/merb/templates/spec/spec.opts +6 -0
  32. data/app_generators/merb/templates/spec/spec_helper.rb +10 -0
  33. data/app_generators/merb/templates/test/test_helper.rb +13 -0
  34. data/app_generators/merb_plugin/USAGE +5 -0
  35. data/app_generators/merb_plugin/merb_plugin_generator.rb +64 -0
  36. data/app_generators/merb_plugin/templates/LICENSE +20 -0
  37. data/app_generators/merb_plugin/templates/README +4 -0
  38. data/app_generators/merb_plugin/templates/Rakefile +35 -0
  39. data/app_generators/merb_plugin/templates/TODO +5 -0
  40. data/app_generators/merb_plugin/templates/merbtasks.rb +6 -0
  41. data/app_generators/merb_plugin/templates/sampleplugin.rb +10 -0
  42. data/app_generators/merb_plugin/templates/sampleplugin_spec.rb +7 -0
  43. data/app_generators/merb_plugin/templates/spec_helper.rb +2 -0
  44. data/bin/merb +1 -1
  45. data/lib/autotest/discover.rb +3 -0
  46. data/lib/autotest/merb_rspec.rb +79 -0
  47. data/lib/merb.rb +72 -93
  48. data/lib/merb/{merb_abstract_controller.rb → abstract_controller.rb} +28 -5
  49. data/lib/merb/caching/action_cache.rb +65 -29
  50. data/lib/merb/caching/fragment_cache.rb +9 -4
  51. data/lib/merb/caching/store/file_cache.rb +22 -14
  52. data/lib/merb/caching/store/memory_cache.rb +26 -8
  53. data/lib/merb/{merb_constants.rb → constants.rb} +9 -7
  54. data/lib/merb/controller.rb +178 -0
  55. data/lib/merb/core_ext.rb +13 -11
  56. data/lib/merb/core_ext/array.rb +0 -0
  57. data/lib/merb/core_ext/{merb_class.rb → class.rb} +0 -0
  58. data/lib/merb/core_ext/{merb_enumerable.rb → enumerable.rb} +0 -0
  59. data/lib/merb/core_ext/get_args.rb +52 -0
  60. data/lib/merb/core_ext/{merb_hash.rb → hash.rb} +40 -11
  61. data/lib/merb/core_ext/{merb_inflections.rb → inflections.rb} +0 -0
  62. data/lib/merb/core_ext/{merb_inflector.rb → inflector.rb} +1 -1
  63. data/lib/merb/core_ext/{merb_kernel.rb → kernel.rb} +56 -3
  64. data/lib/merb/core_ext/mash.rb +88 -0
  65. data/lib/merb/core_ext/{merb_module.rb → module.rb} +0 -0
  66. data/lib/merb/core_ext/{merb_numeric.rb → numeric.rb} +0 -0
  67. data/lib/merb/core_ext/{merb_object.rb → object.rb} +10 -47
  68. data/lib/merb/core_ext/string.rb +56 -0
  69. data/lib/merb/core_ext/{merb_symbol.rb → symbol.rb} +0 -0
  70. data/lib/merb/dispatcher.rb +109 -0
  71. data/lib/merb/{merb_drb_server.rb → drb_server.rb} +0 -0
  72. data/lib/merb/erubis_ext.rb +10 -0
  73. data/lib/merb/exceptions.rb +173 -0
  74. data/lib/merb/generators/merb_app/merb_app.rb +5 -25
  75. data/lib/merb/generators/merb_generator_helpers.rb +317 -0
  76. data/lib/merb/generators/merb_plugin.rb +19 -0
  77. data/lib/merb/logger.rb +65 -0
  78. data/lib/merb/{merb_mail_controller.rb → mail_controller.rb} +102 -49
  79. data/lib/merb/{merb_mailer.rb → mailer.rb} +31 -27
  80. data/lib/merb/mixins/{basic_authentication_mixin.rb → basic_authentication.rb} +3 -3
  81. data/lib/merb/mixins/{controller_mixin.rb → controller.rb} +131 -112
  82. data/lib/merb/mixins/{erubis_capture_mixin.rb → erubis_capture.rb} +12 -21
  83. data/lib/merb/mixins/{form_control_mixin.rb → form_control.rb} +6 -12
  84. data/lib/merb/mixins/render.rb +401 -0
  85. data/lib/merb/mixins/responder.rb +378 -0
  86. data/lib/merb/mixins/{view_context_mixin.rb → view_context.rb} +65 -10
  87. data/lib/merb/mixins/web_controller.rb +29 -0
  88. data/lib/merb/{merb_handler.rb → mongrel_handler.rb} +59 -38
  89. data/lib/merb/part_controller.rb +19 -0
  90. data/lib/merb/plugins.rb +16 -0
  91. data/lib/merb/rack_adapter.rb +37 -0
  92. data/lib/merb/request.rb +421 -0
  93. data/lib/merb/router.rb +576 -0
  94. data/lib/merb/{merb_server.rb → server.rb} +275 -71
  95. data/lib/merb/session.rb +10 -10
  96. data/lib/merb/session/cookie_store.rb +125 -0
  97. data/lib/merb/session/{merb_mem_cache_session.rb → mem_cache_session.rb} +22 -9
  98. data/lib/merb/session/{merb_memory_session.rb → memory_session.rb} +15 -11
  99. data/lib/merb/template.rb +35 -8
  100. data/lib/merb/template/erubis.rb +16 -10
  101. data/lib/merb/template/haml.rb +33 -20
  102. data/lib/merb/template/markaby.rb +16 -14
  103. data/lib/merb/template/xml_builder.rb +8 -4
  104. data/lib/merb/test/{merb_fake_request.rb → fake_request.rb} +11 -5
  105. data/lib/merb/test/helper.rb +31 -0
  106. data/lib/merb/test/hpricot.rb +136 -0
  107. data/lib/merb/test/{merb_multipart.rb → multipart.rb} +1 -1
  108. data/lib/merb/test/rspec.rb +93 -0
  109. data/lib/merb/{merb_upload_handler.rb → upload_handler.rb} +5 -6
  110. data/lib/merb/{merb_upload_progress.rb → upload_progress.rb} +1 -1
  111. data/lib/merb/{merb_view_context.rb → view_context.rb} +27 -42
  112. data/lib/{merb_tasks.rb → tasks.rb} +0 -0
  113. data/lib/tasks/merb.rake +21 -11
  114. data/merb_default_generators/model/USAGE +0 -0
  115. data/merb_default_generators/model/model_generator.rb +16 -0
  116. data/merb_default_generators/model/templates/new_model_template.erb +5 -0
  117. data/merb_default_generators/resource_controller/USAGE +0 -0
  118. data/merb_default_generators/resource_controller/resource_controller_generator.rb +26 -0
  119. data/merb_default_generators/resource_controller/templates/controller.rb +30 -0
  120. data/merb_default_generators/resource_controller/templates/edit.html.erb +1 -0
  121. data/merb_default_generators/resource_controller/templates/helper.rb +5 -0
  122. data/merb_default_generators/resource_controller/templates/index.html.erb +1 -0
  123. data/merb_default_generators/resource_controller/templates/new.html.erb +1 -0
  124. data/merb_default_generators/resource_controller/templates/show.html.erb +1 -0
  125. data/merb_generators/controller/USAGE +5 -0
  126. data/merb_generators/controller/controller_generator.rb +16 -0
  127. data/merb_generators/controller/templates/controller.rb +8 -0
  128. data/merb_generators/controller/templates/helper.rb +5 -0
  129. data/merb_generators/controller/templates/index.html.erb +3 -0
  130. data/merb_generators/resource/USAGE +0 -0
  131. data/merb_generators/resource/resource_generator.rb +60 -0
  132. data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +67 -0
  133. data/rspec_generators/merb_controller_test/templates/controller_spec.rb +8 -0
  134. data/rspec_generators/merb_controller_test/templates/edit_spec.rb +12 -0
  135. data/rspec_generators/merb_controller_test/templates/helper_spec.rb +5 -0
  136. data/rspec_generators/merb_controller_test/templates/index_spec.rb +12 -0
  137. data/rspec_generators/merb_controller_test/templates/new_spec.rb +12 -0
  138. data/rspec_generators/merb_controller_test/templates/show_spec.rb +5 -0
  139. data/rspec_generators/merb_model_test/merb_model_test_generator.rb +26 -0
  140. data/rspec_generators/merb_model_test/templates/model_spec_template.erb +7 -0
  141. data/script/destroy +14 -0
  142. data/script/generate +14 -0
  143. data/test_unit_generators/merb_controller_test/merb_controller_test_generator.rb +53 -0
  144. data/test_unit_generators/merb_controller_test/templates/functional_test.rb +17 -0
  145. data/test_unit_generators/merb_controller_test/templates/helper_test.rb +9 -0
  146. data/test_unit_generators/merb_model_test/merb_model_test_generator.rb +29 -0
  147. data/test_unit_generators/merb_model_test/templates/model_test_unit_template.erb +9 -0
  148. metadata +172 -94
  149. data/examples/README_EXAMPLES +0 -10
  150. data/examples/skeleton/Rakefile +0 -68
  151. data/examples/skeleton/dist/app/views/layout/application.herb +0 -12
  152. data/examples/skeleton/dist/conf/database.yml +0 -23
  153. data/examples/skeleton/dist/conf/merb.yml +0 -57
  154. data/examples/skeleton/dist/conf/merb_init.rb +0 -24
  155. data/examples/skeleton/dist/conf/router.rb +0 -22
  156. data/examples/skeleton/dist/conf/upload.conf +0 -5
  157. data/examples/skeleton/dist/schema/migrations/001_add_sessions_table.rb +0 -14
  158. data/examples/skeleton/script/new_migration +0 -21
  159. data/lib/merb/core_ext/merb_string.rb +0 -18
  160. data/lib/merb/merb_controller.rb +0 -206
  161. data/lib/merb/merb_dispatcher.rb +0 -87
  162. data/lib/merb/merb_exceptions.rb +0 -319
  163. data/lib/merb/merb_part_controller.rb +0 -42
  164. data/lib/merb/merb_plugins.rb +0 -293
  165. data/lib/merb/merb_request.rb +0 -165
  166. data/lib/merb/merb_router.rb +0 -309
  167. data/lib/merb/merb_yaml_store.rb +0 -31
  168. data/lib/merb/mixins/render_mixin.rb +0 -283
  169. data/lib/merb/mixins/responder_mixin.rb +0 -159
  170. data/lib/merb/session/merb_ar_session.rb +0 -131
  171. data/lib/merb/vendor/paginator/README.txt +0 -84
  172. data/lib/merb/vendor/paginator/paginator.rb +0 -124
  173. data/lib/tasks/db.rake +0 -55
@@ -1,87 +0,0 @@
1
- module Merb
2
-
3
- class Dispatcher
4
- class << self
5
-
6
- attr_accessor :path_prefix
7
-
8
- def use_mutex=(val)
9
- @@use_mutex = val
10
- end
11
-
12
- @@mutex = Mutex.new
13
- @@use_mutex = ::Merb::Server.use_mutex
14
- # This is where we grab the incoming request REQUEST_URI and use that in
15
- # the merb RouteMatcher to determine which controller and method to run.
16
- # Returns a 2 element tuple of: [controller, action]
17
- def handle(request, response)
18
- start = Time.now
19
-
20
- request_uri = request.params[Merb::Const::REQUEST_URI]
21
- request_uri.sub!(path_prefix, '') if path_prefix
22
- route = route_path(request_uri)
23
-
24
- allowed = route.delete(:allowed)
25
- rest = route.delete(:rest)
26
- namespace = route.delete(:namespace)
27
-
28
- cont = namespace ? "#{namespace}/#{route[:controller]}" : route[:controller]
29
-
30
- klass = resolve_controller(cont)
31
- controller = klass.build(request.body, request.params, route, response)
32
-
33
- if rest
34
- method = controller.request.method
35
- if allowed.keys.include?(method) && action = allowed[method]
36
- controller.params[:action] = action
37
- else
38
- raise Merb::HTTPMethodNotAllowed.new(method, allowed)
39
- end
40
- else
41
- action = route[:action]
42
- end
43
- controller._benchmarks[:setup_time] = Time.now - start
44
- if @@use_mutex
45
- @@mutex.synchronize {
46
- controller.dispatch(action)
47
- }
48
- else
49
- controller.dispatch(action)
50
- end
51
- [controller, action]
52
- end
53
-
54
- def route_path(path)
55
- path = path.sub(/\/+/, '/').sub(/\?.*$/, '')
56
- path = path[0..-2] if (path[-1] == ?/) && path.size > 1
57
- Merb::Router.match(path)
58
- end
59
-
60
- # Take a controller class name string and reload or require the right
61
- # controller file then CamelCase it and return the class object.
62
- def resolve_controller(controller_name)
63
- segments = controller_name.split('/').map{|s| s.snake_case}
64
- path = "#{DIST_ROOT}/app/controllers/#{controller_name}.rb"
65
- cnt = segments.map{|s| s.camel_case }.join('::')
66
-
67
- if !File.exist?(path)
68
- raise "Bad controller! #{cnt}"
69
- end unless $TESTING
70
-
71
- begin
72
- if MERB_ENV == 'development'
73
- Object.send(:remove_const, cnt) rescue nil
74
- load(path)
75
- end
76
- return Object.full_const_get(cnt)
77
- rescue RuntimeError
78
- warn "Error getting instance of '#{controller_name.camel_case}': #{$!}"
79
- raise $!
80
- end
81
- end
82
-
83
- end # end class << self
84
-
85
- end
86
-
87
- end
@@ -1,319 +0,0 @@
1
- begin
2
- require 'coderay'
3
- rescue LoadError => ex
4
- end
5
-
6
- module Merb
7
-
8
- module ControllerExceptions
9
- # ControllerExceptions are a way of simplifying controller code by placing
10
- # exceptional logic elsewhere. ControllerExceptions are like
11
- # mini-controllers which have one action. The exception action is called
12
- # to render a web page when the exception is raised. Additionally all
13
- # ControllerExceptions have an HTTP status code associated with them
14
- # which is given to the browser when it's action is rendered.
15
- #
16
- # ControllerExceptions::Base is an abstract base class, it cannot be
17
- # raised. Derived from Base are many exceptions, one for each HTTP status
18
- # code. EG Unauthorized (401), PaymentRequired (402), and Forbidden (403).
19
- #
20
- # These exceptions can be raised by your controller without any further
21
- # work. For example
22
- #
23
- # def show
24
- # product = Product.find(params[:id])
25
- # raise NotFound if product.nil?
26
- # [...]
27
- # end
28
- #
29
- # By default the NotFound exception will look in for a template at
30
- # app/views/exceptions/not_found.{rhtml, haml, whatevs}
31
- # If the template is not found then a simple message will be sent.
32
- #
33
- # To extend the use of the ControllerExceptions one may derive a new
34
- # exception from one of the already defined ones. Then one must add a
35
- # special method called error_response which is like a controller action
36
- # preparing the context for rendering a template at
37
- # app/views/exceptions/my_exception_snake_cased.whatevs
38
- #
39
- # As an example we will create an exception called AdminAccessRequired.
40
- # First we decide on what HTTP status code such an error might have.
41
- # 401, Unauthorized seems to fit.
42
- #
43
- # class AdminAccessRequired < Merb::ControllerExceptions::Unauthorized
44
- # def error_response
45
- # @tried_to_access request.uri
46
- # render :layout => 'error_page'
47
- # end
48
- # end
49
- #
50
- # At app/views/exceptions/admin_access_required.rhtml we write
51
- #
52
- # <h1>You're not an administrator!</h1>
53
- # <p>You tried to access <%= @tried_to_access %> but that URL is
54
- # restricted to administrators.</p>
55
- #
56
- # The layout 'error_page' works like any other controller, it would be
57
- # looked for at app/views/layouts
58
- #
59
- # TODO: if you need to pass data to your exception use a constructor.
60
- class Base < StandardError
61
- include Merb::RenderMixin
62
- include Merb::ControllerMixin
63
- include Merb::ResponderMixin
64
-
65
- def _template_root
66
- @controller._template_root
67
- end
68
-
69
- # The filename of the exception template. usually something like
70
- # views/exceptions/not_found.rhtml
71
- def template_path
72
- _template_root / 'exceptions' / self.class.name.snake_case.split('::').last
73
- end
74
-
75
- def set_controller(controller)
76
- @controller = controller
77
- end
78
-
79
- def request; @controller.request; end
80
- def params; @controller.params; end
81
- def cookies; @controller.cookies; end
82
- def headers; @controller.headers; end
83
- def session; @controller.session; end
84
- def response; @controller.response; end
85
-
86
- def status
87
- self.class.const_get(:STATUS)
88
- end
89
-
90
- def call_action
91
- # TODO: this method is meaningless at the moment but it could call
92
- # filters
93
- # before filters?
94
- error_response
95
- # after filters?
96
- end
97
-
98
- def error_response
99
- if File.exists?(template_path)
100
- render
101
- else
102
- "Error #{status} #{self.class.name.split('::').last}!"
103
- end
104
- end
105
- end
106
- module HTTPErrors
107
- # created with:
108
- # ruby -r rubygems -e "require 'mongrel'; puts Mongrel::HTTP_STATUS_CODES.keys.sort.map {|code| %Q{class #{Mongrel::HTTP_STATUS_CODES[code].gsub /[^\w]/,''} < Merb::ControllerExceptions::Base; STATUS = #{code}; end} }.join(%Q{\n})"
109
- # we could do some magic here, but i think it's more instructive to just
110
- # have these values copied
111
- class Continue < Merb::ControllerExceptions::Base; STATUS = 100; end
112
- class SwitchingProtocols < Merb::ControllerExceptions::Base; STATUS = 101; end
113
- class OK < Merb::ControllerExceptions::Base; STATUS = 200; end
114
- class Created < Merb::ControllerExceptions::Base; STATUS = 201; end
115
- class Accepted < Merb::ControllerExceptions::Base; STATUS = 202; end
116
- class NonAuthoritativeInformation < Merb::ControllerExceptions::Base; STATUS = 203; end
117
- class NoContent < Merb::ControllerExceptions::Base; STATUS = 204; end
118
- class ResetContent < Merb::ControllerExceptions::Base; STATUS = 205; end
119
- class PartialContent < Merb::ControllerExceptions::Base; STATUS = 206; end
120
- class MultipleChoices < Merb::ControllerExceptions::Base; STATUS = 300; end
121
- class MovedPermanently < Merb::ControllerExceptions::Base; STATUS = 301; end
122
- class MovedTemporarily < Merb::ControllerExceptions::Base; STATUS = 302; end
123
- class SeeOther < Merb::ControllerExceptions::Base; STATUS = 303; end
124
- class NotModified < Merb::ControllerExceptions::Base; STATUS = 304; end
125
- class UseProxy < Merb::ControllerExceptions::Base; STATUS = 305; end
126
- class BadRequest < Merb::ControllerExceptions::Base; STATUS = 400; end
127
- class Unauthorized < Merb::ControllerExceptions::Base; STATUS = 401; end
128
- class PaymentRequired < Merb::ControllerExceptions::Base; STATUS = 402; end
129
- class Forbidden < Merb::ControllerExceptions::Base; STATUS = 403; end
130
- class NotFound < Merb::ControllerExceptions::Base; STATUS = 404; end
131
- class MethodNotAllowed < Merb::ControllerExceptions::Base; STATUS = 405; end
132
- class NotAcceptable < Merb::ControllerExceptions::Base; STATUS = 406; end
133
- class ProxyAuthenticationRequired < Merb::ControllerExceptions::Base; STATUS = 407; end
134
- class RequestTimeout < Merb::ControllerExceptions::Base; STATUS = 408; end
135
- class Conflict < Merb::ControllerExceptions::Base; STATUS = 409; end
136
- class Gone < Merb::ControllerExceptions::Base; STATUS = 410; end
137
- class LengthRequired < Merb::ControllerExceptions::Base; STATUS = 411; end
138
- class PreconditionFailed < Merb::ControllerExceptions::Base; STATUS = 412; end
139
- class RequestEntityTooLarge < Merb::ControllerExceptions::Base; STATUS = 413; end
140
- class RequestURITooLarge < Merb::ControllerExceptions::Base; STATUS = 414; end
141
- class UnsupportedMediaType < Merb::ControllerExceptions::Base; STATUS = 415; end
142
- class InternalServerError < Merb::ControllerExceptions::Base; STATUS = 500; end
143
- class NotImplemented < Merb::ControllerExceptions::Base; STATUS = 501; end
144
- class BadGateway < Merb::ControllerExceptions::Base; STATUS = 502; end
145
- class ServiceUnavailable < Merb::ControllerExceptions::Base; STATUS = 503; end
146
- class GatewayTimeout < Merb::ControllerExceptions::Base; STATUS = 504; end
147
- class HTTPVersionNotSupported < Merb::ControllerExceptions::Base; STATUS = 505; end
148
- end
149
-
150
- include HTTPErrors
151
- end
152
-
153
- class MerbError < StandardError; end
154
- class Noroutefound < MerbError; end
155
- class MissingControllerFile < MerbError; end
156
- class MerbControllerError < MerbError; end
157
- class HTTPMethodNotAllowed < MerbError
158
- def initialize(method, allowed)
159
- super("HTTPMethodNotAllowed: #{method}\n"+ "Allowed: #{allowed.keys.join(' ')})")
160
- end
161
-
162
- end
163
-
164
- # Format exception message for browser display.
165
- def self.html_exception(e)
166
- if ::Merb::Server.show_error
167
- ErrorResponse.new(e).out
168
- else
169
- IO.read(DIST_ROOT / 'public/500.html') rescue "500 Internal Server Error!"
170
- end
171
- end
172
-
173
- def self.exception(e)
174
- "#{ e.message } - (#{ e.class })\n" <<
175
- "#{(e.backtrace or []).join("\n")}"
176
- end
177
-
178
- class ErrorResponse
179
- def initialize error
180
- @error = error
181
- end
182
-
183
- def out
184
- error = @error
185
- backtrace = @error.backtrace
186
-
187
- colors = []
188
- min = 200
189
- max = 255
190
- step = -((max - min) / backtrace.size).abs
191
- max.step(min, step) do |color|
192
- colors << color
193
- end
194
-
195
- backtrace.map! do |line|
196
- file, lineno, meth = line.scan(/(.*?):(\d+)(?::in `(.*?)')?/).first
197
-
198
- # When a backtrace entry doesn't have a filepath as the first field
199
- # (e.g., "(haml):12" or "(eval):41:in `_haml_render'"), it'll cause
200
- # a second exception to be raised, masking the first. This traps it.
201
- lines = (__caller_lines__(file, lineno, 5) rescue [])
202
-
203
- [ lines, lines.object_id.abs, file, lineno, meth ]
204
- end
205
-
206
- error_page(colors, error, *backtrace)
207
- end
208
-
209
- # This method offers highlighting for the sourcecode-chunks from the
210
- # traceback. Just 'gem install coderay'.
211
- def error_page(colors, title, *backtrace)
212
- @backtrace = backtrace
213
- @colors = colors
214
- @title = title
215
- @coderay = Object.constants.include?('CodeRay')
216
-
217
-
218
- template =
219
- <<-HEREDOC
220
- <html>
221
- <head>
222
- <title><%= @title %></title>
223
- <style type="text/css">
224
- <!--
225
- table {border:0px}
226
- tr {line-height:1.3}
227
- td {font-size:.8em; padding:4px}
228
- h1 {font-size:2em}
229
- h1, td {font-family:'courier new', 'courier', monospace}
230
- td.line {color:#000; text-align:center}
231
- td.method {font-weight:bold; text-align:right}
232
- td.file a {color:#000}
233
- td.file a:hover {color:#F00}
234
- tr.clickable:hover {background:#FFA}
235
- .clickable {cursor: help }
236
- #title {float: left;}
237
- .source
238
- {
239
- border:1px #000 solid;
240
- margin:2px;
241
- padding:8px;
242
- background:#F0F0F0;
243
- }
244
-
245
- -->
246
- <% if @coderay %>
247
- <%= CodeRay::Encoders[:html]::CSS.new.stylesheet %>
248
- <% end %>
249
- </style>
250
- <script type="text/javascript">
251
- $ = function(el){
252
- if(el === null || el === undefined)
253
- throw("Argument for $() must be a domRef/domId");
254
- if( el.constructor === String )
255
- el = document.getElementById(el);
256
- if(el === null || !el.nodeType)
257
- throw("Argument for $() not found in document tree.");
258
- return el;
259
- }
260
-
261
- var toggle = function(el){
262
- el = $(el);
263
- var visible = el.style.display != 'none'; // visible? boolean
264
- if(visible){
265
- el.style.display = 'none'; // hide
266
- }else{
267
- el.style.display = ''; // unhide
268
- }
269
- }
270
- </script>
271
- </head>
272
- <body>
273
- <div>
274
- <h1><img src="data:image/jpg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAJQAA/+4ADkFk\nb2JlAGTAAAAAAf/bAIQADQkJCQoJDQoKDRMMCwwTFhENDREWGhUVFhUVGhkU\nFhUVFhQZGR0fIB8dGScnKionJzk4ODg5QEBAQEBAQEBAQAEODAwOEA4RDw8R\nFA4RDhQVERISERUgFRUXFRUgKB0ZGRkZHSgjJiAgICYjLCwoKCwsNzc1NzdA\nQEBAQEBAQEBA/8AAEQgAJgAtAwEiAAIRAQMRAf/EAT8AAAEFAQEBAQEBAAAA\nAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoL\nEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVS\nwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePz\nRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5/cRAAIC\nAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLh\ncoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSF\ntJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x//aAAwDAQACEQMR\nAD8A9OVDK6xRQYa02axuEBvnB7x8Fm/W36x19HqoxmAvyswkMraHFwY2N7va\nCe/5Vy/Seu29RvdXaI2CW6EBw4OhGnZAk9Einrbuvn03Oaw1lvmCCP8ANXPW\n9Zz7shlrM9zKBLnN3Fmg1gnj8An61m14eCbAN9j4ZVWJJc5x2gQPivO3ZnUM\nXLtfY8by73sDmuHw9pPCZRPVNgdH13F+teJU51WbZpX9O4xpPEho4juug9Wr\n0vW3t9Lbv9SRt2xO7dxEL5+blW5I2W2FrdsSJJgdj4r0P1W/+Nf6Un1p9PZJ\nnf8AaPU2+P0fwThdVaLF3TlfXZvUsr63ZIpZY4Y9VDKTWwuIY5vqEe3uXFx+\nSn0XBupy9t+loqDXy1zTJLST7tefJbVDLsjLycwO9Sy/09ANQafUJP8A4IrG\nQGufXltEAjZYPA900kkeCRoXA+sHSeoTXn41xJxnB9bY3e4HRcTbVsfB2h7j\ntDWkkAT7jrPjC9FzCMfpJZU5wDGgN7wNI4HZcJdiNrvP2t+62SNg9vedxnRO\nj2WyQfZy2oOA5kbfGedF0jb8w/Uq2ra/25NcGD9F1dk6/BqrYNODY5rrve4+\n2rGpBcR3Mr0j9iVf83vscD1J3bZMep/NelM+Hsn5oqa3RG0uuf6b9j9dsCRI\n+lx4haGT9g1FgZ6nc0n/AKrSEkko/Kg7vO9XtsxzV+y6a8xjtxu+hWWwPY0f\npBMnv2XN52ZmbyLunYocCZNl1bpdENmS0wOdUkkPsT9rL6rfbf8AnJiPzvT+\nzfpPVrZ6ezb6Ttv0e26OTzC9U3uk+z88ACRu+hz8YSSR6q6P/9k=\n"/>
275
- <%= @title %></h1>
276
- </div>
277
-
278
- <table class="main">
279
- <thead>
280
- <tr>
281
- <td class="method">Method</td>
282
- <td class="line">Line</td>
283
- <td class="file">File</td>
284
- </tr>
285
- </thead>
286
- <% @backtrace.each do |lines, hash, file, lineno, meth| %>
287
- <tr id="line_<%= hash %>" onclick="toggle('source_<%= hash %>'); return false"; class="clickable" style="background:rgb(250,250,<%= @colors.shift %>);">
288
- <td class="method"><%= meth %></td>
289
- <td class="line"><%= lineno %></td>
290
- <td class="file"><%= file %></td>
291
- </tr>
292
- <tr id="source_<%= hash %>" <%= @coderay? " class='CodeRay' " : ''%> style="display:none;">
293
- <td colspan="3">
294
- <div class="source">
295
- <table>
296
- <tr><td colspan='2'><a href='txmt://open?url=file://<%=file%>&line=<%=lineno%>'>Open in TextMate</a></td></tr>
297
- <% lines.each do |llineno, lcode, lcurrent| %>
298
- <tr class="source"<%= 'style="background:#faa;"' if lcurrent %>>
299
- <td><%= llineno %></td>
300
- <td>
301
- <%= @coderay ? CodeRay.scan(lcode, :ruby).html : "<pre>\#{lcode}</pre>" %>
302
- </td>
303
- </tr>
304
- <% end %>
305
- </table>
306
- </div>
307
- </td>
308
- </tr>
309
- <% end %>
310
- </table>
311
- </body>
312
- </html>
313
- HEREDOC
314
- tmpl = Erubis::MEruby.new template
315
- tmpl.result(binding)
316
- end
317
- end
318
-
319
- end
@@ -1,42 +0,0 @@
1
- module Merb
2
- class PartController < AbstractController
3
- self._template_root = File.expand_path(DIST_ROOT / "app/parts/views")
4
-
5
- def initialize(web_controller)
6
- @_benchmarks = {}
7
- @web_controller = web_controller
8
- end
9
-
10
- def dispatch(action=:to_s)
11
- old_action = params[:action]
12
- params[:action] = action
13
- super(action)
14
- params[:action] = old_action
15
- @_body
16
- end
17
-
18
- def request
19
- @web_controller.request
20
- end
21
-
22
- def params
23
- @web_controller.params
24
- end
25
-
26
- def cookies
27
- @web_controller.cookies
28
- end
29
-
30
- def headers
31
- @web_controller.headers
32
- end
33
-
34
- def session
35
- @web_controller.session
36
- end
37
-
38
- def response
39
- @web_controller.response
40
- end
41
- end
42
- end
@@ -1,293 +0,0 @@
1
- # TODO: Find Merb app root so we aren't wantonly copying Rakefiles
2
- # TODO: Figure out a good way to handle the lack of install/uninstall script
3
- # TODO: Minimum versions for local gems in install
4
-
5
- require 'yaml'
6
- require 'rubygems'
7
-
8
- module Merb
9
- class PluginManager
10
-
11
- def self.gem_name
12
- @@gem_name
13
- end
14
-
15
- def self.gem_spec
16
- @@gem_spec
17
- end
18
-
19
- def self.options
20
- @@options
21
- end
22
-
23
- def self.gem_name=(val)
24
- @@gem_name = val
25
- end
26
-
27
- def self.gem_spec=(val)
28
- @@gem_spec = val
29
- end
30
-
31
- def self.options=(val)
32
- @@options = val
33
- end
34
-
35
-
36
- # Run a particular plugin action
37
- def self.action(action, gem_name = nil, opts = [])
38
- @@gem_name = gem_name
39
- @@options = opts.flatten
40
-
41
- case action
42
- when 'install':
43
- install
44
- when 'uninstall':
45
- uninstall
46
- when 'remove':
47
- remove_from_manifest
48
- when 'list':
49
- list
50
- when 'help'
51
- help
52
- when 'migrate'
53
- migrate
54
- when 'update'
55
- raise "This hasn't been implemented yet!"
56
- when 'upgrade'
57
- raise "This hasn't been implemented yet!"
58
- else
59
- raise "Invalid action: #{action}"
60
- end
61
- end
62
-
63
- # Install a new plugin named +gem_name+.
64
- def self.install
65
- raise "Plugin already installed!" if plugin_installed?
66
-
67
- self.gem_spec = find_locally or install_gem
68
-
69
- run_install_script
70
- copy_rakefile
71
- add_to_manifest
72
- rescue Exception => e
73
- puts "\n!!! Plugin installation FAILED: #{e.message}\n\n"
74
- end
75
-
76
- # Check the manifest to see if the plugin is already installed in this application.
77
- def self.plugin_installed?
78
- with_manifest do |manifest|
79
- return manifest.has_key?(gem_name)
80
- end
81
- rescue
82
- false
83
- end
84
-
85
- # Search the local Rubygems installation for the gem.
86
- def self.find_locally
87
- all_installed_gems = Gem::SourceIndex.from_installed_gems
88
- latest_gem_version = all_installed_gems.search(gem_name).sort_by {|x| x.version.version }.last
89
- require 'pp'
90
-
91
- if latest_gem_version
92
- puts "Local gem found."
93
- return latest_gem_version
94
- else
95
- puts "Can't find gem...installing."
96
- return false
97
- end
98
- end
99
-
100
- # Run the installation code in the gem.
101
- def self.run_install_script
102
- require "#{gem_name}/install"
103
- end
104
-
105
- # Copy the Rakefile from the gem to a directory in our application.
106
- def self.copy_rakefile
107
- path = gem_spec.loaded_from.split(/specifications/)[0] + "gems/#{gem_name}-#{gem_spec.version.version}/"
108
-
109
- merb_rake_file = path + "Rakefile.merb"
110
-
111
- require 'fileutils'
112
- Dir.mkdir 'plugins' if !File.exists?('plugins/')
113
- FileUtils.cp merb_rake_file, "plugins/#{gem_name}.rake"
114
-
115
- File.open('Rakefile', 'a') do |rakefile|
116
- rakefile.write("\nrequire 'plugins/#{gem_name}.rake\n")
117
- end
118
- end
119
-
120
- def self.remove_rakefile
121
- FileUtils.rm "plugins/#{gem_name}.rake"
122
-
123
- File.open('Rakefile', 'r+') do |rakefile|
124
- contents = rakefile.read
125
- contents.gsub!("\nrequire 'plugins/#{gem_name}.rake\n", "")
126
-
127
- rakefile.pos = 0
128
- rakefile.write contents
129
- rakefile.truncate rakefile.pos
130
- end
131
- end
132
-
133
- # Do a gem installation since it wasn't found in the locally installed gems.
134
- def self.install_gem
135
- require 'rubygems/installer'
136
-
137
- options = {
138
- :domain => :both,
139
- :generate_rdoc => true,
140
- :generate_ri => true,
141
- :force => false,
142
- :test => false,
143
- :wrappers => true,
144
- :version => "> 0",
145
- :install_dir => Gem.dir,
146
- :security_policy => nil }
147
-
148
-
149
-
150
- puts "Attempting local install..."
151
- local_install = Gem::Installer.new(gem_name, options).install(options[:force], options[:install_dir]) rescue false
152
-
153
- if !local_install
154
- # Do remote installation
155
- require 'rubygems/remote_installer'
156
-
157
- Gem.configuration = ConfigStub.new
158
-
159
- puts "Attempting remote installation..."
160
- installer = Gem::RemoteInstaller.new(options)
161
-
162
- @@options.each do |opt|
163
- installer.sources << opt.gsub(/source=/, '') if opt.scan(/^source=/) != []
164
- options[:version] = "> #{opt.gsub(/version=/, '')}" if opt.scan(/^version=/) != []
165
- end
166
-
167
- remote_install = installer.install(gem_name, options[:version], options[:force], options[:install_dir]) rescue false
168
- end
169
-
170
- if !remote_install && !local_install
171
- raise "That plugin can't be found in locally or in a remote repository."
172
- else
173
- find_locally
174
- end
175
- end
176
-
177
- # Method to open and load our manifest; yields the manifest data to whatever method calls it.
178
- def self.with_manifest
179
- File.open('plugins.manifest', 'r+') do |manifest_file|
180
- manifest_data = YAML::load(manifest_file.read)
181
- manifest_data = {} if !manifest_data.is_a?(Hash)
182
-
183
- yield manifest_data
184
-
185
- manifest_file.pos = 0
186
- manifest_file.write manifest_data.to_yaml
187
- manifest_file.truncate manifest_file.pos
188
- end
189
- end
190
-
191
- # Write our newly installed plugin to the application's manifest.
192
- def self.add_to_manifest
193
- with_manifest do |manifest_data|
194
- manifest_data[gem_name] = {'version' => gem_spec.version.version}
195
- end
196
- end
197
-
198
- def self.uninstall
199
- raise "That plugin isn't installed!" if !plugin_installed?
200
-
201
- require "#{gem_name}/uninstall" rescue nil
202
-
203
- remove_rakefile
204
- remove_from_manifest
205
- uninstall_gem
206
- end
207
-
208
- def self.remove_from_manifest
209
- with_manifest do |manifest|
210
- manifest.delete(gem_name)
211
- end
212
- end
213
-
214
- def self.uninstall_gem
215
- require 'rubygems/installer'
216
- require 'rubygems/doc_manager'
217
-
218
- options = {
219
- :domain => :both,
220
- :generate_rdoc => true,
221
- :generate_ri => true,
222
- :force => false,
223
- :test => false,
224
- :wrappers => true,
225
- :version => "> 0",
226
- :install_dir => Gem.dir,
227
- :security_policy => nil }
228
-
229
- Gem::Uninstaller.new(gem_name, options).uninstall
230
- end
231
-
232
- def self.list
233
- with_manifest do |manifest_data|
234
- manifest_data.each do |key, value|
235
- gem_name = key
236
- gem_spec = find_locally
237
- puts "#{key} (#{gem_spec.version.version})"
238
- puts "\t#{gem_spec.description}\n"
239
- end
240
- end
241
- end
242
-
243
- def self.migrate
244
- raise "This hasn't been implemented yet!"
245
- end
246
-
247
- def self.help
248
- puts """
249
- Merb Plugins
250
- The -P (--plugin) option fed to Merb allows you to manage plugins.
251
-
252
- Commands
253
- --------
254
- install Installs a new plugin.
255
- uninstall Uninstalls a plugin, removing its entry from the manifest and uninstalling the gem.
256
- remove Uninstalls a plugin, removing its entry from the manifest but leaving the gem installed.
257
- list Lists all installed plugins for this Merb application.
258
- upgrade Upgrades a plugin to the specified version.
259
- update Updates a plugin to the latest available version.
260
- migrate Reads the manifest for this application, installing and updating gems as needed.
261
- help Shows this help message.
262
-
263
- """
264
- end
265
- end
266
-
267
- # Class to stub out the verbose flag in Rubygems user interaction lib
268
- class ConfigStub
269
- attr_accessor :verbose
270
-
271
- def initialize
272
- @verbose = false
273
- end
274
- end
275
- end
276
-
277
- module Gem
278
- # Fixes a bug in RubyGems where the SilentProgressReporter class is
279
- # inaccurately named SilentReporter. Maybe one day we'll monkeypatch this for
280
- # our own purposes.
281
- class SilentProgressReporter
282
- attr_reader :count
283
-
284
- def initialize(out_stream, size, initial_message)
285
- end
286
-
287
- def updated(message)
288
- end
289
-
290
- def done
291
- end
292
- end
293
- end