在 class 定义之外调用私有方法
Call Private methods outside class definition
我正在尝试使用 Gem 为我提供 DSL,我需要在我的某些 classes 上应用。但是直接使用它会使我的 class 定义不像我希望的那样干净,所以我想将使用 DSL 的代码移到其他地方,这让我遇到了这个问题,我将在 abstract/general方式:
如果我有一个 ruby class 包含来自另一个 gem 的私有方法,并且在文档中他们告诉我在 class 定义中调用这些方法。
例如:
class A
include ModuleB::PrivateMethods
end
class B < A
do_z :param do
set_property 'a', :x, :y, false
set_property 'b', :x, :y, false
set_property 'only for class B', :x, :y, true
end
def whatever
end
end
# this is from the gem
module ModuleZ
module PrivateMethods
def self.included(base)
base.extend Zmethods
end
module Zmethods
private
def do_z(param1, &block)
# this method do something and calls the block
end
end
end
end
有没有办法干掉对 do_z 的那些调用,例如
任何继承自 A 的 class 都必须这样做:
do_z :param do
set_property 'a', :x, :y, false
set_property 'b', :x, :y, false
end
和
do_z :param do
set_property 'only for class B', :x, :y, true
end
仅 class B 需要,我不想在 class 定义中编写此调用,而是在其他地方?
就像另一个模块一样,当包含时即使这些方法是私有的,也会进行这些调用?
所以我可以这样写 class 定义?
class B < A
include TheModuleForAllClases::AndTheOneForBclass
def whatever
end
end
我可以在基础 class 上调用#do_z,然后再为每个专门的 class 调用一次,以便只在每个实现上进行所需的调用,但它们仍然很多而且这些块非常大,所以我的 class 定义变得很长,class 的实际方法实现被隐藏在这些调用之后。
如果想知道,Gem 是 Rails 上的 swagger-docs look: documenting-a-controller。
您好!
像这样的东西应该可以工作
module AllClassesMethods
def self.included(base)
base.class_eval do
do_z :param do
set_property 'a', :x, :y, false
set_property 'b', :x, :y, false
end
end
end
end
module OnlyBMethods
def self.included(base)
base.class_eval do
do_z :param do
set_property 'only for class B', :x, :y, true
end
end
end
end
class A
include ModuleB::PrivateMethods
include AllClassesMethods
def self.inherited(klass)
klass.include AllClassesMethods
end
end
class B < A
include OnlyBMethods
end
A
和任何继承自 A
的 class 将在其 included
方法中包含 AllClassesMethods
、运行 代码。它必须显式包含在每个继承的 class 中,否则 included
方法只会被父 A
调用。 class_eval
块在包含 class 的上下文中执行,因此它就像在 class 定义中打开 class 一样。只有 B
包含 OnlyBMethods
,因此是唯一触发两个模块的 included
实现的模块。
您可以使用另一种方法。如果您在 extend
ed 模块中定义一个 class 方法宏,class 方法将在 class 上下文中执行,同时让您轻松访问它的私有方法(我说 "easy" 访问是因为在 Ruby 中,您始终可以使用 send
)
从任何上下文访问对象的私有方法
module AllClassesMethods
def does_z
do_z :param do
set_property 'a', :x, :y, false
set_property 'b', :x, :y, false
end
end
def does_z_for_b
do_z :param do
set_property 'only for class B', :x, :y, true
end
end
end
class A
include ModuleB::PrivateMethods
extend AllClassesMethods
does_z
def self.inherited(klass)
klass.does_z
end
end
class B < A
does_z_for_b
end
使用发送方法
obj = SomeClass.new
obj.send(:private_method)
我正在尝试使用 Gem 为我提供 DSL,我需要在我的某些 classes 上应用。但是直接使用它会使我的 class 定义不像我希望的那样干净,所以我想将使用 DSL 的代码移到其他地方,这让我遇到了这个问题,我将在 abstract/general方式:
如果我有一个 ruby class 包含来自另一个 gem 的私有方法,并且在文档中他们告诉我在 class 定义中调用这些方法。
例如:
class A
include ModuleB::PrivateMethods
end
class B < A
do_z :param do
set_property 'a', :x, :y, false
set_property 'b', :x, :y, false
set_property 'only for class B', :x, :y, true
end
def whatever
end
end
# this is from the gem
module ModuleZ
module PrivateMethods
def self.included(base)
base.extend Zmethods
end
module Zmethods
private
def do_z(param1, &block)
# this method do something and calls the block
end
end
end
end
有没有办法干掉对 do_z 的那些调用,例如 任何继承自 A 的 class 都必须这样做:
do_z :param do
set_property 'a', :x, :y, false
set_property 'b', :x, :y, false
end
和
do_z :param do
set_property 'only for class B', :x, :y, true
end
仅 class B 需要,我不想在 class 定义中编写此调用,而是在其他地方?
就像另一个模块一样,当包含时即使这些方法是私有的,也会进行这些调用?
所以我可以这样写 class 定义?
class B < A
include TheModuleForAllClases::AndTheOneForBclass
def whatever
end
end
我可以在基础 class 上调用#do_z,然后再为每个专门的 class 调用一次,以便只在每个实现上进行所需的调用,但它们仍然很多而且这些块非常大,所以我的 class 定义变得很长,class 的实际方法实现被隐藏在这些调用之后。
如果想知道,Gem 是 Rails 上的 swagger-docs look: documenting-a-controller。
您好!
像这样的东西应该可以工作
module AllClassesMethods
def self.included(base)
base.class_eval do
do_z :param do
set_property 'a', :x, :y, false
set_property 'b', :x, :y, false
end
end
end
end
module OnlyBMethods
def self.included(base)
base.class_eval do
do_z :param do
set_property 'only for class B', :x, :y, true
end
end
end
end
class A
include ModuleB::PrivateMethods
include AllClassesMethods
def self.inherited(klass)
klass.include AllClassesMethods
end
end
class B < A
include OnlyBMethods
end
A
和任何继承自 A
的 class 将在其 included
方法中包含 AllClassesMethods
、运行 代码。它必须显式包含在每个继承的 class 中,否则 included
方法只会被父 A
调用。 class_eval
块在包含 class 的上下文中执行,因此它就像在 class 定义中打开 class 一样。只有 B
包含 OnlyBMethods
,因此是唯一触发两个模块的 included
实现的模块。
您可以使用另一种方法。如果您在 extend
ed 模块中定义一个 class 方法宏,class 方法将在 class 上下文中执行,同时让您轻松访问它的私有方法(我说 "easy" 访问是因为在 Ruby 中,您始终可以使用 send
)
module AllClassesMethods
def does_z
do_z :param do
set_property 'a', :x, :y, false
set_property 'b', :x, :y, false
end
end
def does_z_for_b
do_z :param do
set_property 'only for class B', :x, :y, true
end
end
end
class A
include ModuleB::PrivateMethods
extend AllClassesMethods
does_z
def self.inherited(klass)
klass.does_z
end
end
class B < A
does_z_for_b
end
使用发送方法
obj = SomeClass.new
obj.send(:private_method)