mirage-on-thin 3.0.8
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.
- checksums.yaml +7 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.simplecov +6 -0
- data/.travis.yml +3 -0
- data/Gemfile +29 -0
- data/Gemfile.lock +151 -0
- data/HISTORY +22 -0
- data/README.md +156 -0
- data/Rakefile +10 -0
- data/VERSION +1 -0
- data/bin/mirage +14 -0
- data/features/.nav +29 -0
- data/features/client/clear.feature +78 -0
- data/features/client/configure.feature +72 -0
- data/features/client/model.feature +95 -0
- data/features/client/preview_responses.feature +33 -0
- data/features/client/prime.feature +32 -0
- data/features/client/put.feature +111 -0
- data/features/client/readme.md +3 -0
- data/features/client/requests.feature +20 -0
- data/features/client/running.feature +51 -0
- data/features/client/save_and_revert.feature +39 -0
- data/features/client/start.feature +46 -0
- data/features/client/stop.feature +53 -0
- data/features/commandline_interface/help.feature +17 -0
- data/features/commandline_interface/readme.md +1 -0
- data/features/commandline_interface/start.feature +18 -0
- data/features/commandline_interface/stop.feature +42 -0
- data/features/logging.feature +6 -0
- data/features/prime.feature +35 -0
- data/features/readme.md +7 -0
- data/features/requests/delete.feature +48 -0
- data/features/requests/get.feature +36 -0
- data/features/save_and_revert.feature +35 -0
- data/features/step_definitions/my_steps.rb +98 -0
- data/features/step_definitions/observation_steps.rb +103 -0
- data/features/support/command_line.rb +33 -0
- data/features/support/env.rb +22 -0
- data/features/support/hooks.rb +26 -0
- data/features/support/mirage.rb +12 -0
- data/features/support/web.rb +20 -0
- data/features/templates/delete.feature +45 -0
- data/features/templates/get.feature +54 -0
- data/features/templates/path_wildcards.feature +10 -0
- data/features/templates/preview.feature +18 -0
- data/features/templates/put.feature +77 -0
- data/features/templates/put_with_substitutions.feature +22 -0
- data/features/templates/readme.md +4 -0
- data/features/templates/required_content.feature +113 -0
- data/features/web_user_interface.feature +44 -0
- data/full_build.sh +100 -0
- data/lib/mirage/client.rb +10 -0
- data/lib/mirage/client/cli_bridge.rb +30 -0
- data/lib/mirage/client/client.rb +73 -0
- data/lib/mirage/client/error.rb +22 -0
- data/lib/mirage/client/helpers/method_builder.rb +19 -0
- data/lib/mirage/client/request.rb +26 -0
- data/lib/mirage/client/requests.rb +13 -0
- data/lib/mirage/client/runner.rb +103 -0
- data/lib/mirage/client/template.rb +56 -0
- data/lib/mirage/client/template/configuration.rb +44 -0
- data/lib/mirage/client/template/model.rb +48 -0
- data/lib/mirage/client/template/model/common_methods.rb +24 -0
- data/lib/mirage/client/template/model/instance_methods.rb +95 -0
- data/lib/mirage/client/templates.rb +50 -0
- data/mirage-on-thin.gemspec +175 -0
- data/mirage_server.rb +35 -0
- data/server/app.rb +4 -0
- data/server/binary_data_checker.rb +15 -0
- data/server/extensions/hash.rb +10 -0
- data/server/extensions/object.rb +5 -0
- data/server/helpers.rb +3 -0
- data/server/helpers/http_headers.rb +31 -0
- data/server/helpers/template_requirements.rb +33 -0
- data/server/mock_response.rb +242 -0
- data/server/server.rb +184 -0
- data/spec/client/cli_bridge_spec.rb +63 -0
- data/spec/client/client_spec.rb +179 -0
- data/spec/client/helpers/method_builder_spec.rb +40 -0
- data/spec/client/request_spec.rb +39 -0
- data/spec/client/requests_spec.rb +9 -0
- data/spec/client/runner_spec.rb +138 -0
- data/spec/client/template/configuration_spec.rb +32 -0
- data/spec/client/template/model/common_methods_spec.rb +25 -0
- data/spec/client/template/model/instance_methods_spec.rb +169 -0
- data/spec/client/template/model_spec.rb +119 -0
- data/spec/client/template_spec.rb +146 -0
- data/spec/client/templates_spec.rb +197 -0
- data/spec/resources/binary.file +0 -0
- data/spec/server/binary_data_checker_spec.rb +21 -0
- data/spec/server/helpers/http_headers_spec.rb +20 -0
- data/spec/server/helpers/template_requirements_spec.rb +34 -0
- data/spec/server/mock_response_spec.rb +577 -0
- data/spec/server/server_spec.rb +156 -0
- data/spec/spec_helper.rb +85 -0
- data/tasks/application.rake +7 -0
- data/tasks/packaging.rake +28 -0
- data/tasks/tests.rake +25 -0
- data/views/index.haml +16 -0
- data/views/response.haml +46 -0
- metadata +337 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Mirage
|
|
2
|
+
class MirageError < ::Exception
|
|
3
|
+
attr_reader :code
|
|
4
|
+
|
|
5
|
+
def initialize message, code
|
|
6
|
+
super message
|
|
7
|
+
@code = message, code
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class InternalServerException < MirageError
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class TemplateNotFound < ::Exception
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class ClientError < ::Exception
|
|
18
|
+
def initialize message
|
|
19
|
+
super message
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Mirage
|
|
2
|
+
module Helpers
|
|
3
|
+
module MethodBuilder
|
|
4
|
+
def builder_methods *method_names
|
|
5
|
+
|
|
6
|
+
method_names.each do |method_name|
|
|
7
|
+
method_name = method_name.to_sym
|
|
8
|
+
define_method method_name do |arg=nil|
|
|
9
|
+
return instance_variable_get("@#{method_name}".to_sym) if arg.nil?
|
|
10
|
+
instance_variable_set("@#{method_name}".to_sym, arg)
|
|
11
|
+
self
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
alias builder_method builder_methods
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'hashie/mash'
|
|
2
|
+
module Mirage
|
|
3
|
+
class Request
|
|
4
|
+
include HTTParty
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
alias_method :backedup_get, :get
|
|
8
|
+
def get url
|
|
9
|
+
result = Hashie::Mash.new(backedup_get(url, format: :json))
|
|
10
|
+
request = new
|
|
11
|
+
request.parameters = result.parameters
|
|
12
|
+
request.headers = result.headers
|
|
13
|
+
request.request_url = result.request_url
|
|
14
|
+
request.body = result.body
|
|
15
|
+
request.id = result.id
|
|
16
|
+
request
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
attr_accessor :parameters, :headers, :body, :request_url, :id
|
|
21
|
+
|
|
22
|
+
def delete
|
|
23
|
+
self.class.delete(id)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require 'thor'
|
|
2
|
+
require 'waitforit'
|
|
3
|
+
require 'childprocess'
|
|
4
|
+
require 'uri'
|
|
5
|
+
require 'httparty'
|
|
6
|
+
module Mirage
|
|
7
|
+
class << self
|
|
8
|
+
|
|
9
|
+
# Start Mirage locally on a given port
|
|
10
|
+
# Example Usage:
|
|
11
|
+
#
|
|
12
|
+
# Mirage.start :port => 9001 -> Configured MirageClient ready to use.
|
|
13
|
+
def start options={}
|
|
14
|
+
options={:port => 7001}.merge(options)
|
|
15
|
+
Runner.new.invoke(:start, [], options)
|
|
16
|
+
Mirage::Client.new(options)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Stop locally running instance(s) of Mirage
|
|
20
|
+
#
|
|
21
|
+
# Example Usage:
|
|
22
|
+
# Mirage.stop -> Will stop mirage if there is only instance running. Can be running on any port.
|
|
23
|
+
# Mirage.stop :port => port -> stop mirage on a given port
|
|
24
|
+
# Mirage.stop :port => [port1, port2...] -> stops multiple running instances of Mirage
|
|
25
|
+
def stop options={:port => []}
|
|
26
|
+
options = {:port => :all} if options == :all
|
|
27
|
+
|
|
28
|
+
if options[:port]
|
|
29
|
+
options[:port] = [options[:port]] unless options[:port].is_a?(Array)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Runner.new.invoke(:stop, [], options)
|
|
33
|
+
rescue ClientError => e
|
|
34
|
+
raise ClientError.new("Mirage is running multiple ports, please specify the port(s) see api/tests for details")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Detect if Mirage is running on a URL or a local port
|
|
39
|
+
#
|
|
40
|
+
# Example Usage:
|
|
41
|
+
# Mirage.running? -> boolean indicating whether Mirage is running on *locally* on port 7001
|
|
42
|
+
# Mirage.running? :port => port -> boolean indicating whether Mirage is running on *locally* on the given port
|
|
43
|
+
# Mirage.running? url -> boolean indicating whether Mirage is running on the given URL
|
|
44
|
+
def running? options_or_url = {:port => 7001}
|
|
45
|
+
url = options_or_url.kind_of?(Hash) ? "http://localhost:#{options_or_url[:port]}" : options_or_url
|
|
46
|
+
HTTParty.get(url) and return true
|
|
47
|
+
rescue Errno::ECONNREFUSED
|
|
48
|
+
return false
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class Runner < Thor
|
|
54
|
+
include CLIBridge
|
|
55
|
+
RUBY_CMD = ChildProcess.jruby? ? 'jruby' : 'ruby'
|
|
56
|
+
|
|
57
|
+
desc "start", "Starts mirage"
|
|
58
|
+
method_option :port, :aliases => "-p", :type => :numeric, :default => 7001, :desc => "port that mirage should be started on"
|
|
59
|
+
method_option :defaults, :aliases => "-d", :type => :string, :default => 'mirage', :desc => "location to load default responses from"
|
|
60
|
+
method_option :debug, :type => :boolean, :default => false, :desc => "run in debug mode"
|
|
61
|
+
|
|
62
|
+
def start
|
|
63
|
+
port = options[:port]
|
|
64
|
+
process_ids = mirage_process_ids([port])
|
|
65
|
+
unless process_ids.empty?
|
|
66
|
+
warn "Mirage is already running: #{process_ids.values.join(",")}"
|
|
67
|
+
return
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
mirage_server_file = "#{File.dirname(__FILE__)}/../../../mirage_server.rb"
|
|
71
|
+
|
|
72
|
+
if ChildProcess.windows?
|
|
73
|
+
command = ["cmd", "/C", "start", "mirage server port #{port}", RUBY_CMD, mirage_server_file]
|
|
74
|
+
else
|
|
75
|
+
command = [RUBY_CMD, mirage_server_file]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
command = command.concat(options.to_a).flatten.collect { |arg| arg.to_s }
|
|
80
|
+
ChildProcess.build(*command).start
|
|
81
|
+
|
|
82
|
+
wait_until(:timeout_after => 30.seconds) { Mirage.running?(options) }
|
|
83
|
+
|
|
84
|
+
begin
|
|
85
|
+
Mirage::Client.new(options).prime
|
|
86
|
+
rescue Mirage::InternalServerException => e
|
|
87
|
+
puts "WARN: #{e.message}"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
desc "stop", "Stops mirage"
|
|
92
|
+
method_option :port, :aliases => "-p", :type => :array, :default => [], :banner => "[port_1 port_2|all]", :desc => "port(s) of mirage instance(s). ALL stops all running instances"
|
|
93
|
+
|
|
94
|
+
def stop
|
|
95
|
+
ports = options[:port].collect{|port| port=~/\d+/ ? port.to_i : port}
|
|
96
|
+
process_ids = mirage_process_ids(ports)
|
|
97
|
+
raise ClientError.new("Mirage is running on ports #{process_ids.keys.sort.join(", ")}. Please run mirage stop -p [PORT(s)] instead") if (process_ids.size > 1 && ports.empty?)
|
|
98
|
+
process_ids.values.each { |process_id| kill process_id }
|
|
99
|
+
wait_until { mirage_process_ids(options[:port]).empty? }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'ostruct'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'httparty'
|
|
4
|
+
require 'hashie/mash'
|
|
5
|
+
|
|
6
|
+
require 'client/template/configuration'
|
|
7
|
+
require 'client/template/model'
|
|
8
|
+
|
|
9
|
+
module Mirage
|
|
10
|
+
|
|
11
|
+
class Template
|
|
12
|
+
|
|
13
|
+
include HTTParty
|
|
14
|
+
include Model::InstanceMethods
|
|
15
|
+
include Model::CommonMethods
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
alias_method :backedup_get, :get
|
|
19
|
+
|
|
20
|
+
def get url
|
|
21
|
+
response = backedup_get(url, :format => :json)
|
|
22
|
+
raise TemplateNotFound if response.code == 404
|
|
23
|
+
response_hashie = Hashie::Mash.new response
|
|
24
|
+
|
|
25
|
+
response_config = response_hashie.response
|
|
26
|
+
request_config = response_hashie.request
|
|
27
|
+
|
|
28
|
+
template = new(response_hashie.endpoint, Base64.decode64(response_config.body))
|
|
29
|
+
|
|
30
|
+
template.id response_hashie.id
|
|
31
|
+
template.default response_config['default']
|
|
32
|
+
template.delay response_config.delay
|
|
33
|
+
template.content_type response_config.content_type
|
|
34
|
+
template.status response_config.status
|
|
35
|
+
template.headers response_config.headers
|
|
36
|
+
|
|
37
|
+
template.required_parameters request_config.parameters
|
|
38
|
+
template.required_body_content request_config.body_content
|
|
39
|
+
template.http_method request_config.http_method
|
|
40
|
+
template.url url
|
|
41
|
+
template.requests_url response_hashie.requests_url
|
|
42
|
+
template.required_headers request_config.headers
|
|
43
|
+
|
|
44
|
+
template
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def initialize *args
|
|
49
|
+
endpoint = args.first
|
|
50
|
+
|
|
51
|
+
raise ArgumentError, "You must specify a string endpoint as the first argument" unless endpoint && endpoint.is_a?(String)
|
|
52
|
+
super *args
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require 'client/helpers/method_builder'
|
|
2
|
+
|
|
3
|
+
module Mirage
|
|
4
|
+
class Template
|
|
5
|
+
class Configuration
|
|
6
|
+
extend Helpers::MethodBuilder
|
|
7
|
+
builder_methods :http_method, :status, :delay, :content_type, :default
|
|
8
|
+
attr_accessor :caller_binding
|
|
9
|
+
DEFAULT_HTTP_METHOD=:get
|
|
10
|
+
DEFAULT_STATUS=200
|
|
11
|
+
DEFAULT_DELAY=0
|
|
12
|
+
DEFAULT_CONTENT_TYPE="text/plain"
|
|
13
|
+
DEFAULT_DEFAULT=false
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
reset
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def reset
|
|
20
|
+
@http_method = DEFAULT_HTTP_METHOD
|
|
21
|
+
@status = DEFAULT_STATUS
|
|
22
|
+
@delay = DEFAULT_DELAY
|
|
23
|
+
@content_type = DEFAULT_CONTENT_TYPE
|
|
24
|
+
@default = DEFAULT_DEFAULT
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def method_missing(method, *args, &block)
|
|
29
|
+
@caller_binding.send method, *args, &block if @caller_binding
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def == config
|
|
33
|
+
config.is_a?(Configuration) &&
|
|
34
|
+
http_method == config.http_method &&
|
|
35
|
+
status == config.status &&
|
|
36
|
+
delay == config.delay &&
|
|
37
|
+
content_type == config.content_type &&
|
|
38
|
+
default == config.default
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'client/helpers/method_builder'
|
|
2
|
+
require 'client/template/model/common_methods'
|
|
3
|
+
require 'client/template/model/instance_methods'
|
|
4
|
+
|
|
5
|
+
module Mirage
|
|
6
|
+
class Template
|
|
7
|
+
module Model
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def extended clazz
|
|
11
|
+
clazz.extend(CommonMethods)
|
|
12
|
+
clazz.extend(Helpers::MethodBuilder)
|
|
13
|
+
clazz.send(:include, HTTParty)
|
|
14
|
+
clazz.send(:include, CommonMethods)
|
|
15
|
+
clazz.send(:include, InstanceMethods)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
mod = Module.new do
|
|
19
|
+
def initialize *args
|
|
20
|
+
|
|
21
|
+
super *args
|
|
22
|
+
[:content_type,
|
|
23
|
+
:http_method,
|
|
24
|
+
:default,
|
|
25
|
+
:status,
|
|
26
|
+
:delay,
|
|
27
|
+
:required_parameters,
|
|
28
|
+
:required_body_content,
|
|
29
|
+
:required_headers,
|
|
30
|
+
:headers,
|
|
31
|
+
:endpoint, :delay].each do |attribute|
|
|
32
|
+
eval("#{attribute} self.class.#{attribute} if self.class.#{attribute}")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
clazz.send(:include, mod)
|
|
40
|
+
|
|
41
|
+
clazz.format :json
|
|
42
|
+
clazz
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Mirage
|
|
2
|
+
|
|
3
|
+
class Template
|
|
4
|
+
module Model
|
|
5
|
+
module CommonMethods
|
|
6
|
+
extend Helpers::MethodBuilder
|
|
7
|
+
|
|
8
|
+
builder_methods :content_type,
|
|
9
|
+
:http_method,
|
|
10
|
+
:default,
|
|
11
|
+
:status,
|
|
12
|
+
:delay,
|
|
13
|
+
:required_parameters,
|
|
14
|
+
:required_body_content,
|
|
15
|
+
:required_headers,
|
|
16
|
+
:headers,
|
|
17
|
+
:endpoint,
|
|
18
|
+
:body
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module Mirage
|
|
2
|
+
class Template
|
|
3
|
+
module Model
|
|
4
|
+
module InstanceMethods
|
|
5
|
+
extend Helpers::MethodBuilder
|
|
6
|
+
include CommonMethods
|
|
7
|
+
|
|
8
|
+
attr_accessor :caller_binding
|
|
9
|
+
|
|
10
|
+
def initialize *args
|
|
11
|
+
if args.last.is_a?(Template::Configuration)
|
|
12
|
+
default_config = args.delete_at(-1)
|
|
13
|
+
else
|
|
14
|
+
default_config = Template::Configuration.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
@endpoint, @body = *args
|
|
18
|
+
@content_type = default_config.content_type
|
|
19
|
+
@http_method = default_config.http_method
|
|
20
|
+
@status = default_config.status
|
|
21
|
+
@delay = default_config.delay
|
|
22
|
+
@required_parameters = {}
|
|
23
|
+
@required_headers = {}
|
|
24
|
+
@required_body_content = []
|
|
25
|
+
@headers = {}
|
|
26
|
+
@default = default_config.default
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
builder_method :id,
|
|
30
|
+
:url,
|
|
31
|
+
:requests_url
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def create
|
|
35
|
+
@id = self.class.put("#{@endpoint}", :body => self.to_json, :headers => {'content-type' => 'application/json'})['id']
|
|
36
|
+
self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def delete
|
|
40
|
+
self.class.delete(url)
|
|
41
|
+
Request.delete requests_url
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def to_json
|
|
46
|
+
{
|
|
47
|
+
:response => {
|
|
48
|
+
:body => Base64.encode64(body),
|
|
49
|
+
:status => status,
|
|
50
|
+
:default => default,
|
|
51
|
+
:content_type => content_type,
|
|
52
|
+
:headers => headers,
|
|
53
|
+
:delay => delay
|
|
54
|
+
},
|
|
55
|
+
:request => {
|
|
56
|
+
:parameters => encode_regexs(required_parameters),
|
|
57
|
+
:headers => encode_regexs(required_headers),
|
|
58
|
+
:body_content => encode_regexs(required_body_content),
|
|
59
|
+
:http_method => http_method,
|
|
60
|
+
}
|
|
61
|
+
}.to_json
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def encode_regexs hash_or_array
|
|
66
|
+
case hash_or_array
|
|
67
|
+
when Array
|
|
68
|
+
hash_or_array.collect { |value| encode(value) }
|
|
69
|
+
else
|
|
70
|
+
encoded = {}
|
|
71
|
+
hash_or_array.each do |key, value|
|
|
72
|
+
encoded[key] = encode(value)
|
|
73
|
+
end
|
|
74
|
+
encoded
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def encode(value)
|
|
79
|
+
value.is_a?(Regexp) ? "%r{#{value.source}}" : value
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def method_missing(method, *args, &block)
|
|
83
|
+
|
|
84
|
+
if @caller_binding
|
|
85
|
+
@caller_binding.send method, *args, &block
|
|
86
|
+
else
|
|
87
|
+
super method, *args, &block
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|