我在ROR应用程序中有一个用户模型,它有多个像这样的方法
#getClient() returns an object that knows how to find certain info for a date
#processHeaders() is a function that processes output and updates some values in the database
#refreshToken() is function that is called when an error occurs when requesting data from the object returned by getClient()
def transactions_on_date(date)
if blocked?
# do something
else
begin
output = getClient().transactions(date)
processHeaders(output)
return output
rescue UnauthorizedError => ex
refresh_token()
output = getClient().transactions(date)
process_fitbit_rate_headers(output)
return output
end
end
end
def events_on_date(date)
if blocked?
# do something
else
begin
output = getClient().events(date)
processHeaders(output)
return output
rescue UnauthorizedError => ex
refresh_token()
output = getClient().events(date)
processHeaders(output)
return output
end
end
end
我的User类中有几个看起来完全相同的函数。这些函数之间的唯一区别是行output = getClient().something(date)
。有没有办法让我的代码看起来更干净,这样我就没有重复的函数列表。
答案 0 :(得分:3)
答案通常是在一个块中传递并执行功能样式:
def handle_blocking(date)
if blocked?
# do something
else
begin
output = yield(date)
processHeaders(output)
output
rescue UnauthorizedError => ex
refresh_token
output = yield(date)
process_fitbit_rate_headers(output)
output
end
end
end
然后你这样称呼它:
handle_blocking(date) do |date|
getClient.something(date)
end
这允许大量的自定义。 yield
调用会执行您提供的代码块,并将date
参数传递给它。
干燥代码的过程通常包括寻找模式并将其归结为有用的方法。使用功能方法可以保持清洁。
答案 1 :(得分:2)
是的,您可以使用Object#send
:getClient().send(:method_name, date)
。
BTW,getClient
不是正确的Ruby方法名称。它应该是get_client
。
答案 2 :(得分:0)
两个答案的组合怎么样:
class User
def method_missing sym, *args
m_name = sym.to_s
if m_name.end_with? '_on_date'
prop = m_name.split('_').first.to_sym
handle_blocking(args.first) { getClient().send(prop, args.first) }
else
super(sym, *args)
end
end
def respond_to? sym, private=false
m_name.end_with?('_on_date') || super(sym, private)
end
def handle_blocking date
# see other answer
end
end
然后你可以调用“transaction_on_date”,“events_on_date”,“foo_on_date”,它会起作用。