应用程序助手方法是不是适用于所有视图?

Posted

技术标签:

【中文标题】应用程序助手方法是不是适用于所有视图?【英文标题】:Are application helper methods available to all views?应用程序助手方法是否适用于所有视图? 【发布时间】:2014-09-18 00:53:26 【问题描述】:
Rails 4.1
Ruby 2.0
Windows 8.1

在我的 helpers/application_helper.rb 中,我有:

def agents_and_ids_generator
    agents = Agent.all.order(:last)
    if agents
      agents_and_ids = [['','']]
      agents.each do |l|
        name = "#l.first #l.last"
        agents_and_ids << [name,l.id]
      end
      return agents_and_ids
    end
  end

在我的视图/代理/form.html.erb 中,我有以下内容:

<%= f.select :agent_id, options_for_select(agents_and_ids_generator) %>

在我的控制器/agents_controller.rb 中,我有以下内容:

include ApplicationHelper

但是当我转到这个视图时,我收到以下错误消息:

# 的未定义局部变量或方法 `agents_and_ids_generator'

如果我将 agent_and_ids_generator 方法移动到 helpers/agents_helper.rb 中,它可以正常工作。

我认为通过将方法放在应用程序助手中并将应用程序包含在控制器中,这些方法就可以用于视图。我在那个假设中不正确吗?

答案:

确保应用程序助手不包含在控制器中,并添加了以下简化:

<%= f.collection_select :agent_id, Agent.all.order(:last), :id, :name_with_initial, prompt: true %>

#app/models/agent.rb
Class Agent < ActiveRecord::Base
   def name_with_initial
     "#self.first #self.last"
   end
end

【问题讨论】:

你不必在你的控制器中include ApplicationHelper 是的,但这并不能解释我要问的问题 【参考方案1】:

Rails 5 更新。我遇到了一个类似的问题,视图没有从 application_helper.rb 中获取方法。 This post 帮助了我。新 Rails 应用程序的 helpers 目录中提供的文件仅适用于这些视图。 application_helper.rb 中的方法不会自动对所有视图可用。要创建适用于所有视图的辅助方法,请在辅助目录中创建一个新的辅助文件,例如 clean_emails_helper.rb,并在此处添加您的自定义方法,如下所示:

Module CleanEmailsHelper
  def clean_email(email)
     *do some stuff to email*
     return email
  end
end

然后您可以从应用中的任何视图调用&lt;%= clean_email(email) %&gt;

【讨论】:

【参考方案2】:

帮助者

最重要的答案是application_helper在您的所有视图中都可用。

Rails 实际上在所有地方都使用了助手 - 从 form_for 到其他内置的 Rails 方法。

由于 Rails 基本上只是一系列类和模块,helpers 在您的视图呈现时被加载,允许您在需要时调用它们。 Controllers 在堆栈中处理得更早,因此您必须在其中明确包含您需要的帮助器

重要提示 - 您无需在 ApplicationController 中包含 ApplicationHelper。它应该正常工作


您的问题

可能有几种可能性导致问题;我有两个想法给你:

    您的AgentsController 是否继承自ApplicationController? 也许您包含 ApplicationHelper 会导致问题

奇怪的是,您的 AgentsHelper 有效,而 ApplicationHelper 无效。解释这一点的一种方法是,Rails 将根据正在操作的控制器加载帮助程序,这意味着如果您不从 ApplicationController, 继承,则不会调用 ApplicationHelper

你需要用这个来测试:

#app/controllers/application_controller.rb
Class AgentsController < ApplicationController
   ...
end

接下来,您需要删除控制器中的include ApplicationHelper。这只会使该类(控制器)可以使用助手,并且不会对您的视图产生任何影响

话虽如此,它可能导致您的视图加载 ApplicationHelper 时出现问题 - 这意味着您绝对应该测试从您的 ApplicationController 中删除它


方法

最后,你的方法可以大大简化,使用collection_select

<%= f.collection_select :agent_id, Agent.all.order(:last), :id, :name_with_initial, prompt: true %>

#app/models/agent.rb
Class Agent < ActiveRecord::Base
   def name_with_initial
       "#l.first #l.last"
   end
end

【讨论】:

在控制器中包含 application_helper 是一个 Hail Mary。最初并不知道 application_helper 方法对所有视图都是自动可用的。我会检查其他可能不寻常的地方。感谢您提供的简化方法。 谁投了反对票,请让我知道答案有什么问题。我保持不变,因为我相信它是正确的。 不知道为什么这会被否决,但是当有人在没有发表评论的情况下对答案或问题投反对票时,我觉得这很烦人。我认为这应该是此类论坛的要求。我接受你的回答,对模型方法进行了一点修改 谢谢 - 我不介意投反对票;我只是想知道如何改进,以便下次做得更好

以上是关于应用程序助手方法是不是适用于所有视图?的主要内容,如果未能解决你的问题,请参考以下文章

Swiftui Scrollview Viewmodifier 适用于所有 Scrollview

所有以前的移动视图在适用于操作系统版本高于 4.1.x 的三星设备的 Worklight Android 应用程序中可见

iOS - TapGestureRecognizer - 点击适用于整个屏幕而不是视图

android.hardware.Camera 是不是仍然适用于所有 API 级别?

带有表格视图的视图仅适用于默认视图控制器

自定义 UINavigationBar 背景适用于除一个之外的所有导航控制器