在rails中拥有胖视图是不是很糟糕?

我有一个RESTful控制器,负责构建许多不同的模型。 这意味着任何给定的视图都需要设置一些变量才能正确呈现。 如果我在控制器中设置这些变量,则必须在可能呈现该视图的不同操作之间复制代码。 例如,渲染Page 1需要5个变量。 如果显示,创建和更新所有渲染该视图,则设置这5个变量的代码将跨这些控制器操作重复。 另一种方法是将所有代码放在视图中。 但那可能变得非常难看:

   

我对这个解决方案犹豫不决,因为视图中有多少代码。 我一直遵循视图中的代码不应该触及数据库的原则。 我喜欢的另一种方法是创建专注于设置变量和渲染视图的私有方法。 所有需要渲染的操作都可以调用此方法。

在我看来,你的所有逻辑应该放在你的控制器,模型,帮助器或库中。 在您的情况下,设置变量应该在您的控制器中完成,而不是在您的视图中。

将逻辑放在合适的位置真是令人感兴趣,因为如果您的代码处于最佳位置,调试,维护或重构您的应用程序将更加容易。

所以,这里有一些想法将你的变量声明放在你的控制器而不重复你的代码:)

before_action(在控制器中)

您可以在控制器中使用before_action 。 它将减少重复的代码。

例如,你可以这样做:

 before_action :set_variables def set_variables @var1 = some_code @var2 = other_code ... end 

您可以使用onlyexcept将before_action限制为仅特定操作

 before_action :set_variables, only: [:index, :edit] 

这将仅在索引和编辑之前调用set_variables

before_action(在application_controller.rb中)

如果要为每个控制器中的所有索引操作添加before_action作为示例,则只需在application_controller.rb中执行before_action。

如果要在特定控制器中跳过此类型的before_action,可以使用skip_before_action方法。

 # application_controller.rb before_action :set_variables, only: :index # specific_controller.rb skip_before_action :set_variables 

还有一件事:模型范围

然后,结束前的最后一件事: Model1.where(some conditions) 。 模型范围怎么样?

您的代码将更易读,更少重复:

 class MyModel < ActiveRecord::Base scope :active, -> { where(is_active: true) } end MyModel.active # equivalent to MyModel.where(is_active: true) 

您可以向控制器添加私有方法,并在操作方法中调用它们:

 class MyController < ApplicationController # snip ... def my_action @variable1 = get_variable1() @variable2 = get_variable2() @variable3 = get_variable3() @action_specific_variable = Model4.where(my_condition) end def my_other_action @variable1 = get_variable1() @variable2 = get_variable2() @variable3 = get_variable3() @action_specific_variable = Model5.where(my_other_condition) end private def get_variable1() return Model1.where(some conditions) end def get_variable2() return Model2.where(some other conditions) end def get_variable3() return Model3.where(some third conditions) end end 

如果需要逻辑来使这些变量在控制器之间可用,请在lib文件夹中创建一个新的实用程序模块。 例如,您可以创建包含的文件lib/utilities.rb

 module Utilities def self.get_variable1() return Model1.where(some conditions) end def self.get_variable2() return Model2.where(some other conditions) end def self.get_variable3() return Model3.where(some third conditions) end end 

然后你的控制器看起来像

 class MyController < ApplicationController # snip ... def my_action @variable1 = Utilities::get_variable1() @variable2 = Utilities::get_variable2() @variable3 = Utilities::get_variable3() @action_specific_variable = Model4.where(my_condition) end def my_other_action @variable1 = Utilities::get_variable1() @variable2 = Utilities::get_variable2() @variable3 = Utilities::get_variable3() @action_specific_variable = Model5.where(my_other_condition) end end 

如果您正在寻找一种方法将复杂逻辑与特定视图相关联,以便每次创建视图时都执行逻辑,即使它是使用尚不存在的方法生成的,也可以使用Rails帮助程序。 每个控制器都有一个与之关联的帮助器。 例如,如果您有一个文件app/controllers/my_controller.rb ,Rails将自动查找名为app/helpers/my_helper.rb的文件。

帮助程序中定义的任何方法都可用于由关联控制器创建的视图。 所以,举个例子,假设你有这个控制器:

 def MyController < ApplicationController # snip ... def my_action @var = "some value" end end 

和一个视图app/views/my/my_action.html.erb

 <% variable1 = Model1.where(some conditions) %> <% variable2 = Model2.where(some other conditions) %> <% variable3 = Model3.where(some third conditions) %> <%= "#{variable1} #{variable2} #{variable3} #{@var} %> 

您可以将访问模型的代码重构为app/helpers/my_helper.rb

 module MyHelper def get_variable1() return Model1.where(some conditions) end def get_variable2() return Model2.where(some other conditions) end def get_variable3() return Model3.where(some third conditions) end end 

并像这样重构你的观点:

 <% variable1 = get_variable1() %> <% variable2 = get_variable2() %> <% variable3 = get_variable3() %> <%= "#{variable1} #{variable2} #{variable3} #{@var} %> 

无需修改控制器。