在铁轨上观看胖视图是不是很糟糕?

时间:2013-11-12 23:12:58

标签: ruby-on-rails

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

<% variable1 = Model1.where(some conditions) %>
<% variable2 = Model2.where(some other conditions) %>
<% variable3 = Model3.where(some third conditions) %>

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

3 个答案:

答案 0 :(得分:4)

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

将逻辑置于好的位置真的很有趣,因为如果您的代码处于最佳位置,调试,维护或重构您的应用程序会更容易。

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

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)

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

如果您正在寻找一种方法将复杂逻辑与特定视图相关联,以便每次创建视图时都执行逻辑,即使它是使用尚不存在的方法生成的,也可以使用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} %>

无需修改控制器。

相关问题