ruby - Ruby 动态方法调用的问题
问题描述
我正在 Elasticsearch 的 Ruby API 之上构建一些东西,并且有许多几乎相同的函数的常见 API 问题,这些函数实现对底层 API 的调用并执行错误处理。所以我想要一种方法来执行与调用底层 API 相关的杂乱内容:
def perform_api_request( method, params )
api_method = "#{@method_prefix}#{method}"
puts api_method
begin
r = @es_conn.client.send(api_method, params )
rescue => e
abort "there were errors calling #{method}:#{e}" unless extract_error(e)
return false
end
return true
end
我正在调用:
perform_api_request 'delete_template', { name: @name }
这输出:
indices.delete_template
there were errors calling delete_template:undefined method \
`indices.delete_template' for #<Elasticsearch::Transport::Client:0x0000000282d758>
我已经尝试过self.send
各种其他方法,但我无法让它发挥作用。我所有的努力都导致了“未定义的方法”。
有人可以指出我缺少什么吗?
解决方案
你可以这样做:
r = api_method.split('.').inject(@es_conn.client) { |obj, m| obj.public_send(m) }
如果你想支持任意方法链。这将允许您在@method_prefix
和中需要任何点method
。如果您也想允许私有方法,那么:
r = api_method.split('.').inject(@es_conn.client) { |obj, m| obj.send(m) }
这假设您正在控制一切,并且不允许在@method_prefix
or中进行任何类型的外部输入method
;如果您允许外部输入,那么您真的希望将所有内容列入白名单以避免调用意外和危险的方法。
编辑:如果您需要将参数传递给最终调用,您需要执行以下操作:
api_method = "#{@method_prefix}#{method}".split('.')
last = api_method[-1]
r = api_method.inject(@es_conn.client) do |obj, m|
m == last ? obj.public_send(m, params) : obj.public_send(m)
end
将参数添加到最终调用中。可能有一种更优雅的方式来做到这一点;)
推荐阅读
- reactjs - 限制导航以防止浏览器在 React App 中挂起
- react-native - 反应原生图像,动态需求
- javascript - 如何识别代码中的哪个 java/javascript 文件生成了特定的 cookie?
- sql - 为什么我的插入表格的代码带有错误警告
- android - 如何修复由于资格问题而被谷歌 Play 商店拒绝的 Android 应用程序?
- java - 创建一个包含 10 个整数元素的堆栈,然后添加一个具有函数的元素
- c# - 如何并行调用一些方法并从这些方法中获取信息?
- javascript - 有没有办法让角材料表保持扩大?(带有 tr 和 td,不是 mat-row 标签)
- python - 如何在类装饰器中添加属性?
- wordpress - 在多站点中添加新站点时添加内容时出现问题