用ruby链接的方法
发布时间:2020-12-17 03:41:04 所属栏目:百科 来源:网络整理
导读:我想构建一个具有类似rails活动记录的接口的API客户端.我希望消费者能够链接方法,并且在最后一个方法被链接之后,客户端基于所调用的方法请求URL.所以它的方法是链接一些懒惰的评估.我查看了 Active Record,但这非常复杂(产卵过程等). 这是我正在谈论的那种事
我想构建一个具有类似rails活动记录的接口的API客户端.我希望消费者能够链接方法,并且在最后一个方法被链接之后,客户端基于所调用的方法请求URL.所以它的方法是链接一些懒惰的评估.我查看了
Active Record,但这非常复杂(产卵过程等).
这是我正在谈论的那种事情的玩具示例.你可以在调用’get’之前将任意数量的’bar’方法链接在一起,如下所示: puts Foo.bar.bar.get # => 'bar,bar' puts Foo.bar.bar.bar.get # => 'bar,bar,bar' 我已经成功实现了这个,但我宁愿不需要调用’get’方法.所以我想要的是: puts Foo.bar.bar # => 'bar,bar' 但我目前的实现是这样做的: puts Foo.bar.bar #=> [:bar,:bar] 我曾想过覆盖像each和to_s这样的数组方法,但我确信有更好的解决方案. 我如何链接方法并知道哪个是最后一个,所以我可以返回类似get方法中返回的字符串? 这是我目前的实施: #!/usr/bin/env ruby class Bar def get(args) # does a request to an API and returns things but this will do for now. args.join(',') end end class Foo < Array def self.bar @q = new @q << :bar @q end def bar self << :bar self end def get Bar.new.get(self) end end 另见:Ruby Challenge – Method chaining and Lazy Evaluation 解决方法
它与activerecord的工作原理是,该关系是数组的包装器,将任何未定义的方法委托给这个内部数组(称为目标).所以你需要的是从BasicObject而不是Object开始:
class Foo < BasicObject 那么你需要创建内部变量,你将委托所有方法: def method_missing(*args,&block) reload! unless loaded? @target.send(*args,&block) end def reload! # your logic to populate target,e.g: @target = @counter @loaded = true end def loaded? !!@loaded end 要链接方法,您的方法需要返回类的新实例,例如: def initialize(counter=0) @counter = counter end def bar _class.new(@counter + 1) end private # BasicObject does not define class method. If you want to wrap your target # completely (like ActiveRecord does before rails 4),you want to delegate it # to @target as well. Still you need to access the instance class to create # new instances. That's the way (if there are any suggestion how to improve it,# please comment!) def _class (class << self; self end).superclass end 现在您可以检查它的实际效果: p Foo.new.bar.bar.bar #=> 3 (f = Foo.new) && nil # '&& nil' added to prevent execution of inspect # object in the console,as it will force @target # to be loaded f.loaded? #=> false puts f #=> 0 f.loaded? #=> true (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |