merb 0.4.2 → 0.5.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.
- data/README +21 -14
- data/Rakefile +157 -108
- data/SVN_REVISION +1 -0
- data/app_generators/merb/templates/Rakefile +20 -4
- data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +1 -1
- data/app_generators/merb/templates/config/boot.rb +1 -1
- data/app_generators/merb/templates/config/dependencies.rb +3 -3
- data/app_generators/merb/templates/config/merb.yml +5 -0
- data/app_generators/merb/templates/config/merb_init.rb +3 -3
- data/app_generators/merb/templates/script/destroy +3 -0
- data/app_generators/merb/templates/script/generate +1 -1
- data/app_generators/merb/templates/spec/spec_helper.rb +2 -2
- data/app_generators/merb/templates/test/test_helper.rb +1 -1
- data/app_generators/merb_plugin/merb_plugin_generator.rb +4 -0
- data/bin/merb +1 -3
- data/lib/merb.rb +144 -76
- data/lib/merb/abstract_controller.rb +6 -5
- data/lib/merb/assets.rb +119 -0
- data/lib/merb/boot_loader.rb +217 -0
- data/lib/merb/caching.rb +1 -1
- data/lib/merb/caching/action_cache.rb +1 -1
- data/lib/merb/caching/fragment_cache.rb +1 -1
- data/lib/merb/caching/store/file_cache.rb +1 -1
- data/lib/merb/config.rb +290 -0
- data/lib/merb/controller.rb +5 -5
- data/lib/merb/core_ext/get_args.rb +1 -0
- data/lib/merb/core_ext/hash.rb +182 -169
- data/lib/merb/core_ext/kernel.rb +57 -26
- data/lib/merb/dispatcher.rb +6 -6
- data/lib/merb/drb_server.rb +1 -1
- data/lib/merb/generators/merb_generator_helpers.rb +7 -6
- data/lib/merb/logger.rb +1 -1
- data/lib/merb/mail_controller.rb +3 -4
- data/lib/merb/mailer.rb +2 -2
- data/lib/merb/mixins/basic_authentication.rb +2 -2
- data/lib/merb/mixins/controller.rb +1 -1
- data/lib/merb/mixins/general_controller.rb +13 -20
- data/lib/merb/mixins/inline_partial.rb +32 -0
- data/lib/merb/mixins/render.rb +3 -3
- data/lib/merb/mixins/responder.rb +1 -1
- data/lib/merb/mixins/view_context.rb +159 -33
- data/lib/merb/mongrel_handler.rb +9 -9
- data/lib/merb/plugins.rb +1 -1
- data/lib/merb/request.rb +25 -1
- data/lib/merb/router.rb +264 -226
- data/lib/merb/server.rb +66 -560
- data/lib/merb/session/cookie_store.rb +14 -13
- data/lib/merb/session/mem_cache_session.rb +20 -10
- data/lib/merb/session/memory_session.rb +21 -11
- data/lib/merb/template.rb +2 -2
- data/lib/merb/template/erubis.rb +3 -33
- data/lib/merb/template/haml.rb +8 -3
- data/lib/merb/test/fake_request.rb +8 -3
- data/lib/merb/test/helper.rb +66 -22
- data/lib/merb/test/rspec.rb +9 -155
- data/lib/merb/test/rspec_matchers/controller_matchers.rb +117 -0
- data/lib/merb/test/rspec_matchers/markup_matchers.rb +98 -0
- data/lib/merb/upload_handler.rb +2 -1
- data/lib/merb/version.rb +38 -3
- data/lib/merb/view_context.rb +1 -2
- data/lib/tasks/merb.rake +11 -11
- data/merb_generators/part_controller/USAGE +5 -0
- data/merb_generators/part_controller/part_controller_generator.rb +27 -0
- data/merb_generators/part_controller/templates/controller.rb +8 -0
- data/merb_generators/part_controller/templates/helper.rb +5 -0
- data/merb_generators/part_controller/templates/index.html.erb +3 -0
- data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +1 -1
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/fixtures/controllers/dispatch_spec_controllers.rb +9 -1
- data/spec/fixtures/controllers/render_spec_controllers.rb +5 -5
- data/spec/fixtures/models/router_spec_models.rb +10 -0
- data/spec/merb/abstract_controller_spec.rb +2 -2
- data/spec/merb/assets_spec.rb +207 -0
- data/spec/merb/caching_spec.rb +2 -2
- data/spec/merb/controller_spec.rb +7 -2
- data/spec/merb/cookie_store_spec.rb +1 -1
- data/spec/merb/core_ext/class_spec.rb +97 -0
- data/spec/merb/core_ext/enumerable_spec.rb +27 -0
- data/spec/merb/core_ext/hash_spec.rb +251 -0
- data/spec/merb/core_ext/inflector_spec.rb +34 -0
- data/spec/merb/core_ext/kernel_spec.rb +25 -0
- data/spec/merb/core_ext/numeric_spec.rb +26 -0
- data/spec/merb/core_ext/object_spec.rb +47 -0
- data/spec/merb/core_ext/string_spec.rb +22 -0
- data/spec/merb/core_ext/symbol_spec.rb +7 -0
- data/spec/merb/dependency_spec.rb +22 -0
- data/spec/merb/dispatch_spec.rb +23 -12
- data/spec/merb/fake_request_spec.rb +8 -0
- data/spec/merb/generator_spec.rb +140 -21
- data/spec/merb/handler_spec.rb +5 -5
- data/spec/merb/mail_controller_spec.rb +3 -3
- data/spec/merb/render_spec.rb +1 -1
- data/spec/merb/responder_spec.rb +3 -3
- data/spec/merb/router_spec.rb +260 -191
- data/spec/merb/server_spec.rb +5 -5
- data/spec/merb/upload_handler_spec.rb +7 -0
- data/spec/merb/version_spec.rb +33 -0
- data/spec/merb/view_context_spec.rb +217 -59
- data/spec/spec_generator_helper.rb +15 -0
- data/spec/spec_helper.rb +5 -3
- data/spec/spec_helpers/url_shared_behaviour.rb +5 -7
- metadata +32 -7
- data/lib/merb/caching/store/memcache.rb +0 -20
- data/lib/merb/mixins/form_control.rb +0 -332
- data/lib/patch +0 -69
- data/spec/merb/core_ext_spec.rb +0 -464
- data/spec/merb/form_control_mixin_spec.rb +0 -431
|
@@ -7,13 +7,13 @@ module Merb
|
|
|
7
7
|
|
|
8
8
|
module SessionMixin #:nodoc:
|
|
9
9
|
def setup_session
|
|
10
|
-
|
|
10
|
+
Merb.logger.info("Setting Up Cookie Store Sessions")
|
|
11
11
|
request.session = Merb::CookieStore.new(cookies[_session_id_key], session_secret_key)
|
|
12
12
|
@original_session = request.session.read_cookie
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def finalize_session
|
|
16
|
-
|
|
16
|
+
Merb.logger.info("Finalize Cookie Store Session")
|
|
17
17
|
new_session = request.session.read_cookie
|
|
18
18
|
|
|
19
19
|
if @original_session != new_session
|
|
@@ -74,24 +74,25 @@ module Merb
|
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
# assigns a key value pair
|
|
78
|
-
def []=(k, v)
|
|
77
|
+
# assigns a key value pair
|
|
78
|
+
def []=(k, v)
|
|
79
79
|
@data[k] = v
|
|
80
80
|
end
|
|
81
81
|
|
|
82
|
-
def [](k)
|
|
83
|
-
@data[k]
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if @data.has_key?(key)
|
|
89
|
-
@data.delete(key)
|
|
90
|
-
end
|
|
82
|
+
def [](k)
|
|
83
|
+
@data[k]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def each(&b)
|
|
87
|
+
@data.each(&b)
|
|
91
88
|
end
|
|
92
89
|
|
|
93
90
|
private
|
|
94
91
|
|
|
92
|
+
def method_missing(name, *args, &block)
|
|
93
|
+
@data.send(name, *args, &block)
|
|
94
|
+
end
|
|
95
|
+
|
|
95
96
|
# Generate the HMAC keyed message digest. Uses SHA1.
|
|
96
97
|
def generate_digest(data)
|
|
97
98
|
OpenSSL::HMAC.hexdigest(DIGEST, @secret, data)
|
|
@@ -5,7 +5,7 @@ module Merb
|
|
|
5
5
|
module SessionMixin #:nodoc:
|
|
6
6
|
|
|
7
7
|
def setup_session
|
|
8
|
-
|
|
8
|
+
Merb.logger.info("Setting up session")
|
|
9
9
|
before = cookies[_session_id_key]
|
|
10
10
|
request.session, cookies[_session_id_key] = Merb::MemCacheSession.persist(cookies[_session_id_key])
|
|
11
11
|
@_fingerprint = Marshal.dump(request.session.data).hash
|
|
@@ -13,7 +13,7 @@ module Merb
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def finalize_session
|
|
16
|
-
|
|
16
|
+
Merb.logger.info("Finalize session")
|
|
17
17
|
if @_fingerprint != Marshal.dump(request.session.data).hash
|
|
18
18
|
::Cache.put("session:#{@_session.session_id}", request.session.data)
|
|
19
19
|
end
|
|
@@ -102,19 +102,29 @@ module Merb
|
|
|
102
102
|
def delete
|
|
103
103
|
@data = {}
|
|
104
104
|
end
|
|
105
|
-
|
|
106
|
-
def [](key)
|
|
107
|
-
@data[key]
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def []=(key, val)
|
|
111
|
-
@data[key] = val
|
|
112
|
-
end
|
|
113
105
|
|
|
114
106
|
# Has the session been loaded yet?
|
|
115
107
|
def loaded?
|
|
116
108
|
!! @data
|
|
117
109
|
end
|
|
110
|
+
|
|
111
|
+
# assigns a key value pair
|
|
112
|
+
def []=(k, v)
|
|
113
|
+
@data[k] = v
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def [](k)
|
|
117
|
+
@data[k]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def each(&b)
|
|
121
|
+
@data.each(&b)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
private
|
|
125
|
+
def method_missing(name, *args, &block)
|
|
126
|
+
@data.send(name, *args, &block)
|
|
127
|
+
end
|
|
118
128
|
|
|
119
129
|
end
|
|
120
130
|
|
|
@@ -3,14 +3,14 @@ module Merb
|
|
|
3
3
|
module SessionMixin #:nodoc:
|
|
4
4
|
|
|
5
5
|
def setup_session
|
|
6
|
-
|
|
6
|
+
Merb.logger.info("Setting up session")
|
|
7
7
|
before = cookies[_session_id_key]
|
|
8
8
|
request.session , cookies[_session_id_key] = Merb::MemorySession.persist(cookies[_session_id_key])
|
|
9
9
|
@_new_cookie = cookies[_session_id_key] != before
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def finalize_session
|
|
13
|
-
|
|
13
|
+
Merb.logger.info("Finalize session")
|
|
14
14
|
set_cookie(_session_id_key, request.session.session_id, _session_expiry) if (@_new_cookie || request.session.needs_new_cookie)
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -83,18 +83,28 @@ module Merb
|
|
|
83
83
|
@data = {}
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
def [](key)
|
|
87
|
-
@data[key]
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def []=(key, val)
|
|
91
|
-
@data[key] = val
|
|
92
|
-
end
|
|
93
|
-
|
|
94
86
|
# Has the session been loaded yet?
|
|
95
87
|
def loaded?
|
|
96
88
|
!! @data
|
|
97
89
|
end
|
|
90
|
+
|
|
91
|
+
# assigns a key value pair
|
|
92
|
+
def []=(k, v)
|
|
93
|
+
@data[k] = v
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def [](k)
|
|
97
|
+
@data[k]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def each(&b)
|
|
101
|
+
@data.each(&b)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
def method_missing(name, *args, &block)
|
|
106
|
+
@data.send(name, *args, &block)
|
|
107
|
+
end
|
|
98
108
|
|
|
99
109
|
end
|
|
100
110
|
|
|
@@ -163,4 +173,4 @@ module Merb
|
|
|
163
173
|
end # end MemorySessionContainer
|
|
164
174
|
end
|
|
165
175
|
|
|
166
|
-
Merb::MemorySessionContainer.setup(Merb::
|
|
176
|
+
Merb::MemorySessionContainer.setup(Merb::Config[:memory_session_ttl])
|
data/lib/merb/template.rb
CHANGED
|
@@ -27,10 +27,10 @@ module Merb
|
|
|
27
27
|
# are directly referenced, or a file with their extension is found.
|
|
28
28
|
# If these are declared inside the template engine then
|
|
29
29
|
# they will never be found :(
|
|
30
|
-
register_extensions( :Erubis, %w[erb
|
|
30
|
+
register_extensions( :Erubis, %w[erb])
|
|
31
31
|
register_extensions( :Haml, %w[haml])
|
|
32
32
|
register_extensions( :Markaby, %w[mab])
|
|
33
|
-
register_extensions( :XMLBuilder, %w[builder
|
|
33
|
+
register_extensions( :XMLBuilder, %w[builder])
|
|
34
34
|
|
|
35
35
|
end
|
|
36
36
|
|
data/lib/merb/template/erubis.rb
CHANGED
|
@@ -3,37 +3,7 @@ module Merb # :nodoc:
|
|
|
3
3
|
|
|
4
4
|
class ErubisViewContext < ViewContext
|
|
5
5
|
include ::Merb::ErubisCaptureMixin
|
|
6
|
-
|
|
7
|
-
def partial(template, opts={})
|
|
8
|
-
|
|
9
|
-
unless @_template_format
|
|
10
|
-
@web_controller.choose_template_format(Merb.available_mime_types, {})
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
template = @web_controller._cached_partials["#{template}.#{@_template_format}"] ||=
|
|
14
|
-
@web_controller.send(:find_partial, template)
|
|
15
|
-
|
|
16
|
-
template_method = template.gsub(/[^\.a-zA-Z0-9]/, "__").gsub(/\./, "_")
|
|
17
|
-
|
|
18
|
-
unless self.respond_to?(template_method)
|
|
19
|
-
raise Merb::ControllerExceptions::TemplateNotFound, "No template matched at #{template}"
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
if with = opts.delete(:with)
|
|
23
|
-
as = opts.delete(:as) || template.match(/(.*\/_)([^\.]*)/)[2]
|
|
24
|
-
@_merb_partial_locals = opts
|
|
25
|
-
sent_template = [with].flatten.map do |temp|
|
|
26
|
-
@_merb_partial_locals[as.to_sym] = temp
|
|
27
|
-
send(template_method)
|
|
28
|
-
end.join
|
|
29
|
-
else
|
|
30
|
-
@_merb_partial_locals = opts
|
|
31
|
-
sent_template = send(template_method)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
return sent_template if sent_template
|
|
35
|
-
|
|
36
|
-
end
|
|
6
|
+
include ::Merb::InlinePartialMixin
|
|
37
7
|
end
|
|
38
8
|
|
|
39
9
|
# Module to allow you to use Embedded Ruby templates through Erubis["http://www.kuwata-lab.com/erubis/"].
|
|
@@ -66,7 +36,7 @@ module Merb # :nodoc:
|
|
|
66
36
|
|
|
67
37
|
# Creates a new Erubis object to parse the template given in +path+.
|
|
68
38
|
def new_eruby_obj(path)
|
|
69
|
-
if @@erbs[path] &&
|
|
39
|
+
if @@erbs[path] && Merb.environment == 'production'
|
|
70
40
|
return @@erbs[path]
|
|
71
41
|
else
|
|
72
42
|
begin
|
|
@@ -84,7 +54,7 @@ module Merb # :nodoc:
|
|
|
84
54
|
|
|
85
55
|
private
|
|
86
56
|
def cache_template?(path)
|
|
87
|
-
return false unless ::Merb::
|
|
57
|
+
return false unless ::Merb::Config[:cache_templates]
|
|
88
58
|
return true unless @@erbs[path]
|
|
89
59
|
@@mtimes[path] < File.mtime(path) ||
|
|
90
60
|
(File.symlink?(path) && (@@mtimes[path] < File.lstat(path).mtime))
|
data/lib/merb/template/haml.rb
CHANGED
|
@@ -20,6 +20,10 @@ end
|
|
|
20
20
|
module Merb
|
|
21
21
|
module Template
|
|
22
22
|
|
|
23
|
+
class HamlViewContext < ViewContext
|
|
24
|
+
include ::Merb::InlinePartialMixin
|
|
25
|
+
end
|
|
26
|
+
|
|
23
27
|
module Haml
|
|
24
28
|
|
|
25
29
|
class << self
|
|
@@ -36,7 +40,8 @@ module Merb
|
|
|
36
40
|
|
|
37
41
|
begin
|
|
38
42
|
|
|
39
|
-
|
|
43
|
+
# Merb handles the locals
|
|
44
|
+
opts.delete(:locals)
|
|
40
45
|
|
|
41
46
|
template = text ? text : load_template(file)
|
|
42
47
|
|
|
@@ -51,7 +56,7 @@ module Merb
|
|
|
51
56
|
end
|
|
52
57
|
|
|
53
58
|
def view_context_klass
|
|
54
|
-
|
|
59
|
+
HamlViewContext
|
|
55
60
|
end
|
|
56
61
|
|
|
57
62
|
private
|
|
@@ -69,7 +74,7 @@ module Merb
|
|
|
69
74
|
end
|
|
70
75
|
|
|
71
76
|
def cache_template?(path)
|
|
72
|
-
return false unless ::Merb::
|
|
77
|
+
return false unless ::Merb::Config[:cache_templates]
|
|
73
78
|
return true unless @@hamls[path]
|
|
74
79
|
@@mtimes[path] < File.mtime(path) ||
|
|
75
80
|
(File.symlink?(path) && (@@mtimes[path] < File.lstat(path).mtime))
|
|
@@ -19,6 +19,7 @@ module Merb
|
|
|
19
19
|
r.body = req
|
|
20
20
|
super(r)
|
|
21
21
|
self.post_body = ''
|
|
22
|
+
@session = {}
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def self.with(path, options = {})
|
|
@@ -31,7 +32,11 @@ module Merb
|
|
|
31
32
|
def post_body=(post)
|
|
32
33
|
@req = StringIO.new(post)
|
|
33
34
|
end
|
|
34
|
-
|
|
35
|
+
|
|
36
|
+
def session
|
|
37
|
+
@session
|
|
38
|
+
end
|
|
39
|
+
|
|
35
40
|
def [](key)
|
|
36
41
|
@env[key]
|
|
37
42
|
end
|
|
@@ -41,7 +46,7 @@ module Merb
|
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
private
|
|
44
|
-
DEFAULT_ENV = {
|
|
49
|
+
DEFAULT_ENV = Mash.new({
|
|
45
50
|
'SERVER_NAME' => 'localhost',
|
|
46
51
|
'PATH_INFO' => '/',
|
|
47
52
|
'HTTP_ACCEPT_ENCODING' => 'gzip,deflate',
|
|
@@ -63,7 +68,7 @@ module Merb
|
|
|
63
68
|
'HTTP_ACCEPT' => 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
|
|
64
69
|
'HTTP_CONNECTION' => 'keep-alive',
|
|
65
70
|
'REQUEST_METHOD' => 'GET'
|
|
66
|
-
} unless defined?(DEFAULT_ENV)
|
|
71
|
+
}) unless defined?(DEFAULT_ENV)
|
|
67
72
|
end
|
|
68
73
|
end
|
|
69
74
|
end
|
data/lib/merb/test/helper.rb
CHANGED
|
@@ -5,22 +5,15 @@ include HpricotTestHelper
|
|
|
5
5
|
module Merb
|
|
6
6
|
module Test
|
|
7
7
|
module Helper
|
|
8
|
+
include Merb::GeneralControllerMixin
|
|
9
|
+
|
|
8
10
|
# Create a FakeRequest suitable for passing to Controller.build
|
|
9
|
-
def fake_request(
|
|
11
|
+
def fake_request(params = {})
|
|
10
12
|
method = method.to_s.upcase
|
|
11
|
-
Merb::Test::FakeRequest.with(
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Turn a named route into a string with the path
|
|
15
|
-
# This is the same method as is found in the controller
|
|
16
|
-
def url(name, *args)
|
|
17
|
-
Merb::Router.generate(name, *args)
|
|
13
|
+
Merb::Test::FakeRequest.with("/", {:request_method => "GET"}.merge(params))
|
|
18
14
|
end
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
|
|
21
16
|
# For integration/functional testing
|
|
22
|
-
|
|
23
|
-
|
|
24
17
|
def request(verb, path)
|
|
25
18
|
response = StringIO.new
|
|
26
19
|
@request = Merb::Test::FakeRequest.with(path, :request_method => (verb.to_s.upcase rescue 'GET'))
|
|
@@ -30,8 +23,44 @@ module Merb
|
|
|
30
23
|
@controller, @action = Merb::Dispatcher.handle @request, response
|
|
31
24
|
end
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
|
|
27
|
+
# Makes a get request routed to +path+ with any options encoded into the
|
|
28
|
+
# request url
|
|
29
|
+
# Example
|
|
30
|
+
# {{{
|
|
31
|
+
# get "/users", :user => {:login => "dave", :email => "email@example.com"}
|
|
32
|
+
# }}}
|
|
33
|
+
def get(path, opts = {}, &block)
|
|
34
|
+
request("GET",path_with_options(path,opts), &block)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Makes a post request routed to +path+ with any options encoded into the
|
|
38
|
+
# request url
|
|
39
|
+
# Example
|
|
40
|
+
# {{{
|
|
41
|
+
# post "/users", :user => {:login => "dave", :email => "email@example.com"}
|
|
42
|
+
# }}}
|
|
43
|
+
def post(path, opts = {}, &block)
|
|
44
|
+
request("POST", path_with_options(path,opts), &block)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Makes a put request routed to +path+ with any options encoded into the
|
|
48
|
+
# request url
|
|
49
|
+
# Example
|
|
50
|
+
# {{{
|
|
51
|
+
# put "/users/1", :user => {:login => "dave", :email => "email@example.com"}
|
|
52
|
+
# }}}
|
|
53
|
+
def put(path,opts = {}, &block)
|
|
54
|
+
request("PUT", path_with_options(path,opts), &block)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Makes a delete request routed to +path+ with any options encoded into the request url
|
|
58
|
+
# Example
|
|
59
|
+
# {{{
|
|
60
|
+
# delete "/users/1", :user => {:login => "dave", :email => "email@example.com"}
|
|
61
|
+
# }}}
|
|
62
|
+
def delete(path, opts= {}, &block)
|
|
63
|
+
request("DELETE", path_with_options(path,opts), &block)
|
|
35
64
|
end
|
|
36
65
|
|
|
37
66
|
def controller
|
|
@@ -54,7 +83,8 @@ module Merb
|
|
|
54
83
|
# params[:id].should == "1"
|
|
55
84
|
# end
|
|
56
85
|
def with_route(the_path, _method = "GET")
|
|
57
|
-
|
|
86
|
+
_fake_request = Merb::Test::FakeRequest.with(the_path, :request_method => _method)
|
|
87
|
+
result = Merb::Router.match(_fake_request, {})
|
|
58
88
|
yield result[1] if block_given?
|
|
59
89
|
result
|
|
60
90
|
end
|
|
@@ -90,14 +120,28 @@ module Merb
|
|
|
90
120
|
# }}}
|
|
91
121
|
def dispatch_to(controller, action = :index, opts = {})
|
|
92
122
|
klass = controller.class == Class ? controller : controller.class
|
|
93
|
-
klass.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
123
|
+
@controller = klass.build(fake_request)
|
|
124
|
+
@controller.stub!(:params).and_return(opts.merge(:controller => klass.name.downcase, :action => action.to_s).to_mash)
|
|
125
|
+
yield @controller if block_given?
|
|
126
|
+
[@controller, @controller.dispatch(action.to_sym)]
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def path_with_options(path, opts)
|
|
130
|
+
path = path << "?" << params_to_query_string(opts) unless opts.empty?
|
|
131
|
+
path
|
|
100
132
|
end
|
|
101
133
|
end
|
|
102
134
|
end
|
|
103
135
|
end
|
|
136
|
+
|
|
137
|
+
class Object
|
|
138
|
+
# Checks that an object has assigned an instance variable of name
|
|
139
|
+
# :name
|
|
140
|
+
#
|
|
141
|
+
# ===Example in a spec
|
|
142
|
+
# @my_obj.assings(:my_value).should == @my_value
|
|
143
|
+
def assigns(attr)
|
|
144
|
+
self.instance_variable_get("@#{attr}")
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
data/lib/merb/test/rspec.rb
CHANGED
|
@@ -1,164 +1,18 @@
|
|
|
1
1
|
require 'hpricot'
|
|
2
2
|
require 'spec'
|
|
3
|
-
module Merb
|
|
4
|
-
module Test
|
|
5
|
-
module MerbRspecControllerRedirect
|
|
6
|
-
class BeRedirect
|
|
7
|
-
def matches?(target)
|
|
8
|
-
@target = target
|
|
9
|
-
target == 302
|
|
10
|
-
end
|
|
11
|
-
def failure_message
|
|
12
|
-
"expected to redirect"
|
|
13
|
-
end
|
|
14
|
-
def negative_failure_message
|
|
15
|
-
"expected not to redirect"
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
class Redirect
|
|
20
|
-
def matches?(target)
|
|
21
|
-
@target = target
|
|
22
|
-
BeRedirect.new.matches?(target.status)
|
|
23
|
-
end
|
|
24
|
-
def failure_message
|
|
25
|
-
"expected #{@target.inspect} to redirect"
|
|
26
|
-
end
|
|
27
|
-
def negative_failure_message
|
|
28
|
-
"expected #{@target.inspect} not to redirect"
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
class RedirectTo
|
|
33
|
-
def initialize(expected)
|
|
34
|
-
@expected = expected
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def matches?(target)
|
|
38
|
-
@target = target.headers['Location']
|
|
39
|
-
@redirected = BeRedirect.new.matches?(target.status)
|
|
40
|
-
@target == @expected
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def failure_message
|
|
44
|
-
msg = "expected a redirect to <#{@expected}>, but "
|
|
45
|
-
if @redirected
|
|
46
|
-
msg << "found one to <#{@target}>"
|
|
47
|
-
else
|
|
48
|
-
msg << "there was no redirect"
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def negative_failure_message
|
|
53
|
-
"expected not to redirect to <#{@expected}>, but did anyway"
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
3
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
4
|
+
# Get all the rspec matchers for merb and include them
|
|
5
|
+
Dir[(File.dirname(__FILE__) + "/rspec_matchers/**/*.rb")].each do |file|
|
|
6
|
+
require "#{file[0...-3]}"
|
|
7
|
+
end
|
|
60
8
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def redirect_to(expected)
|
|
66
|
-
RedirectTo.new(expected)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
9
|
+
module Merb
|
|
10
|
+
module Test
|
|
70
11
|
module RspecMatchers
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def matches?(stringlike)
|
|
77
|
-
@document = case stringlike
|
|
78
|
-
when Hpricot::Elem
|
|
79
|
-
stringlike
|
|
80
|
-
when StringIO
|
|
81
|
-
Hpricot.parse(stringlike.string)
|
|
82
|
-
else
|
|
83
|
-
Hpricot.parse(stringlike)
|
|
84
|
-
end
|
|
85
|
-
!@document.search(@expected).empty?
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def failure_message
|
|
89
|
-
"expected following text to match selector #{@expected}:\n#{@document}"
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def negative_failure_message
|
|
93
|
-
"expected following text to not match selector #{@expected}:\n#{@document}"
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
class MatchTag
|
|
98
|
-
def initialize(name, attrs)
|
|
99
|
-
@name, @attrs = name, attrs
|
|
100
|
-
@content = @attrs.delete(:content)
|
|
101
|
-
end
|
|
12
|
+
|
|
13
|
+
include ControllerMatchers
|
|
14
|
+
include MarkupMatchers
|
|
102
15
|
|
|
103
|
-
def matches?(target)
|
|
104
|
-
@errors = []
|
|
105
|
-
unless target.include?("<#{@name}")
|
|
106
|
-
@errors << "Expected a <#{@name}>, but was #{target}"
|
|
107
|
-
end
|
|
108
|
-
@attrs.each do |attr, val|
|
|
109
|
-
unless target.include?("#{attr}=\"#{val}\"")
|
|
110
|
-
@errors << "Expected #{attr}=\"#{val}\", but was #{target}"
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
if @content
|
|
114
|
-
unless target.include?(">#{@content}<")
|
|
115
|
-
@errors << "Expected #{target} to include #{@content}"
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
@errors.size == 0
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def failure_message
|
|
122
|
-
@errors[0]
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def negative_failure_message
|
|
126
|
-
"Expected not to match against <#{@name} #{@attrs.map{ |a,v| "#{a}=\"#{v}\"" }.join(" ")}> tag, but it matched"
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
class NotMatchTag
|
|
131
|
-
def initialize(attrs)
|
|
132
|
-
@attrs = attrs
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def matches?(target)
|
|
136
|
-
@errors = []
|
|
137
|
-
@attrs.each do |attr, val|
|
|
138
|
-
if target.include?("#{attr}=\"#{val}\"")
|
|
139
|
-
@errors << "Should not include #{attr}=\"#{val}\", but was #{target}"
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
@errors.size == 0
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def failure_message
|
|
146
|
-
@errors[0]
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def match_tag(name, attrs)
|
|
151
|
-
MatchTag.new(name, attrs)
|
|
152
|
-
end
|
|
153
|
-
def not_match_tag(attrs)
|
|
154
|
-
NotMatchTag.new(attrs)
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def have_selector(expected)
|
|
158
|
-
HaveSelector.new(expected)
|
|
159
|
-
end
|
|
160
|
-
alias_method :match_selector, :have_selector
|
|
161
|
-
# alias_method :match_regex, :match
|
|
162
16
|
end
|
|
163
17
|
end
|
|
164
18
|
end
|