应用程序帮助程序方法是否可用于所有视图?

Eas*_*per 4 ruby-on-rails ruby-on-rails-4.1

Rails 4.1
Ruby 2.0
Windows 8.1
Run Code Online (Sandbox Code Playgroud)

在我的助手/ 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
Run Code Online (Sandbox Code Playgroud)

在我的views/agents/form.html.erb中,我有以下内容:

<%= f.select :agent_id, options_for_select(agents_and_ids_generator) %>
Run Code Online (Sandbox Code Playgroud)

在我的controllers/agents_controller.rb中,我有以下内容:

include ApplicationHelper
Run Code Online (Sandbox Code Playgroud)

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

未定义的局部变量或方法`agents_and_ids_generator'用于#<#:0x00000006fc9148>

如果我将agents_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
Run Code Online (Sandbox Code Playgroud)

Ric*_*eck 5

助手

底线答案是您的所有视图application_helper 可用.

Rails实际上在整个地方都使用了帮助程序 - 从喜欢的东西form_for到其他内置的Rails方法.

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

重要 - 您不需要包含ApplicationHelper在您的ApplicationController.它应该工作


你的问题

可能存在导致该问题的几种可能性; 我有两个想法:

  1. AgentsController继承了ApplicationController吗?
  2. 也许你所包含的ApplicationHelper是一个问题

奇怪的是你的AgentsHelper作品,而ApplicationHelper不是.解释这将是Rails会加载取决于它正在操作的控制器上的帮手,如果你不继承意味着一种方式ApplicationController,ApplicationHelper不会被调用.

你需要测试一下:

#app/controllers/application_controller.rb
Class AgentsController < ApplicationController
   ...
end
Run Code Online (Sandbox Code Playgroud)

接下来,您需要摆脱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
Run Code Online (Sandbox Code Playgroud)

  • 无论谁投票,请告诉我答案有什么问题.我将它保持不变,因为我认为这是正确的. (2认同)