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
@@ -1,4 +1,3 @@
1
-
2
1
  begin
3
2
  require 'markaby'
4
3
  rescue LoadError
@@ -7,22 +6,20 @@ end
7
6
 
8
7
  module Markaby
9
8
  class Builder
10
- def _buf; self end
11
- def throw_content(name, &block)
12
- @helpers.instance_variable_set "@_#{name}_content",
13
- eval("@_#{name}_content = (@_#{name}_content|| '') + capture(&block)")
9
+ def _buffer( binding )
10
+ eval( "_erbout", binding )
11
+ end
12
+
13
+ def concat( string, binding )
14
+ _buffer( binding ) << string
14
15
  end
15
16
  end
16
17
  end
17
18
 
18
19
  module Merb
19
20
 
20
- module Template
21
-
22
- module Markaby
23
-
24
- ::Merb::AbstractController.register_engine self, %w[ mab ]
25
-
21
+ module Template
22
+ module Markaby
26
23
  class << self
27
24
 
28
25
  def exempt_from_layout?
@@ -32,7 +29,7 @@ module Merb
32
29
  # OPTIMIZE : add mab template caching. what does this mean for mab?
33
30
  # mab is just ruby, there's no two phase compile and run
34
31
  def transform(options = {})
35
- opts, file, view_context = options.values_at(:opts, :file, :view_context)
32
+ opts, text, file, view_context = options.values_at(:opts, :text, :file, :view_context)
36
33
 
37
34
  if opts[:locals]
38
35
  locals = ""
@@ -42,12 +39,17 @@ module Merb
42
39
  locals
43
40
  end
44
41
 
42
+ template = text ? text : File.read(file)
45
43
  mab = ::Markaby::Builder.new({}, view_context) {
46
- instance_eval("#{locals}#{File.read(file)}")
44
+ instance_eval("#{locals}#{template}")
47
45
  }
48
46
  mab.to_s
49
47
  end
50
-
48
+
49
+ def view_context_klass
50
+ ::Merb::ViewContext
51
+ end
52
+
51
53
  end
52
54
 
53
55
  end
@@ -9,10 +9,11 @@ module Merb
9
9
  module Template # :nodoc:
10
10
  # A module to allow you to use Builder["http://builder.rubyforge.org/"] templates in your Merb applications.
11
11
  # Your Builder templates must end in .rxml, .xerb, or .builder for Merb to use them.
12
- module XMLBuilder
13
12
 
14
- ::Merb::AbstractController.register_engine self, %w[ rxml xerb builder]
15
13
 
14
+
15
+ module XMLBuilder
16
+
16
17
  class << self
17
18
 
18
19
  def exempt_from_layout? # :nodoc:
@@ -25,8 +26,8 @@ module Merb
25
26
  # executes the Builder template by feeding it to <tt>Builder::XmlMarkup.new</tt>,
26
27
  # then calls <tt>target!</tt> on the<tt>Builder::XmlMarkup</tt> instance to get its XML output.
27
28
  def transform(options = {})
28
- opts, file, view_context = options.values_at(:opts, :file, :view_context)
29
- xml_body = IO.read(file)
29
+ opts, text, file, view_context = options.values_at(:opts, :text, :file, :view_context)
30
+ xml_body = text ? text : IO.read(file)
30
31
  view_context.headers['Content-Type'] = 'application/xml'
31
32
  view_context.headers['Encoding'] = 'UTF-8'
32
33
  view_context.instance_eval %{
@@ -37,6 +38,9 @@ module Merb
37
38
  }
38
39
  end
39
40
 
41
+ def view_context_klass
42
+ ::Merb::ViewContext
43
+ end
40
44
  end
41
45
 
42
46
  end
@@ -1,3 +1,5 @@
1
+ require 'ostruct'
2
+
1
3
  module Merb
2
4
  module Test
3
5
  # FakeRequest sets up a default enviroment which can be overridden either
@@ -8,14 +10,19 @@ module Merb
8
10
  alias :params :env
9
11
  alias :to_hash :env
10
12
 
11
- def initialize(env = {}, method = 'GET', req = StringIO.new)
13
+ def initialize(env = {}, req = StringIO.new)
12
14
  env[:http_cookie] = env.delete(:cookies) if env[:cookies]
13
15
  env.environmentize_keys!
