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,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