【问题标题】:Only load helpers on specific controller actions仅在特定控制器操作上加载帮助程序
【发布时间】:2013-04-05 09:47:39
【问题描述】:

在我的 Rails 3 应用程序中,我有一个包含我自己的助手的模块,它覆盖了几个内置的 rails 助手:

module MyHelpers
  def form_for(*args)
     ...
  end

  def link_to(*args)
     ...
  end
end

上述模块位于 lib 文件夹中。

我希望这些助手仅用于特定的控制器操作。我的第一次尝试是这样的:

require "my_helpers"
class MyController < ApplicationController 

  before_filter :add_helpers

  def add_helpers
    if some_condition
      ApplicationHelper.send(:include, MyHelpers)
    end
  end
  ..
end

Module.send(:include, ModuleB) 是在另一个模块中包含一个模块的有效方法,但在这种情况下它不能满足我的需要:我的模块中的方法在视图中不可用。在运行任何控制器方法之前,Rails 似乎已经确定了视图可以使用哪些辅助方法。

有什么方法可以满足我的需要吗?

我知道我可以全局覆盖 form_for 方法,但我不想这样做。

我认为这个问题的答案将来自于理解 rails 如何让视图可以访问辅助方法。

【问题讨论】:

  • 为什么不直接重命名方法呢?他们显然做了其他事情然后form_forlink_to 正在做。
  • 因为我正在开发的库正在做的事情应该适用于任何 Rails 应用程序中的任何控制器。控制器本身不应该知道发生了什么。
  • 我强烈建议不要覆盖 Rails 原生的辅助方法。当 link_to 没有像 Rails 所说的那样工作时,将抛出一个新的代码。正如 Benjamin 建议的那样,我建议重命名这些方法,并在必要时更新您的视图。

标签: ruby-on-rails ruby-on-rails-3


【解决方案1】:

config.action_controller.include_all_helpers 应设置为 false

【讨论】:

  • 这应该默认设置为false
【解决方案2】:

由于 Rails 会自动加载并包含 app/helpers 目录中的所有助手,您可以尝试将助手放在不同的位置,例如 lib 目录中。

这样 .rb 文件会被解析和加载,但模块不会自动包含在 ApplicationHelper 类中。然后您可以按照您的说明在之前的过滤器中执行此操作。

【讨论】:

  • 这正是我的客户 Helper 模块所在的位置,在 lib 文件夹中。问题不在于它被自动包含,问题是我只需要在某些请求中包含该模块。
  • 什么不起作用?您收到错误消息吗?你在config/application.rb中正确配置了autoload_paths吗?
  • 没有错误消息,所以它似乎包含在 ApplicationHelper 模块中。问题是我的模块中的方法对视图不可用。
  • 我不确定这个,但尝试使用ApplicationController.send(:include, MyHelpers)而不是ApplicationHelper
【解决方案3】:

Vapire 认为将这些模块放置在app/helpers 之外的其他位置是一个很好的观点。我会更进一步,并说您尝试做的事情可能不明智 - 在每个操作的基础上提供或不提供一些方法感觉有点太脆弱了,我不喜欢。

我宁愿采用将自定义控制器超类放在您的控制器和包含模块的ApplicationController 之间的方法(或者只是在您的超类中包含这些方法)。

【讨论】:

  • 这正是我的客户 Helper 模块所在的位置,在 lib 文件夹中。问题不在于它被自动包含,问题是我只需要在某些请求中包含该模块。
  • 我建议您采用一种方法,这意味着您不仅仅在某些请求中包含模块,而是仅包含用于不同控制器(和/或控制器超类)的模块。
  • 是的,但我只需要在某些动作上使用它,这些动作可以分布在几个不同的控制器中。我将使用配置文件来确定应该影响哪些操作(或 URL)。
  • 很公平。这不是我会采取的方法。
  • 我同意 - 这种方法是疯狂的。不过,我仍然对如何动态添加助手感兴趣。
【解决方案4】:

在控制器类或帮助器类上添加帮助器后,它会在请求后保持加载状态。 您需要在操作后卸载它们。 不幸的是,没有官方的方法可以卸载一部分助手,你需要编写它。

class MyController < ApplicationController
  around_action :load_helper, only: :create

  def load_helper
    self.class.helper_method :your_helper_method
    yield
    self.class.helper { undef your_helper_method }
  end
end

【讨论】:

  • 在同一进程中服务多个线程时看起来很危险......!如果每个进程一次只处理一个请求,这个解决方案应该没问题。
【解决方案5】:

答案是使用'helper'类方法如下:

require "my_helpers"
class MyController < ApplicationController 

  before_filter :add_helpers

  def add_helpers
    if some_condition
      MyController.helper MyHelpers
    end
  end
  ..
end

【讨论】:

  • 你真的需要require "my_helpers"吗?如果模块在您的lib 目录中,这应该会自动发生...
  • 是的,您确实需要在 rails 3 中使用它。(除非您添加一些自动加载路径)。在 Rails 2 中它是自动的,但现在你必须明确。
  • 这不是答案,因为MyController.helper MyHelpers 导致助手永久加载到控制器上。它会延迟加载帮助程序,但一旦加载,它就可以被任何其他操作调用。
猜你喜欢
  • 2016-02-09
  • 1970-01-01
  • 2011-11-27
  • 2011-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-07
  • 2023-04-03
相关资源
最近更新 更多