Rails 4将局部变量获取到js.erb文件

时间:2015-11-18 04:24:25

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

我已经阅读/研究了其他答案,但我无法让它发挥作用。我有一个渲染部分的js.erb文件。我想将@node变量传递给它,但我在控制台中遇到错误NameError: - undefined local variable or method "node" for #<#<Class:0x007fdcd9163510>:0x007fdcd813b728>

我不确定为什么它不会抓住它。

_node.html.erb(节点是此部分中的局部变量):

<div id="tagged_users">
  <%= render partial: "nodes/user_tag_list", locals: { node: node } %>
</div>

我想在js.erb

中呈现的部分内容

_user_tag_list.html.erb:

<ul>
  <% node.tagged_users.map(&:name).each do |tag| %>
    <li><%= tag %>
      <%= link_to "x", node_path(node, remove_tag: tag), method: :patch %>
    </li>
  <% end %>
</ul>

node#update controller action:

def update
  @node = Node.find(params[:id])

  if params.fetch(:node, {}).fetch(:autocomplete_tag_names, false)
    tag = params[:node][:taggable_email]
    @node.user_tag_list.add(tag)
    @node.save

      respond_to do |format|
        format.js { render 'user_tag_add.js.erb' }
      end
    elseif
      # ...
    else
    # ...
  end

最后是js.erb文件:

user_tag_add.js.erb:

$("#tagged_users").html("<%= escape_javascript(render 'user_tag_list', locals: { node: @node }) %>");

一些笔记。逻辑是合理的。如果我用字符串替换html而不是部分它可以正常工作。另外,如果我binding.pry我可以将节点设置为@node而不会出现问题。只是无法将@node传递给js.erb文件中的节点。

修改

如果有用的话,这是部分形式:

<%= form_for node, remote: true, html: { class: "edit_node tag-users" } do |f| %>
  <%= f.label :autocomplete_tag_names %>
  <%= f.text_field :autocomplete_tag_names, data: { autocomplete_source: users_path }, value: nil %>
  <%= f.hidden_field :taggable_email, value: nil %>
  <%= f.submit %>  
<% end %>

1 个答案:

答案 0 :(得分:5)

呃,根本不是变量范围。在我上面的js.erb文件中,我最初有:

$("#tagged_users").html("<%= escape_javascript(render 'user_tag_list', locals: { node: @node }) %>");

请注意,上面我说user_tag_list是部分?好吧,我没有在我的渲染语句中指定它。我需要将代码修改为以下内容:

$("#tagged_users").html("<%= escape_javascript(render partial: 'user_tag_list', locals: {node: @node}) %>");

然后它奏效了。如果其他人在调试此类代码时遇到问题,看看它是否是变量,我会通过以下步骤创建控制台消息:

  1. 确保可以看到变量

    console.log("<%= @node %>"); response: #&lt;Node:0x007fdcd8203138&gt;
    
  2. 要确认我写了几个控制台语句,这些语句会从对象中提取一些内容以确保捕获到正确的信息

    console.log("<%= @node.id %>"); response: 49
    console.log("<%= @node.name %>"); response: 'Test 2'
    
  3. 一旦我看到变量被传递,我就知道这不是问题所在,并且它确保我的render语句格式正确。错过partial是一个很大的错误,花了我几个小时的生命。我希望这篇文章得到了一些回报。

    其他信息

    我在调试时学到的另一件事:如果你想设置一个局部变量而不是一个实例变量(无论出于何种原因我都不确定)你可以在你的控制器动作的render语句中创建它

    respond_to do |format|
        format.js { render 'user_tag_add.js.erb', locals: {node: @node} }
    end
    

    然后你可以在你的js.erb文件中做这样的事情

    console.log("<%= node %>")