Rails应用程序中的本地问题

时间:2016-10-10 02:30:48

标签: javascript ruby-on-rails ruby

我在使用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 }) %> ");

2 个答案:

答案 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作为局部变量传递。如果您要渲染包含表单的模板...那么您不需要传入表单,因为它已经在呈现表单。尝试只渲染部分而不传入本地,看看会发生什么......如果你遇到错误,我们就可以继续处理。