我有一个基本的"最佳实践"关于控制器和实例变量的问题。
假设您在控制器中有新的实例变量或更新操作,是否可以通过控制器中的私有方法修改该实例变量?或者该方法是否存在于模型中?
e.g。在下面的这个例子中,我需要循环实例变量的属性,并添加或删除一些东西。例如,如果我使用3层深度的嵌套属性并且必须删除某些属性,请更改它们然后重新添加它们。我知道这可能看起来很奇怪,但是假设它是必要的。
def new
@some_thing = SomeThing.new(:some_params)
do_something_to_inst_var # method call
@some_thing.save
end
private
def do_something_to_inst_var
@some_thing.addresses.each do |address|
# modify it in some way
end
end
或者这是不好的做法?这应该是模型中的方法,应该被称为:
@some_thing.do_something_to_inst_var
OR
我们应该将实例变量显式传递给类似的方法:
def new
@some_thing = SomeThing.new(:some_params)
do_something_to_inst_var(@some_thing) # method call
@some_thing.save
end
private
def do_something_to_inst_var(some_thing)
some_thing.addresses.each do |addresses|
# modify it in some way
end
end
我在这里寻找一些清晰度,如果可能的话,举个例子。我还在学习并试图改进,但我没有找到答案。
答案 0 :(得分:1)
Rails应用程序应该有"thin controllers" and "fat models",原因有两个:
每个对象应该只处理自己的职责。控制器应该只是关于连接Web,模型和视图,这要感谢Rails不需要太多代码。如果控制器方法反复引用同一模型的方法,则它会错误地承担模型责任;我们说它不是cohesive或它有"Feature Envy"。如果模型更改,控制器更有可能必须并行更改。
测试模型比测试控制器更容易。
通过在模型中编写一个方法来修复它,该方法执行特定于模型的工作并在控制器中调用它(第二个选项)。 (最终你的模型会变得太胖,你也必须分解它,但这是另一个故事。)例如:
class SomeThingsController
def new
@some_thing = SomeThing.new(:some_params)
@some_thing.do_something # method call
@some_thing.save
end
end
class SomeThing
def do_something
addresses.each do |address|
# modify it in some way
end
end
end
关于实例变量。
仅在必要时定义它们。据推测,视图中需要您的示例中的那个。
假设一个实例变量完全合理,没有理由不在包含它的类的私有方法中引用它。这就是他们的目的。所以你的第一个选项(直接引用实例变量)比你的第三个选项(传入它)好一点。但是,如上所述,提取模型方法优于其他两个选项。
答案 1 :(得分:1)
在我看来,如果您的控制器只有100行,则可以从私有方法修改@instance_vars
。
想象一下这样一个场景,你的控制器中有500个LOC,经过几个小时的努力,你发现某个私有方法正在修改@intance_var
。
有用的提示:
!
放在method_name!
的末尾,表示它会修改某些内容。特别是当您看到my_private_method!
,!
让您意识到它正在修改某些内容时,此功能非常有用。答案 2 :(得分:1)
还有一个选择:
在控制器中:
def new
@some_thing = SomeThing.new(:some_params)
@some_thing_modified = @some_thing.modify_somehow(params)
@some_thing_modified.save
end
在SomeThing
模型:
def modify_somehow(params)
result = self.clone
# ... modify result ...
return result
end
因为modify_somehow
现在是pure function(假设你不在... modify result ...
部分做任何事情,这会让它变得不纯净),你在这里获得的是Referential transparency 。引用透明性的主要好处是,您可以通过查看其参数来确定要执行的函数/方法调用,并仅通过返回值获取其工作结果,而不是通过side effects。这使您的代码更具可预测性,从而使其更易于理解和调试。
当然有一些缺点:因为您创建了新对象,所以此选项的性能可能较低,而且其替代方案也更加冗长。
函数式编程概念,如引用透明性,在Rails社区中并不常见(可能是因为以OO为中心的Ruby)。但是,如果你想要它,它的优点和缺点就是参考透明度。