3

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

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

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

4

3 回答 3

4

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

把你的逻辑放在好的地方真的很有趣,因为如果你的代码在好地方,调试、维护或重构你的应用程序会更容易。

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

before_action(在控制器中)

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

例如,您可以这样做:

before_action :set_variables

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

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

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)
于 2013-11-12T23:37:23.927 回答
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
于 2013-11-12T23:26:24.207 回答
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} %>

无需修改控制器。

于 2013-11-12T23:35:08.197 回答