14
- super(DEFAULT_ENV.dup.merge(env), method, req)
16
+
17
+ r = OpenStruct.new
18
+ r.params = DEFAULT_ENV.dup.merge(env)
19
+ r.body = req
20
+ super(r)
15
21
  self.post_body = ''
16
22
  end
17
23
 
18
24
  def self.with(path, options = {})
25
+ options.merge!(:QUERY_STRING => path.split("?")[1])
19
26
  options.environmentize_keys!
20
27
  new({'REQUEST_URI' => path,
21
28
  'PATH_INFO' => path.sub(/\?.*$/,'')}.merge(options))
@@ -32,8 +39,7 @@ module Merb
32
39
  def []=(key, value)
33
40
  @env[key] = value
34
41
  end
35
-
36
-
42
+
37
43
  private
38
44
  DEFAULT_ENV = {
39
45
  'SERVER_NAME' => 'localhost',
@@ -57,7 +63,7 @@ module Merb
57
63
  'HTTP_ACCEPT' => 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
58
64
  'HTTP_CONNECTION' => 'keep-alive',
59
65
  'REQUEST_METHOD' => 'GET'
60
- }
66
+ } unless defined?(DEFAULT_ENV)
61
67
  end
62
68
  end
63
69
  end
@@ -0,0 +1,31 @@
1
+ require 'merb/test/fake_request'
2
+ require 'merb/test/hpricot'
3
+ include HpricotTestHelper
4
+
5
+ # Create a FakeRequest suitable for passing to Controller.build
6
+ def fake_request(path="/",method='GET')
7
+ method = method.to_s.upcase
8
+ Merb::Test::FakeRequest.with(path, :request_method => method)
9
+ end
10
+
11
+ # Turn a named route into a string with the path
12
+ def url(name, *args)
13
+ Merb::Router.generate(name, *args)
14
+ end
15
+
16
+
17
+ # For integration/functional testing
18
+
19
+
20
+ def request(verb, path)
21
+ response = StringIO.new
22
+ @request = Merb::Test::FakeRequest.with(path, :request_method => (verb.to_s.upcase rescue 'GET'))
23
+
24
+ yield @request if block_given?
25
+
26
+ @controller, @action = Merb::Dispatcher.handle @request, response
27
+ end
28
+
29
+ def get(path)
30
+ request("GET",path)
31
+ end
@@ -0,0 +1,136 @@
1
+ # http://yehudakatz.com/2007/01/27/a-better-assert_select-assert_elements/
2
+ # based on assert_elements
3
+ # Author: Yehuda Katz
4
+ # Email: wycats @nospam@ gmail.com
5
+ # Web: http://www.yehudakatz.com
6
+ #
7
+ # which was based on HpricotTestHelper
8
+ # Author: Luke Redpath
9
+ # Email: contact @nospam@ lukeredpath.co.uk
10
+ # Web: www.lukeredpath.co.uk / opensource.agileevolved.com
11
+
12
+ require 'hpricot'
13
+
14
+ class Hpricot::Elem
15
+ def should_contain(value)
16
+ self.inner_text.include?(value)
17
+ end
18
+
19
+ def should_match(regex)
20
+ self.inner_text.match(regex)
21
+ end
22
+
23
+ # courtesy of 'thomas' from the comments
24
+ # of _whys blog - get in touch if you want a better credit!
25
+ def inner_text
26
+ self.children.collect do |child|
27
+ child.is_a?(Hpricot::Text) ? child.content : ((child.respond_to?("inner_text") && child.inner_text) || "")
28
+ end.join.strip
29
+ end
30
+ end
31
+
32
+ module HpricotTestHelper
33
+ # returns the inner content of
34
+ # the first tag found by the css query
35
+ def tag(css_query)
36
+ process_output
37
+ @output.content_for(css_query)
38
+ end
39
+
40
+ # returns an array of tag contents
41
+ # for all of the tags found by the
42
+ # css query
43
+ def tags(css_query)
44
+ process_output
45
+ @output.content_for_all(css_query)
46
+ end
47
+
48
+ # returns a raw Hpricot::Elem object
49
+ # for the first result found by the query
50
+ def element(css_query)
51
+ process_output
52
+ @output[css_query].first
53
+ end
54
+
55
+ # returns an array of Hpricot::Elem objects
56
+ # for the results found by the query
57
+ def elements(css_query)
58
+ process_output
59
+ Hpricot::Elements[*css_query.split(",").map(&:strip).map do |query|
60
+ @output[query]
61
+ end.flatten]
62
+ end
63
+
64
+ def get_elements css_query, text
65
+ els = elements(css_query)
66
+ case text
67
+ when String then els.reject! {|t| !t.should_contain(text) }
68
+ when Regexp then els.reject! {|t| !t.should_match(text) }
69
+ end
70
+ els
71
+ end
72
+
73
+ def assert_elements css_query, equality = nil, &block
74
+ message = equality.delete(:message) if equality.is_a?(Hash)
75
+
76
+ case equality
77
+ when Numeric then equality = {:count => equality}
78
+ when Range then equality = {:minimum => equality.to_a.first, :maximum => equality.to_a.last }
79
+ else equality ||= {}
80
+ end
81
+
82
+ equality.merge!({:minimum => 1}) if (equality.keys & [:minimum, :maximum, :count]).empty?
83
+
84
+ els = get_elements(css_query, equality[:text])
85
+
86
+ ret = equality.keys.include?(:minimum) ? (els.size >= equality[:minimum]) : true
87
+ ret &&= (els.size <= equality[:maximum]) if equality.keys.include?(:maximum)
88
+ ret &&= (els.size == equality[:count]) if equality.keys.include?(:count)
89
+
90
+ if block && !els.empty?
91
+ ret &&= self.dup.instance_eval do
92
+ @output = HpricotTestHelper::DocumentOutput.new(els.inner_html)
93
+ @block = true
94
+ instance_eval(&block)
95
+ end
96
+ end
97
+
98
+ if(equality[:count] != 0)
99
+ assert ret, "#{ message } \"#{ css_query }\" with \"#{ equality.inspect }\" was not found."
100
+ else
101
+ assert ret, "#{ message } \"#{ css_query }\" with \"#{ equality.reject{|k,v| k == :count}.inspect }\" was found, but you specified :count => 0."
102
+ end
103
+ ret
104
+ end
105
+
106
+ # small utility class for working with
107
+ # the Hpricot parser class
108
+ class DocumentOutput
109
+ def initialize(response_body)
110
+ @parser = Hpricot.parse(response_body)
111
+ end
112
+
113
+ def content_for(css_query)
114
+ @parser.search(css_query).first.inner_text
115
+ end
116
+
117
+ def content_for_all(css_query)
118
+ @parser.search(css_query).collect(&:inner_text)
119
+ end
120
+
121
+ def [](css_query)
122
+ @parser.search(css_query)
123
+ end
124
+ end
125
+
126
+ protected
127
+ # creates a new DocumentOutput object from the response
128
+ # body if hasn't already been created. This is
129
+ # called automatically by the element and tag methods
130
+ def process_output
131
+ if !@block && (@output.nil? || (@controller.body != @response_output))
132
+ @output = HpricotTestHelper::DocumentOutput.new(@controller.body)
133
+ @response_output = @controller.body
134
+ end
135
+ end
136
+ end
@@ -39,7 +39,7 @@ module Merb
39
39
  end
