merb 0.3.7 → 0.4.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 (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
@@ -6,11 +6,16 @@ module Merb
6
6
  @cache ||= determine_cache_store
7
7
  end
8
8
 
9
+ def clear
10
+ cache.clear
11
+ @cache = nil
12
+ end
13
+
9
14
  def get(name)
10
15
  cache.get(name)
11
16
  end
12
17
 
13
- def put(name, content = nil)
18
+ def put(name, content = nil)
14
19
  cache.put(name, content)
15
20
  content
16
21
  end
@@ -20,12 +25,12 @@ module Merb
20
25
  end
21
26
 
22
27
  def determine_cache_store
23
- if ::Merb::Server.cache_store.to_s == "file"
28
+ if ::Merb::Server.config[:cache_store].to_s == "file"
24
29
  require 'merb/caching/store/file_cache'
25
30
  ::Merb::Caching::Store::FileCache.new
26
31
  else
27
- require 'merb/caching/store/memory_cache'
28
- ::Merb::Caching::Store::MemoryCache.new
32
+ require 'merb/caching/store/memory_cache'
33
+ ::Merb::Caching::Store::MemoryCache.new
29
34
  end
30
35
  end
31
36
  end
@@ -10,29 +10,31 @@ module Merb
10
10
 
11
11
  def initialize(name = "cache", keepalive = nil)
12
12
  @path = File.join(MERB_ROOT, name)
13
- @keepalive = keepalive
14
-
15
- FileUtils.mkdir_p(@path, :mode => 0700)
13
+ @keepalive = keepalive
16
14
  end
17
15
 
18
- def []=(k,v)
19
- fn = File.join(@path, escape_filename(k.to_s) )
20
- encode_file(fn, v)
16
+ def []=(key,val)
17
+ key = escape_filenames([key].flatten)
18
+ FileUtils.mkdir_p(File.join(@path, *key[0..-2]), :mode => 0700)
19
+ fn = File.join(@path, *key )
20
+ encode_file(fn, val)
21
21
  end
22
22
  alias :put :[]=
23
23
  alias :write :[]=
24
24
 
25
- def [](k)
26
- fn = File.join(@path, escape_filename(k.to_s) )
25
+ def [](key)
26
+ key = escape_filenames([key].flatten)
27
+ fn = File.join(@path, *key )
27
28
  return nil unless File.exists?(fn)
28
29
  decode_file(fn)
29
30
  end
30
31
  alias :get :[]
31
32
  alias_method :read, :[]
32
33
 
33
- def delete(k)
34
- f = File.join(@path, escape_filename(k.to_s))
35
- File.delete(f) if File.exists?(f)
34
+ def delete(key)
35
+ key = escape_filenames([key].flatten)
36
+ f = File.join(@path, *key)
37
+ FileUtils.rm_rf(f)
36
38
  end
37
39
 
38
40
  def gc!
@@ -44,12 +46,16 @@ module Merb
44
46
  File.delete(fn) if now > expire_time
45
47
  end
46
48
  end
49
+
50
+ def clear
51
+ all.each{|file| delete(File.basename(file)) }
52
+ end
47
53
 
48
54
  private
49
55
 
50
56
  def decode_file(fn)
51
57
  val = nil
52
- File.open(fn,"rb") do |f|
58
+ File.open(fn,"r+b") do |f|
53
59
  f.flock(File::LOCK_EX)
54
60
  val = Marshal.load( f.read )
55
61
  f.flock(File::LOCK_UN)
@@ -70,8 +76,10 @@ module Merb
70
76
  Dir.glob( File.join(@path, '*' ) )
71
77
  end
72
78
  # need this for fat filesystems
73
- def escape_filename(fn)
74
- URI.escape(fn, /["\/:;|=,\[\]]/)
79
+ def escape_filenames(fns)
80
+ fns.collect do |fn|
81
+ URI.escape(fn.to_s, /["\/:;|=,\[\]]/)
82
+ end
75
83
  end
76
84
 
77
85
  end
@@ -13,26 +13,41 @@ module Merb
13
13
  end
14
14
 
15
15
  def [](key)
16
+ key = [key].flatten.collect{|k| k.to_s}
16
17
  @mutex.synchronize {
17
18
  @timestamps[key] = Time.now
18
- @cache[key]
19
+ sub_cache = @cache
20
+ key[0..-2].each do |subkey|
21
+ sub_cache = (sub_cache[subkey] ||= {})
22
+ end
23
+ sub_cache[key[-1]]
19
24
  }
20
25
  end
21
26
  alias_method :get, :[]
22
27
  alias_method :read, :[]
23
28
 
24
- def []=(key, val)
29
+ def []=(key, val)
30
+ key = [key].flatten.collect{|k| k.to_s}
25
31
  @mutex.synchronize {
32
+ sub_cache = @cache
33
+ key[0..-2].each do |subkey|
34
+ sub_cache = (sub_cache[subkey] ||= {})
35
+ end
36
+ sub_cache[key[-1]] = val
26
37
  @timestamps[key] = Time.now
27
- @cache[key] = val
28
38
  }
29
39
  end
30
40
  alias_method :put, :[]=
31
41
  alias_method :write, :[]=
32
42
 
33
43
  def delete(key)
44
+ key = [key].flatten.collect{|k| k.to_s}
34
45
  @mutex.synchronize {
35
- @cache.delete(key)
46
+ sub_cache = @cache
47
+ key[0..-2].each do |subkey|
48
+ sub_cache = (sub_cache[subkey] ||= {})
49
+ end
50
+ sub_cache.delete(key[-1])
36
51
  }
37
52
  end
38
53
  alias_method :remove, :delete
@@ -57,11 +72,14 @@ module Merb
57
72
  def keys
58
73
  @cache.keys
59
74
  end
75
+
76
+ def clear
77
+ @cache = Hash.new
78
+ @timestamps = Hash.new
79
+ @mutex = Mutex.new
80
+ end
60
81
 
61
82
  end
62
-
63
83
  end
64
-
65
- end
66
-
84
+ end
67
85
  end
@@ -15,6 +15,7 @@ module Merb
15
15
  }.freeze
16
16
 
17
17
  SET_COOKIE = " %s=%s; path=/; expires=%s".freeze
18
+ COOKIE_EXPIRATION_FORMAT = "%a, %d-%b-%Y %H:%M:%S GMT".freeze
18
19
  COOKIE_SPLIT = /[;,] */n.freeze
19
20
  COOKIE_REGEXP = /\s*(.+)=(.*)\s*/.freeze
20
21
  COOKIE_EXPIRED_TIME = Time.at(0).freeze
@@ -27,7 +28,8 @@ module Merb
27
28
  APPLICATION_JSON = 'application/json'.freeze
28
29
  TEXT_JSON = 'text/x-json'.freeze
29
30
  APPLICATION_XML = 'application/xml'.freeze
30
- TEXT_XML = 'text/xml'.freeze
31
+ TEXT_XML = 'text/xml'.freeze
32
+ FORM_URL_ENCODED_REGEXP = %r{^application/x-www-form-urlencoded}.freeze
31
33
  UPCASE_CONTENT_TYPE = 'CONTENT_TYPE'.freeze
32
34
  CONTENT_TYPE = "Content-Type".freeze
33
35
  LAST_MODIFIED = "Last-Modified".freeze
@@ -40,11 +42,11 @@ module Merb
40
42
  HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
41
43
  HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE".freeze
42
44
  HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH".freeze
43
- UPLOAD_ID = 'upload_id'.freeze
44
- PATH_INFO="PATH_INFO".freeze
45
- SCRIPT_NAME="SCRIPT_NAME".freeze
46
- REQUEST_URI='REQUEST_URI'.freeze
47
- REQUEST_PATH='REQUEST_PATH'.freeze
48
- REMOTE_ADDR="REMOTE_ADDR".freeze
45
+ UPLOAD_ID = "upload_id".freeze
46
+ PATH_INFO = "PATH_INFO".freeze
47
+ SCRIPT_NAME = "SCRIPT_NAME".freeze
48
+ REQUEST_URI = "REQUEST_URI".freeze
49
+ REQUEST_PATH = "REQUEST_PATH".freeze
50
+ REMOTE_ADDR = "REMOTE_ADDR".freeze
49
51
  end
50
52
  end
@@ -0,0 +1,178 @@
1
+ module Merb
2
+
3
+ # All of your web controllers will inherit from Merb::Controller. This
4
+ # superclass takes care of parsing the incoming headers and body into
5
+ # params and cookies and headers. If the request is a file upload it will
6
+ # stream it into a tempfile and pass in the filename and tempfile object
7
+ # to your controller via params. It also parses the ?query=string and
8
+ # puts that into params as well.
9
+ class Controller < AbstractController
10
+ cattr_accessor :_subclasses
11
+ self._subclasses = []
12
+
13
+ class_inheritable_accessor :_session_id_key, :_session_expiry
14
+ self._session_id_key = :_session_id
15
+ self._session_expiry = Time.now + Merb::Const::WEEK * 2
16
+
17
+ include Merb::ControllerMixin
18
+ include Merb::ResponderMixin
19
+ include Merb::ControllerExceptions
20
+
21
+ class << self
22
+ def inherited(klass)
23
+ _subclasses << klass.to_s
24
+ super
25
+ end
26
+
27
+ def callable_actions
28
+ @callable_actions ||= begin
29
+ hsh = {}
30
+ (public_instance_methods - hidden_actions).each {|action| hsh[action.to_s] = true}
31
+ hsh
32
+ end
33
+ end
34
+
35
+ def hidden_actions
36
+ write_inheritable_attribute(:hidden_actions, Merb::Controller.public_instance_methods) unless read_inheritable_attribute(:hidden_actions)
37
+ read_inheritable_attribute(:hidden_actions)
38
+ end
39
+
40
+ # Hide each of the given methods from being callable as actions.
41
+ def hide_action(*names)
42
+ write_inheritable_attribute(:hidden_actions, hidden_actions | names.collect { |n| n.to_s })
43
+ end
44
+
45
+ def build(request, response = StringIO.new, status=200, headers={'Content-Type' => 'text/html; charset=utf-8'})
46
+ cont = new
47
+ cont.set_dispatch_variables(request, response, status, headers)
48
+ cont
49
+ end
50
+ end
51
+
52
+ def set_dispatch_variables(request, response, status, headers)
53
+ if request.params.key?(_session_id_key)
54
+ if Merb::Server.config[:session_id_cookie_only]
55
+ # This condition allows for certain controller/action paths to allow
56
+ # a session ID to be passed in a query string. This is needed for
57
+ # Flash Uploads to work since flash will not pass a Session Cookie
58
+ # Recommend running session.regenerate after any controller taking
59
+ # advantage of this in case someone is attempting a session fixation
60
+ # attack
61
+ if Merb::Server.config[:query_string_whitelist].include?("#{request.controller_name}/#{request.action}")
62
+ # FIXME to use routes not controller and action names -----^
63
+ request.cookies[_session_id_key] = request.params[_session_id_key]
64
+ end
65
+ else
66
+ request.cookies[_session_id_key] = request.params[_session_id_key]
67
+ end
68
+ end
69
+ @_request = request
70
+ @_response = response
71
+ @_status = status
72
+ @_headers = headers
73
+ end
74
+
75
+ def dispatch(action=:index)
76
+ start = Time.now
77
+ if self.class.callable_actions[action.to_s]
78
+ params[:action] ||= action
79
+ setup_session
80
+ super(action)
81
+ finalize_session
82
+ else
83
+ raise ActionNotFound, "Action '#{action}' was not found in #{self.class}"
84
+ end
85
+ @_benchmarks[:action_time] = Time.now - start
86
+ MERB_LOGGER.info("Time spent in #{self.class}##{action} action: #{@_benchmarks[:action_time]} seconds")
87
+ end
88
+
89
+ # Accessor for @_body. Please use body and never @body directly.
90
+ def body
91
+ @_body
92
+ end
93
+
94
+ # Accessor for @_status. Please use status and never @_status directly.
95
+ def status
96
+ @_status
97
+ end
98
+
99
+ # Accessor for @_request. Please use request and never @_request directly.
100
+ def request
101
+ @_request
102
+ end
103
+
104
+ def params
105
+ request.params
106
+ end
107
+
108
+ def cookies
109
+ request.cookies
110
+ end
111
+
112
+ # Accessor for @_headers. Please use headers and never @_headers directly.
113
+ def headers
114
+ @_headers
115
+ end
116
+
117
+ # Accessor for @_session. Please use session and never @_session directly.
118
+ def session
119
+ request.session
120
+ end
121
+
122
+ # Accessor for @_response. Please use response and never @_response directly.
123
+ def response
124
+ @_response
125
+ end
126
+
127
+ # Accessor for @_route. Please use route and never @_route directly.
128
+ def route
129
+ request.route
130
+ end
131
+
132
+ # Sends mail via a MailController (a tutorial can be found in the
133
+ # MailController docs).
134
+ #
135
+ # send_mail FooMailer, :bar, :from => "foo@bar.com", :to => "baz@bat.com"
136
+ #
137
+ # would send an email via the FooMailer's bar method.
138
+ #
139
+ # The mail_params hash would be sent to the mailer, and includes items
140
+ # like from, to subject, and cc. See
141
+ # Merb::MailController#dispatch_and_deliver for more details.
142
+ #
143
+ # The send_params hash would be sent to the MailController, and is
144
+ # available to methods in the MailController as <tt>params</tt>. If you do
145
+ # not send any send_params, this controller's params will be available to
146
+ # the MailController as <tt>params</tt>
147
+ def send_mail(klass, method, mail_params, send_params = nil)
148
+ klass.new(send_params || params, self).dispatch_and_deliver(method, mail_params)
149
+ end
150
+
151
+ # Dispatches a PartController. Use like:
152
+ #
153
+ # <%= part TodoPart => :list %>
154
+ #
155
+ # will instantiate a new TodoPart controller and call the :list action
156
+ # invoking the Part's before and after filters as part of the call.
157
+ #
158
+ # returns a string containing the results of the Part controllers dispatch
159
+ #
160
+ # You can compose parts easily as well, these two parts will stil be wrapped
161
+ # in the layout of the Foo controller:
162
+ #
163
+ # class Foo < Application
164
+ # def some_action
165
+ # wrap_layout(part(TodoPart => :new) + part(TodoPart => :list))
166
+ # end
167
+ # end
168
+ #
169
+ def part(opts={})
170
+ res = opts.inject([]) do |memo,(klass,action)|
171
+ memo << klass.new(self).dispatch(action)
172
+ end
173
+ res.size == 1 ? res[0] : res
174
+ end
175
+
176
+ end
177
+
178
+ end
@@ -1,13 +1,15 @@
1
- corelib = __DIR__+'/merb/core_ext'
1
+ corelib = File.dirname(__FILE__) + '/core_ext'
2
2
 
3
- %w[ merb_inflector
4
- merb_class
5
- merb_kernel
6
- merb_object
7
- merb_enumerable
8
- merb_module
9
- merb_string
10
- merb_hash
11
- merb_numeric
12
- merb_symbol
3
+ %w[ inflector
4
+ class
5
+ kernel
6
+ object
7
+ mash
8
+ enumerable
9
+ module
10
+ string
11
+ hash
12
+ numeric
13
+ symbol
14
+ get_args
13
15
  ].each {|fn| require File.join(corelib, fn)}
File without changes
@@ -0,0 +1,52 @@
1
+ begin
2
+ require 'ruby2ruby'
3
+
4
+ class ParseTreeArray < Array
5
+ def self.translate(*args)
6
+ self.new(ParseTree.translate(*args))
7
+ end
8
+
9
+ def deep_array_node(type = nil)
10
+ each do |node|
11
+ return ParseTreeArray.new(node) if node.is_a?(Array) && (!type || node[0] == type)
12
+ next unless node.is_a?(Array)
13
+ return ParseTreeArray.new(node).deep_array_node(type)
14
+ end
15
+ nil
16
+ end
17
+
18
+ def arg_nodes
19
+ self[1..-1].inject([]) do |sum,item|
20
+ sum << [item] unless item.is_a?(Array)
21
+ sum
22
+ end
23
+ end
24
+
25
+ def get_args
26
+ arg_node = deep_array_node(:args)
27
+ args = arg_node.arg_nodes
28
+ lasgns = arg_node.deep_array_node(:block)[1..-1]
29
+ lasgns.each do |asgn|
30
+ args.assoc(asgn[1]) << eval(RubyToRuby.new.process(asgn[2]))
31
+ end
32
+ args
33
+ end
34
+
35
+ end
36
+
37
+ module GetArgs
38
+ def get_args
39
+ klass, meth = self.to_s.split(/ /).to_a[1][0..-2].split("#")
40
+ ParseTreeArray.translate(Object.const_get(klass), meth).get_args
41
+ end
42
+ end
43
+
44
+ class UnboundMethod
45
+ include GetArgs
46
+ end
47
+
48
+ class Method
49
+ include GetArgs
50
+ end
51
+ rescue LoadError
52
+ end