有一个带有“命名空间”方法的类:
class MyOrder
def add
end
def edit
end
end
class MyCompany
def list
end
end
class MyDriver
def add
end
def edit
end
end
class MyAPI
attr_reader :order, :company, :driver
def initialize
@order = MyOrder.new
@company = MyCompany.new
@driver = MyDriver.new
end
end
我们的想法是将方法分组为几个部分来调用它们:
api = MyApi.new
api.order.add
api.company.list
有没有办法在不创建容器类的情况下对方法进行分组?
答案 0 :(得分:1)
class MyAPI
def initialize
@namespace = []
end
def self.namespace sym
define_method(sym){@namespace.push(sym); self}
end
namespace :order
namespace :company
namespace :driver
def add
case @namespace
when [:order] then ...
when [:driver] then ...
else raise "invalid namespace"
end
@namespace = []
self
end
def edit
case @namespace
when [:order] then ...
when [:driver] then ...
else raise "invalid namespace"
end
@namespace = []
self
end
def list
case @namespace
when [:company] then ...
else raise "invalid namespace"
end
@namespace = []
self
end
end
方法结尾处的self
是让你能够像
MyApi.new.order.add.company.list
如果您不需要这样做,则不需要self
。
答案 1 :(得分:0)
好的,我明白了,请尝试以下方法:
module MyApi
[MyOrder, MyCompany, MyDriver].each do |klass|
names = klass.to_s.scan(/[A-Z][a-z]+/)
funcname = names[1].downcase
define_singleton_method(funcname) do
instance_variable_get("@#{funcname}") ||
instance_variable_set("@#{funcname}", klass.new)
end
end
end
MyApi.order.add
如果您更喜欢order_add,那么:
module MyApi
[MyOrder, MyCompany, MyDriver].each do |klass|
names = klass.to_s.scan(/[A-Z][a-z]+/)
prefix_name = names[1].downcase
klass.public_instance_methods(false).each do |method|
funcname = "#{prefix_name}_#{method}"
define_singleton_method(funcname) do |*args|
@obj = instance_variable_get("@#{prefix_name}") ||
instance_variable_set("@#{prefix_name}", klass.new)
@obj.send(method, *args)
end
end
end
end