我是Ruby新手,来自C#世界.在C#中,做这样的事情是合法的:
public class Test
{
public void Method()
{
PrivateMethod();
}
private void PrivateMethod()
{
PrivateStaticMethod();
}
private static void PrivateStaticMethod()
{
}
}
Run Code Online (Sandbox Code Playgroud)
可以在Ruby中做类似的事情吗?
一点上下文:我有一个Rails应用程序......其中一个模型有一个私有方法来设置一些依赖项.有一个类方法可以创建模型的初始化实例.由于遗留原因,有些模型的实例未正确初始化.我添加了一个实例方法,初始化'未初始化'实例,我想要做同样的初始化逻辑.有没有办法避免重复?
样品:
class MyModel < ActiveRecord::Base
def self.create_instance
model = MyModel.new
model.init_some_dependencies # this fails
model
end
def initialize_instance
// do some other work
other_init
// call private method
init_some_dependencies
end
private
def init_some_dependencies
end
end
Run Code Online (Sandbox Code Playgroud)
我试图将我的私有方法转换为私有类方法,但我仍然得到一个错误:
class MyModel < ActiveRecord::Base
def self.create_instance
model = MyModel.new
MyModel.init_some_dependencies_class(model)
model
end
def initialize_instance
# do some other work
other_init
# call private method
init_some_dependencies
end
private
def init_some_dependencies
MyModel.init_some_dependencies_class(self) # now this fails with exception
end
def self.init_some_dependencies_class(model)
# do something with model
end
private_class_method :init_some_dependencies_class
end
Run Code Online (Sandbox Code Playgroud)
首先让我尝试解释为什么代码不起作用
class MyModel < ActiveRecord::Base
def self.create_instance
model = MyModel.new
# in here, you are not inside of the instance scope, you are outside of the object
# so calling model.somemething can only access public method of the object.
model.init_some_dependencies
...
end
...
Run Code Online (Sandbox Code Playgroud)
您可以使用model.send :init_some_dependencies
. 但我认为在这种情况下可能有更好的解决方案。
我猜这init_some_dependencies
可能包含更多的业务/领域逻辑而不是持久性。这就是为什么我建议将此逻辑提取到“域对象”(或有人称之为服务对象)中的原因。这只是一个包含域逻辑的普通 ruby 对象。
通过这种方式,您可以将持久性逻辑与 ActiveRecord 分开,并将域逻辑与该类分开。因此,您不会膨胀 ActiveRecord 模型。而且您无需 ActiveRecord 即可获得测试域逻辑的好处。这将使您的测试更快。
你可以创建一个文件,比如“lib/MyModelDomain.rb”
class MyModelDomain
attr_accessor :my_model
def initialize(my_model)
@my_model = my_model
end
def init_some_dependencies
my_model.property = 'some value example'
end
end
Run Code Online (Sandbox Code Playgroud)
现在你可以用这个对象说这样的话
class MyModel < ActiveRecord::Base
def self.create_instance
model = MyModel.new
domain = MyModelDomain.new(model)
domain.init_some_dependencies
domain.my_model
end
def initialize_instance
# do some other work
other_init
domain = MyModelDomain.new(self)
domain.init_some_dependencies
end
end
Run Code Online (Sandbox Code Playgroud)
initialize_instance
如果您认为有必要,您可能还想移动
一些深入研究这种模式的资源:
归档时间: |
|
查看次数: |
4293 次 |
最近记录: |