用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
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!  | 
                  