40
40
 
41
41
  def push_params(params)
42
- params.each do |key, value|
42
+ params.sort_by {|k| k.to_s}.each do |key, value|
43
43
  if value.respond_to?(:read)
44
44
  @multipart_params << FileParam.new(key, value.path, value.read)
45
45
  else
@@ -0,0 +1,93 @@
1
+ require 'hpricot'
2
+ require 'spec'
3
+ module MerbRspecMatchers
4
+ class HaveSelector
5
+ def initialize(expected)
6
+ @expected = expected
7
+ end
8
+
9
+ def matches?(stringlike)
10
+ @document = case stringlike
11
+ when Hpricot::Elem
12
+ stringlike
13
+ when StringIO
14
+ Hpricot.parse(stringlike.string)
15
+ else
16
+ Hpricot.parse(stringlike)
17
+ end
18
+ !@document.search(@expected).empty?
19
+ end
20
+
21
+ def failure_message
22
+ "expected following text to match selector #{@expected}:\n#{@document}"
23
+ end
24
+
25
+ def negative_failure_message
26
+ "expected following text to not match selector #{@expected}:\n#{@document}"
27
+ end
28
+ end
29
+
30
+ class MatchTag
31
+ def initialize(name, attrs)
32
+ @name, @attrs = name, attrs
33
+ end
34
+
35
+ def matches?(target)
36
+ @errors = []
37
+ unless target.include?("<#{@name}")
38
+ @errors << "Expected a <#{@name}>, but was #{target}"
39
+ end
40
+ @attrs.each do |attr, val|
41
+ unless target.include?("#{attr}=\"#{val}\"")
42
+ @errors << "Expected #{attr}=\"#{val}\", but was #{target}"
43
+ end
44
+ end
45
+ @errors.size == 0
46
+ end
47
+
48
+ def failure_message
49
+ @errors[0]
50
+ end
51
+
52
+ def negative_failure_message
53
+ "Expected not to match against <#{@name} #{@attrs.map{ |a,v| "#{a}=\"#{v}\"" }.join(" ")}> tag, but it matched"
54
+ end
55
+ end
56
+
57
+ class NotMatchTag
58
+ def initialize(attrs)
59
+ @attrs = attrs
60
+ end
61
+
62
+ def matches?(target)
63
+ @errors = []
64
+ @attrs.each do |attr, val|
65
+ if target.include?("#{attr}=\"#{val}\"")
66
+ @errors << "Should not include #{attr}=\"#{val}\", but was #{target}"
67
+ end
68
+ end
69
+ @errors.size == 0
70
+ end
71
+
72
+ def failure_message
73
+ @errors[0]
74
+ end
75
+ end
76
+
77
+ def match_tag(name, attrs)
78
+ MatchTag.new(name, attrs)
79
+ end
80
+ def not_match_tag(attrs)
81
+ NotMatchTag.new(attrs)
82
+ end
83
+
84
+ def have_selector(expected)
85
+ HaveSelector.new(expected)
86
+ end
87
+ alias_method :match_selector, :have_selector
88
+ # alias_method :match_regex, :match
89
+ end
90
+
91
+ Spec::Runner.configure do |config|
92
+ config.include(MerbRspecMatchers)
93
+ end
@@ -28,15 +28,14 @@ end
28
28
  class MerbUploadHandler < Mongrel::HttpHandler
29
29
 
30
30
  def initialize(options = {})
31
- @path_info = Array(options[:path_info])
32
- @frequency = options[:frequency] || 3
31
+ @path_match = Regexp.new(options[:upload_path_match])
32
+ @frequency = options[:upload_frequency] || 3
33
33
  @request_notify = true
34
- if options[:drb]
34
+ if options[:start_drb]
35
35
  require 'drb'
36
36
  DRb.start_service
37
- Mongrel.const_set :Uploads, DRbObject.new(nil, "druby://#{Merb::Server.host}:#{Merb::Server.drb_server_port}").upload_progress
37
+ Mongrel.const_set :Uploads, DRbObject.new(nil, "druby://#{options[:host]}:#{options[:drb_server_port]}").upload_progress
38
38
  else
39
- require File.dirname(__FILE__)+'/merb_upload_progress'
40
39
  Mongrel.const_set :Uploads, Merb::UploadProgress.new
41
40
  end
42
41
  Mongrel::Uploads.debug = true if options[:debug]
@@ -72,7 +71,7 @@ class MerbUploadHandler < Mongrel::HttpHandler
72
71
  end
73
72
 
74
73
  def valid_upload?(params)
75
- @path_info.any? { |p| params[Mongrel::Const::PATH_INFO].include?(p) } &&
74
+ params[Mongrel::Const::PATH_INFO].match(@path_match) &&
76
75
  [Mongrel::Const::POST, Mongrel::Const::PUT].include?(params[Mongrel::Const::REQUEST_METHOD]) &&
77
76
  Mongrel::HttpRequest.query_parse(params[Mongrel::Const::QUERY_STRING])[Mongrel::Const::UPLOAD_ID]
78
77
  end
@@ -1,7 +1,7 @@
1
1
  module Merb
2
2
  # Keeps track of the status of all currently processing uploads
3
3
  class UploadProgress
4
- include DRbUndumped
4
+ include DRbUndumped if defined?(DRbUndumped)
5
5
  attr_accessor :debug
6
6
  def initialize
7
7
  @guard = Mutex.new