这有点跑题了。因此,如果它不有趣或没有帮助,请提前道歉。
TL;DR:不要将模型知识放在视图中。保持你的控制器瘦。以下是我的做法。
在我当前的项目中,我一直在努力确保我的视图完全不了解系统的其余部分(以减少耦合)。这样,如果您决定更改实现某些东西的方式(例如,current_user.account.name 与 current_user.account_name),那么您不必进入您的视图并进行更改。
每个控制器操作都提供一个@results 哈希,其中包含视图正确呈现所需的所有内容。 @results 哈希的结构本质上是视图和控制器之间的契约。
所以,在我的控制器中,@results 可能看起来像 {current_user: {account: {name: 'foo'}}}。在我看来,我会做类似@results[:current_user][:account][:name] 的事情。我喜欢使用HashWithIndifferentAccess,所以我也可以使用@results['current_user']['account']['name'],而不会出现问题或行为不端。
此外,我一直在将尽可能多的逻辑从控制器转移到服务对象(我称它们为“经理”)。我发现我的经理(他们是 PORO)比控制器更容易测试。所以,我可能有:
# app/controllers/some_controller.rb
class SomeController
def create
@results = SomeManager.create(params)
if @results[:success]
# happy routing
else
# sad routing
end
end
end
现在,我的控制器非常瘦,除了路由之外不包含任何逻辑。他们对我的模型一无所知。 (事实上,几乎我所有的控制器操作看起来都完全一样,基本上都是相同的六行代码。)我喜欢这个,因为它创造了分离。
当然,我需要经理:
#app/managers/some_manager.rb
class SomeManager
class << self
def create(params)
# do stuff that ends up creating the @results hash
# if things went well, the return will include success: true
# if things did not go well, the return will not include a :success key
end
end
end
所以,事实上,@results 的结构是视图和管理器之间的契约,而不是视图和控制器之间的契约。