Ruby method chain

I want to create an API client that has an interface similar to the active rails entry. I want consumers to be able to chain methods, and after the last method is bound, the client requests a URL based on the methods called. So this is a chaining method with some lazy rating. I looked at Active Recording , but it is very difficult (spawning processes, etc.).

Here is an example of the toy I'm talking about. You can combine as many bar methods as you like before calling get, for example:

puts Foo.bar.bar.get # => 'bar,bar'
puts Foo.bar.bar.bar.get # => 'bar,bar,bar'

I have successfully completed this, but I would not need to call the get method. So I want this:

puts Foo.bar.bar # => 'bar,bar' 

But my current implementation does this:

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 -

+4
2

activerecord, , undefined ( target). , 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 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
+8

A ( , , ) to_s - "" (, puts), " ".

0

Source: https://habr.com/ru/post/1538719/


All Articles