我有一个方法mock_request
,我为了单元测试目的而凌驾于此。对于每个请求,我想执行一些代码:
def mock_request(method, url, params={})
case "#{method} #{url}"
when 'post /customers'
# create customer
when %r{post /customers/(.*)/items}
id = $1 # update customer
when %r{post /customers/(.*)}
id = $1 # update customer
else
throw 'Unrecognized request'
end
end
问题是这个案例陈述变得很长,每个案例的行数都在缓慢增加。此外,一些模型正在同时处理。
我想要做的是为每个模型提供单独的文件,并以某种方式包含它们以用于此mock_request
方法。像这样:
# handlers/customers.rb
module RequestHandlers
# post /customers
# post /customers/(.*)
end
# handlers/items.rb
module RequestHandlers
# post /customers/(.*)/items
end
# mock_request.rb
class MockServer
def mock_request(method, url, params={})
handle_request(method, url)
end
end
但是我不确定如何实现这一点。在红宝石中处理这个问题的最佳方法是什么?
答案 0 :(得分:1)
您可以创建一个哈希,其中包含方法和URL字符串作为您的键,以及您要作为值评估的代码块。
def mock_request(method, url, params={})
#create a request hash where the default value is your else, this way if a key that doesn't exist is called, the unrecognized request is called
req = Hash.new ({throw 'Unrecognized request'})
req['post /customers'] = {#create customer block/proc}
req[%r{post /customers/(.*)/items}] = {#update customer block/proc}
req["#{method} #{url}"]
end
对于您来说,这可能是一个更好的选择,并且可以摆脱冗长的案例陈述。
答案 1 :(得分:0)
为了记录,这是我最终如何重构它。
处理程序的每个“主题”都有自己的模块和文件:
module RequestHandlers
module Customers
def Customers.included(mock_server)
mock_server.add_handler 'post /customers', :new_customer
mock_server.add_handler 'post /customers/(.*)', :update_customer
end
def new_customer(route, method_url, params)
# create new customer
end
def update_customer(route, method_url, params)
# update existing customer
end
end
end
主要类是处理程序生存和使用的地方:
class MockServer
# Handlers are ordered by priority
@@handlers = []
include RequestHandlers::Customers
include RequestHandlers::Items
# etc.
def self.add_handler(route, name)
@@handlers << {
:route => %r{^#{route}$},
:name => name
}
end
def mock_request(method, url, params={})
method_url = "#{method} #{url}"
handler = @@handlers.find {|h| method_url =~ h[:route] }
if handler
self.send(handler[:name], handler[:route], method_url, params)
else
throw 'Unrecognized request'
end
end
end