我在使用remote: true
与本地人进行AJAX通话时遇到错误。这是错误:
ActionView::Template::Error (undefined local variable or method `f' for #<#<Class:0x94db890>:0x9ab41d0>):
以下是我的代码:
new.html.erb
<%= form_for(@author) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :age %><br>
<%= f.number_field :age %>
</div>
<%= link_to "Add Books" , remote: true %>
<div id = "add_book"></div>
<%= f.submit %>
控制器
def new
@author = Author.new
@books = @author.books.build
respond_to do |format|
format.html
format.js
end
end
new.js.erb
$("#add_book").append(" <%= escape_javascript(render partial: 'addbook', :locals => { :f => f }) %> ");
答案 0 :(得分:2)
您正在使用remote:true(AJAX调用)调用控制器的新操作。这将导致new.js.erb被渲染为作为响应发回 - new.html.erb将不会被处理。
在new.js.erb中你有:
$("#add_book").append(" <%= escape_javascript(render partial: 'addbook', :locals => { :f => f }) %> ");
意味着它试图将addbook部署并为其设置局部变量,在partial中引用为f
,并为其赋值(new.js.erb为local){{ 1}}。
new.js.erb尚未声明本地变量f
,因而未声明您的错误。
为了提供更多帮助,我们需要知道这个变量的意图是什么--_addbook.html.erb以什么方式需要它?
答案 1 :(得分:1)
所以...... erb模板的工作方式是:
Rails会生成一个页面,在您的示例中,这将是new
,通过控制器中的new
操作并收集所有变量(例如author
和{{1 }})。
然后它获得了该动作的正确模板。在您首次打开books
页面的情况下,您会收到表单......对吗?这来自new
模板。
所以rails读取模板并运行ruby代码......用适当的html替换它。然后它将html发送到浏览器。
当它将它发送到浏览器时,不再有任何红宝石代码......只是html,因为浏览器并不理解ruby,只是html - 所以这就是&#39; s发送的所有内容。
现在......浏览器有一个html表单,其中包含一些js - 这将是new.html.erb
链接 - 它的html,它会调用一些向你的rails应用程序发送请求的js。
rails应用程序然后执行add books
操作,再次收集变量,但这次,它不会渲染html模板...因为它被js调用。所以它取而代之的是new
模板。
此时rails对html模板一无所知。 html模板中的任何内容早已不复存在 - 被发送到浏览器。所有它知道的是js
模板中的内容。它试图在模板中运行ruby代码......并且它要求js
...而f
并不存在于您的js模板中...所以它迷茫并且告诉你它不知道这个f
的东西。
在过去的某个时刻它呈现了一个名为f
的形式并不重要,因为它属于远离过去不再存在的请求的方式。浏览器并没有告诉有关f
的信息,因为它从来不知道它(这是红宝石的一部分,而不是浏览器所见过的所有HTML)。所以...没有f
。 ;)
在这种情况下 - 我不确定您是否需要将f
作为局部变量传递。如果您要渲染包含表单的模板...那么您不需要传入表单,因为它已经在呈现表单。尝试只渲染部分而不传入本地,看看会发生什么......如果你遇到错误,我们就可以继续处理。