vcr 2.0.0.beta2 → 2.0.0.rc1
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/.gitignore +1 -0
- data/.travis.yml +0 -2
- data/CHANGELOG.md +22 -1
- data/CONTRIBUTING.md +46 -0
- data/Gemfile +1 -9
- data/README.md +8 -2
- data/Rakefile +12 -1
- data/cucumber.yml +8 -9
- data/features/.nav +10 -4
- data/features/cassettes/format.feature +1 -1
- data/features/cassettes/no_cassette.feature +8 -11
- data/features/configuration/allow_http_connections_when_no_cassette.feature +4 -4
- data/features/configuration/filter_sensitive_data.feature +3 -0
- data/features/configuration/hook_into.feature +4 -8
- data/features/configuration/ignore_request.feature +191 -0
- data/features/getting_started.md +38 -21
- data/features/hooks/after_http_request.feature +44 -0
- data/features/hooks/around_http_request.feature +56 -0
- data/features/hooks/before_http_request.feature +44 -0
- data/features/hooks/before_playback.feature +181 -0
- data/features/hooks/before_record.feature +172 -0
- data/features/middleware/faraday.feature +7 -3
- data/features/record_modes/none.feature +2 -1
- data/features/record_modes/once.feature +2 -1
- data/features/request_matching/body.feature +2 -2
- data/features/request_matching/custom_matcher.feature +2 -2
- data/features/request_matching/headers.feature +2 -2
- data/features/request_matching/host.feature +2 -2
- data/features/request_matching/identical_request_sequence.feature +2 -2
- data/features/request_matching/method.feature +2 -2
- data/features/request_matching/path.feature +2 -2
- data/features/request_matching/playback_repeats.feature +2 -1
- data/features/request_matching/uri.feature +2 -2
- data/features/support/env.rb +21 -12
- data/features/test_frameworks/cucumber.feature +9 -4
- data/features/test_frameworks/{rspec.feature → rspec_macro.feature} +7 -7
- data/features/test_frameworks/rspec_metadata.feature +90 -0
- data/lib/vcr.rb +1 -1
- data/lib/vcr/cassette.rb +3 -3
- data/lib/vcr/cassette/http_interaction_list.rb +13 -9
- data/lib/vcr/cassette/migrator.rb +1 -1
- data/lib/vcr/configuration.rb +37 -0
- data/lib/vcr/errors.rb +172 -6
- data/lib/vcr/library_hooks.rb +4 -6
- data/lib/vcr/library_hooks/excon.rb +23 -11
- data/lib/vcr/library_hooks/fakeweb.rb +85 -24
- data/lib/vcr/library_hooks/faraday.rb +30 -2
- data/lib/vcr/library_hooks/typhoeus.rb +25 -3
- data/lib/vcr/library_hooks/webmock.rb +25 -36
- data/lib/vcr/middleware/faraday.rb +23 -5
- data/lib/vcr/request_handler.rb +12 -1
- data/lib/vcr/request_ignorer.rb +12 -1
- data/lib/vcr/request_matcher_registry.rb +1 -9
- data/lib/vcr/structs.rb +32 -2
- data/lib/vcr/test_frameworks/rspec.rb +28 -0
- data/lib/vcr/util/hooks.rb +12 -4
- data/lib/vcr/util/version_checker.rb +2 -0
- data/lib/vcr/version.rb +1 -1
- data/spec/fixtures/cassette_spec/example.yml +1 -1
- data/spec/fixtures/{fake_example.com_responses.yml → fake_example_responses.yml} +0 -0
- data/spec/monkey_patches.rb +1 -1
- data/spec/spec_helper.rb +3 -1
- data/spec/support/http_library_adapters.rb +4 -3
- data/spec/support/shared_example_groups/hook_into_http_library.rb +194 -12
- data/spec/support/shared_example_groups/request_hooks.rb +58 -0
- data/spec/support/shared_example_groups/version_checking.rb +5 -0
- data/spec/support/sinatra_app.rb +17 -9
- data/spec/support/vcr_stub_helpers.rb +17 -0
- data/spec/vcr/cassette/http_interaction_list_spec.rb +28 -29
- data/spec/vcr/cassette/migrator_spec.rb +6 -7
- data/spec/vcr/cassette_spec.rb +5 -5
- data/spec/vcr/configuration_spec.rb +51 -32
- data/spec/vcr/deprecations_spec.rb +0 -8
- data/spec/vcr/errors_spec.rb +129 -0
- data/spec/vcr/library_hooks/excon_spec.rb +21 -4
- data/spec/vcr/library_hooks/fakeweb_spec.rb +71 -3
- data/spec/vcr/library_hooks/faraday_spec.rb +45 -0
- data/spec/vcr/library_hooks/typhoeus_spec.rb +31 -1
- data/spec/vcr/library_hooks/webmock_spec.rb +26 -3
- data/spec/vcr/middleware/faraday_spec.rb +84 -1
- data/spec/vcr/request_ignorer_spec.rb +16 -0
- data/spec/vcr/request_matcher_registry_spec.rb +0 -26
- data/spec/vcr/structs_spec.rb +61 -1
- data/spec/vcr/test_frameworks/rspec_spec.rb +32 -0
- data/spec/vcr/util/hooks_spec.rb +73 -63
- data/spec/vcr_spec.rb +2 -2
- data/vcr.gemspec +5 -5
- metadata +51 -31
- data/features/configuration/hooks.feature +0 -270
- data/features/configuration/ignore_hosts.feature +0 -61
- data/features/configuration/ignore_localhost.feature +0 -97
@@ -1,3 +1,31 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module VCR
|
4
|
+
class LibraryHooks
|
5
|
+
module Faraday
|
6
|
+
module BuilderClassExtension
|
7
|
+
def new(*args)
|
8
|
+
super.extend BuilderInstanceExtension
|
9
|
+
end
|
10
|
+
|
11
|
+
::Faraday::Builder.extend self
|
12
|
+
end
|
13
|
+
|
14
|
+
module BuilderInstanceExtension
|
15
|
+
def lock!(*args)
|
16
|
+
insert_vcr_middleware
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def insert_vcr_middleware
|
23
|
+
return if handlers.any? { |h| h.klass == VCR::Middleware::Faraday }
|
24
|
+
adapter_index = handlers.index { |h| h.klass < ::Faraday::Adapter }
|
25
|
+
insert_before(adapter_index, VCR::Middleware::Faraday)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
3
31
|
|
@@ -35,6 +35,11 @@ module VCR
|
|
35
35
|
|
36
36
|
private
|
37
37
|
|
38
|
+
def on_connection_not_allowed
|
39
|
+
invoke_after_request_hook(nil)
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
38
43
|
def vcr_request
|
39
44
|
@vcr_request ||= vcr_request_from(request)
|
40
45
|
end
|
@@ -59,9 +64,15 @@ module VCR
|
|
59
64
|
|
60
65
|
extend Helpers
|
61
66
|
::Typhoeus::Hydra.after_request_before_on_complete do |request|
|
62
|
-
unless VCR.library_hooks.disabled?(:typhoeus)
|
63
|
-
|
64
|
-
|
67
|
+
unless VCR.library_hooks.disabled?(:typhoeus)
|
68
|
+
vcr_request, vcr_response = vcr_request_from(request), vcr_response_from(request.response)
|
69
|
+
|
70
|
+
unless request.response.mock?
|
71
|
+
http_interaction = VCR::HTTPInteraction.new(vcr_request, vcr_response)
|
72
|
+
VCR.record_http_interaction(http_interaction)
|
73
|
+
end
|
74
|
+
|
75
|
+
VCR.configuration.invoke_hook(:after_http_request, vcr_request, vcr_response)
|
65
76
|
end
|
66
77
|
end
|
67
78
|
|
@@ -72,6 +83,17 @@ module VCR
|
|
72
83
|
end
|
73
84
|
end
|
74
85
|
|
86
|
+
class << Typhoeus::Hydra
|
87
|
+
# ensure HTTP requests are always allowed; VCR takes care of disallowing
|
88
|
+
# them at the appropriate times in its hook
|
89
|
+
def allow_net_connect_with_vcr?(*args)
|
90
|
+
VCR.turned_on? ? true : allow_net_connect_without_vcr?
|
91
|
+
end
|
92
|
+
|
93
|
+
alias allow_net_connect_without_vcr? allow_net_connect?
|
94
|
+
alias allow_net_connect? allow_net_connect_with_vcr?
|
95
|
+
end unless Typhoeus::Hydra.respond_to?(:allow_net_connect_with_vcr?)
|
96
|
+
|
75
97
|
VCR.configuration.after_library_hooks_loaded do
|
76
98
|
# ensure WebMock's Typhoeus adapter does not conflict with us here
|
77
99
|
# (i.e. to double record requests or whatever).
|
@@ -2,20 +2,12 @@ require 'vcr/util/version_checker'
|
|
2
2
|
require 'vcr/request_handler'
|
3
3
|
require 'webmock'
|
4
4
|
|
5
|
-
VCR::VersionChecker.new('WebMock', WebMock.version, '1.7.
|
5
|
+
VCR::VersionChecker.new('WebMock', WebMock.version, '1.7.8', '1.7').check_version!
|
6
6
|
|
7
7
|
module VCR
|
8
8
|
class LibraryHooks
|
9
9
|
module WebMock
|
10
10
|
module Helpers
|
11
|
-
def response_hash_for(response)
|
12
|
-
{
|
13
|
-
:body => response.body,
|
14
|
-
:status => [response.status.code.to_i, response.status.message],
|
15
|
-
:headers => response.headers
|
16
|
-
}
|
17
|
-
end
|
18
|
-
|
19
11
|
def vcr_request_from(webmock_request)
|
20
12
|
VCR::Request.new \
|
21
13
|
webmock_request.method,
|
@@ -43,30 +35,27 @@ module VCR
|
|
43
35
|
|
44
36
|
private
|
45
37
|
|
46
|
-
def stubbed_response
|
47
|
-
VCR.http_interactions.has_interaction_matching?(vcr_request)
|
48
|
-
end
|
49
|
-
|
50
38
|
def vcr_request
|
51
39
|
@vcr_request ||= vcr_request_from(request)
|
52
40
|
end
|
53
41
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
42
|
+
def on_connection_not_allowed
|
43
|
+
invoke_after_request_hook(nil)
|
44
|
+
super
|
45
|
+
end
|
46
|
+
|
47
|
+
def on_stubbed_request
|
48
|
+
{
|
49
|
+
:body => stubbed_response.body,
|
50
|
+
:status => [stubbed_response.status.code.to_i, stubbed_response.status.message],
|
51
|
+
:headers => stubbed_response.headers
|
52
|
+
}
|
53
|
+
end
|
57
54
|
end
|
58
55
|
|
59
56
|
extend Helpers
|
60
57
|
|
61
|
-
|
62
|
-
stub.with { |request|
|
63
|
-
RequestHandler.new(request).handle
|
64
|
-
}.to_return(lambda { |request|
|
65
|
-
response_hash_for VCR.http_interactions.response_for(vcr_request_from(request))
|
66
|
-
})
|
67
|
-
end
|
68
|
-
|
69
|
-
::WebMock::StubRegistry.instance.register_request_stub(GLOBAL_VCR_HOOK)
|
58
|
+
::WebMock.globally_stub_request { |req| RequestHandler.new(req).handle }
|
70
59
|
|
71
60
|
::WebMock.after_request(:real_requests_only => true) do |request, response|
|
72
61
|
unless VCR.library_hooks.disabled?(:webmock)
|
@@ -77,6 +66,12 @@ module VCR
|
|
77
66
|
VCR.record_http_interaction(http_interaction)
|
78
67
|
end
|
79
68
|
end
|
69
|
+
|
70
|
+
::WebMock.after_request do |request, response|
|
71
|
+
unless VCR.library_hooks.disabled?(:webmock)
|
72
|
+
VCR.configuration.invoke_hook(:after_http_request, vcr_request_from(request), vcr_response_from(response))
|
73
|
+
end
|
74
|
+
end
|
80
75
|
end
|
81
76
|
end
|
82
77
|
end
|
@@ -84,17 +79,11 @@ end
|
|
84
79
|
class << WebMock
|
85
80
|
# ensure HTTP requests are always allowed; VCR takes care of disallowing
|
86
81
|
# them at the appropriate times in its hook
|
87
|
-
|
88
|
-
|
89
|
-
true
|
82
|
+
def net_connect_allowed_with_vcr?(*args)
|
83
|
+
VCR.turned_on? ? true : net_connect_allowed_without_vcr?
|
90
84
|
end
|
91
|
-
end
|
92
85
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
def reset!
|
97
|
-
self.request_stubs = [VCR::LibraryHooks::WebMock::GLOBAL_VCR_HOOK]
|
98
|
-
end
|
99
|
-
end
|
86
|
+
alias net_connect_allowed_without_vcr? net_connect_allowed?
|
87
|
+
alias net_connect_allowed? net_connect_allowed_with_vcr?
|
88
|
+
end unless WebMock.respond_to?(:net_connect_allowed_with_vcr?)
|
100
89
|
|
@@ -15,21 +15,31 @@ module VCR
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def call(env)
|
18
|
-
|
19
|
-
# We don't want double recording/double playback.
|
20
|
-
VCR.library_hooks.exclusively_enabled(:faraday) do
|
21
|
-
RequestHandler.new(@app, env).handle
|
22
|
-
end
|
18
|
+
RequestHandler.new(@app, env).handle
|
23
19
|
end
|
24
20
|
|
25
21
|
class RequestHandler < ::VCR::RequestHandler
|
26
22
|
attr_reader :app, :env
|
27
23
|
def initialize(app, env)
|
28
24
|
@app, @env = app, env
|
25
|
+
@has_on_complete_hook = false
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle
|
29
|
+
# Faraday must be exlusive here in case another library hook is being used.
|
30
|
+
# We don't want double recording/double playback.
|
31
|
+
VCR.library_hooks.exclusive_hook = :faraday
|
32
|
+
super
|
33
|
+
ensure
|
34
|
+
invoke_after_request_hook(response_for(env)) unless delay_finishing?
|
29
35
|
end
|
30
36
|
|
31
37
|
private
|
32
38
|
|
39
|
+
def delay_finishing?
|
40
|
+
!!env[:parallel_manager] && @has_on_complete_hook
|
41
|
+
end
|
42
|
+
|
33
43
|
def vcr_request
|
34
44
|
@vcr_request ||= VCR::Request.new \
|
35
45
|
env[:method],
|
@@ -40,6 +50,7 @@ module VCR
|
|
40
50
|
|
41
51
|
def response_for(env)
|
42
52
|
response = env[:response]
|
53
|
+
return nil unless response
|
43
54
|
|
44
55
|
VCR::Response.new(
|
45
56
|
VCR::ResponseStatus.new(response.status, nil),
|
@@ -64,10 +75,17 @@ module VCR
|
|
64
75
|
end
|
65
76
|
|
66
77
|
def on_recordable_request
|
78
|
+
@has_on_complete_hook = true
|
67
79
|
app.call(env).on_complete do |env|
|
68
80
|
VCR.record_http_interaction(VCR::HTTPInteraction.new(vcr_request, response_for(env)))
|
81
|
+
invoke_after_request_hook(response_for(env)) if delay_finishing?
|
69
82
|
end
|
70
83
|
end
|
84
|
+
|
85
|
+
def invoke_after_request_hook(response)
|
86
|
+
super
|
87
|
+
VCR.library_hooks.exclusive_hook = nil
|
88
|
+
end
|
71
89
|
end
|
72
90
|
end
|
73
91
|
end
|
data/lib/vcr/request_handler.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module VCR
|
2
2
|
class RequestHandler
|
3
3
|
def handle
|
4
|
+
invoke_before_request_hook
|
4
5
|
return on_ignored_request if should_ignore?
|
5
6
|
return on_stubbed_request if stubbed_response
|
6
7
|
return on_recordable_request if VCR.real_http_connections_allowed?
|
@@ -9,6 +10,16 @@ module VCR
|
|
9
10
|
|
10
11
|
private
|
11
12
|
|
13
|
+
def invoke_before_request_hook
|
14
|
+
return if disabled?
|
15
|
+
VCR.configuration.invoke_hook(:before_http_request, vcr_request)
|
16
|
+
end
|
17
|
+
|
18
|
+
def invoke_after_request_hook(vcr_response)
|
19
|
+
return if disabled?
|
20
|
+
VCR.configuration.invoke_hook(:after_http_request, vcr_request, vcr_response)
|
21
|
+
end
|
22
|
+
|
12
23
|
def should_ignore?
|
13
24
|
disabled? || VCR.request_ignorer.ignore?(vcr_request)
|
14
25
|
end
|
@@ -37,7 +48,7 @@ module VCR
|
|
37
48
|
end
|
38
49
|
|
39
50
|
def on_connection_not_allowed
|
40
|
-
raise VCR::
|
51
|
+
raise VCR::Errors::UnhandledHTTPRequestError.new(vcr_request)
|
41
52
|
end
|
42
53
|
end
|
43
54
|
end
|
data/lib/vcr/request_ignorer.rb
CHANGED
@@ -1,10 +1,21 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'set'
|
3
|
+
require 'vcr/util/hooks'
|
3
4
|
|
4
5
|
module VCR
|
5
6
|
class RequestIgnorer
|
7
|
+
include VCR::Hooks
|
8
|
+
|
9
|
+
define_hook :ignore_request
|
10
|
+
|
6
11
|
LOCALHOST_ALIASES = %w( localhost 127.0.0.1 0.0.0.0 )
|
7
12
|
|
13
|
+
def initialize
|
14
|
+
ignore_request do |request|
|
15
|
+
ignored_hosts.include?(URI(request.uri).host)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
8
19
|
def ignore_localhost=(value)
|
9
20
|
if value
|
10
21
|
ignore_hosts(*LOCALHOST_ALIASES)
|
@@ -18,7 +29,7 @@ module VCR
|
|
18
29
|
end
|
19
30
|
|
20
31
|
def ignore?(request)
|
21
|
-
|
32
|
+
invoke_hook(:ignore_request, request).any?
|
22
33
|
end
|
23
34
|
|
24
35
|
private
|
@@ -80,20 +80,12 @@ module VCR
|
|
80
80
|
|
81
81
|
def register_built_ins
|
82
82
|
register(:method) { |r1, r2| r1.method == r2.method }
|
83
|
-
register(:uri) { |r1, r2|
|
83
|
+
register(:uri) { |r1, r2| r1.uri == r2.uri }
|
84
84
|
register(:host) { |r1, r2| URI(r1.uri).host == URI(r2.uri).host }
|
85
85
|
register(:path) { |r1, r2| URI(r1.uri).path == URI(r2.uri).path }
|
86
86
|
register(:body) { |r1, r2| r1.body == r2.body }
|
87
87
|
register(:headers) { |r1, r2| r1.headers == r2.headers }
|
88
88
|
end
|
89
|
-
|
90
|
-
def without_standard_port(uri)
|
91
|
-
URI(uri).tap do |u|
|
92
|
-
if [['http', 80], ['https', 443]].include?([u.scheme, u.port])
|
93
|
-
u.port = nil
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
89
|
end
|
98
90
|
end
|
99
91
|
|
data/lib/vcr/structs.rb
CHANGED
@@ -78,6 +78,12 @@ module VCR
|
|
78
78
|
include Normalizers::Header
|
79
79
|
include Normalizers::Body
|
80
80
|
|
81
|
+
def initialize(*args)
|
82
|
+
super
|
83
|
+
self.method = self.method.to_s.downcase.to_sym if self.method
|
84
|
+
self.uri = without_standard_port(self.uri)
|
85
|
+
end
|
86
|
+
|
81
87
|
def to_hash
|
82
88
|
{
|
83
89
|
'method' => method.to_s,
|
@@ -101,6 +107,31 @@ module VCR
|
|
101
107
|
return super if args.empty?
|
102
108
|
@@object_method.bind(self).call(*args)
|
103
109
|
end
|
110
|
+
|
111
|
+
# transforms the request into a fiber aware one
|
112
|
+
def fiber_aware
|
113
|
+
extend FiberAware
|
114
|
+
end
|
115
|
+
|
116
|
+
module FiberAware
|
117
|
+
def proceed
|
118
|
+
Fiber.yield
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_proc
|
122
|
+
lambda { proceed }
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def without_standard_port(uri)
|
129
|
+
return uri if uri.nil?
|
130
|
+
u = URI(uri)
|
131
|
+
return uri unless [['http', 80], ['https', 443]].include?([u.scheme, u.port])
|
132
|
+
u.port = nil
|
133
|
+
u.to_s
|
134
|
+
end
|
104
135
|
end
|
105
136
|
|
106
137
|
class HTTPInteraction < Struct.new(:request, :response, :recorded_at)
|
@@ -188,8 +219,7 @@ module VCR
|
|
188
219
|
end
|
189
220
|
|
190
221
|
def update_content_length_header
|
191
|
-
|
192
|
-
value = body ? body.length.to_s : '0'
|
222
|
+
value = body ? body.bytesize.to_s : '0'
|
193
223
|
key = %w[ Content-Length content-length ].find { |k| headers.has_key?(k) }
|
194
224
|
headers[key] = [value] if key
|
195
225
|
end
|
@@ -32,6 +32,34 @@ module VCR
|
|
32
32
|
group_descriptions.compact.reverse.join('/')
|
33
33
|
end
|
34
34
|
end
|
35
|
+
|
36
|
+
module Metadata
|
37
|
+
extend self
|
38
|
+
|
39
|
+
def configure!
|
40
|
+
::RSpec.configure do |config|
|
41
|
+
vcr_cassette_name_for = lambda do |metadata|
|
42
|
+
description = metadata[:description]
|
43
|
+
|
44
|
+
if example_group = metadata[:example_group]
|
45
|
+
[vcr_cassette_name_for[example_group], description].join('/')
|
46
|
+
else
|
47
|
+
description
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
config.around(:each, :vcr => lambda { |v| !!v }) do |example|
|
52
|
+
options = example.metadata[:vcr]
|
53
|
+
options = {} unless options.is_a?(Hash) # in case it's just :vcr => true
|
54
|
+
|
55
|
+
cassette_name = options.delete(:cassette_name) ||
|
56
|
+
vcr_cassette_name_for[example.metadata]
|
57
|
+
|
58
|
+
VCR.use_cassette(cassette_name, options, &example)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
35
63
|
end
|
36
64
|
end
|
37
65
|
|
data/lib/vcr/util/hooks.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'vcr/util/variable_args_block_caller'
|
2
|
+
|
1
3
|
module VCR
|
2
4
|
module Hooks
|
3
5
|
include VariableArgsBlockCaller
|
@@ -6,8 +8,12 @@ module VCR
|
|
6
8
|
klass.extend(ClassMethods)
|
7
9
|
end
|
8
10
|
|
9
|
-
def invoke_hook(hook,
|
10
|
-
|
11
|
+
def invoke_hook(hook, *args)
|
12
|
+
invoke_tagged_hook(hook, nil, *args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def invoke_tagged_hook(hook, tag, *args)
|
16
|
+
hooks_for(hook, tag).map do |callback|
|
11
17
|
call_block(callback, *args)
|
12
18
|
end
|
13
19
|
end
|
@@ -34,7 +40,9 @@ module VCR
|
|
34
40
|
end
|
35
41
|
|
36
42
|
module ClassMethods
|
37
|
-
def define_hook(hook)
|
43
|
+
def define_hook(hook, prepend = false)
|
44
|
+
placement_method = prepend ? :unshift : :<<
|
45
|
+
|
38
46
|
# We use splat args here because 1.8.7 doesn't allow default
|
39
47
|
# values for block arguments, so we have to fake it.
|
40
48
|
define_method hook do |*args, &block|
|
@@ -43,7 +51,7 @@ module VCR
|
|
43
51
|
end
|
44
52
|
|
45
53
|
tag = args.first
|
46
|
-
hooks[hook][tag]
|
54
|
+
hooks[hook][tag].send(placement_method, block)
|
47
55
|
end
|
48
56
|
end
|
49
57
|
end
|