javascript - 在 View 中包含带有 ERB 的 Coffeescript 文件

标签 javascript ruby-on-rails ajax coffeescript erb

这让我很头疼...

所以我有一个应用程序,它需要一个边栏来列出与用户的播放器有关的各种信息。此边栏的一部分是 friend 列表。现在,当玩家 A 向玩家 B 发送好友请求时,该请求应该会自动记录在 B 的侧边栏中,我打算使用 WebSockets 来执行此操作。

这是我的 cp.js.coffe.erb 文件(目前只有几个 ERB 片段;会有更多,我宁愿先让它工作):

$ ->
  $("#cp").accordion()

  if `"WebSocket" in window`
    socket = new WebSocket("ws://localhost:8080") 

  socket.onopen = =>
    console.log("Connection Open")
    init = {
      sender: "cp"
      action: "init"
      user:   <%= @user.id %>
      token:  <%= cookies["remember_token"] %>
    }

    socket.send(init.to_json)

  socket.onerror = (e)=>
    console.log(e)

  socket.onclose = =>
    console.log("Closed")

  socket.onmessage = (m)=>
    console.log("Recieved: #{m.data}")
    msg = m.data.JSON.parse
    switch msg.action
      when "ret_init"

      when "friend_udt"
        refreshFriend()

refreshFriend() ->
  html = "<%= j render 'layouts/friends' %>"
  $('#friends').empty()
  $('#friends').add(html)

理论上,代码本身可以正常工作,问题在于 Rails 不允许您在 Assets 管道中使用 ERB,因此该文件必须位于 app/views/layouts.文件无法访问在 Controller 中声明的变量或使用 render 方法(或大多数其他 ERB 方法)。

事情是这样的:我不能在我的 application.html.erb 文件中包含上述文件,我研究了使用 AJAX 请求该文件,但据我了解,这将立即执行 Javascript一次又一次,我需要其中的方法始终可用以更新侧边栏。

有没有什么方法可以包含这个文件,以便它与 ERB 和 CoffeScript 一起工作,以便它可以持续提供给页面?我是否误解了整个 AJAX 请求方法?


感谢@nzifnab 对 JS 的帮助。现在我的 friend 部分看起来像这样:

<ul id="friendlist">
    <% if Relation.find_by(owner: @user.id, type: "freq") != nil %>
        <% Relation.find_by(owner: @user.id, type: "freq").each do |r| %>
            <li class="friend-request-cp"><%= link_to "/#{User.find(r.character).name}" %></li>
        <% end %>
    <% end %>
    <% if Relation.find_by(owner: @user.id, type: "friend") != nil %>
        <% Relation.find_by(owner: @user.id, type: "friend").each do |r| %>
            <li class="friend-cp"><%= link_to "/#{User.find(r.character).name}" %></li>
        <% end %>
    <% end %>
</ul>

我需要对每个项目应用两种不同的样式,因此我在这里使用 ERB。这工作正常,因为它是在第一次导航到页面时加载的,但我的代码应该在每次通过任何新交互的通知时重新呈现该部分。然后它将再次使用数据库中的数据重新填充列表。有没有更有效的方法来做到这一点?我还能用你给我看的 hamlcoffeeassets gem 做这个吗?


随之而来的是轻微的切线:
顺便说一句,我在 Windows 7 上使用 Ruby 2.0.0-p247 和 Rails 4。我觉得有必要包括它,因为与 Ubuntu 有很大不同的 gem 存在一些主要的兼容性问题。我不得不从 Ubuntu 转移到 Windows,因为从 13.04 更新到 13.10 破坏了该操作系统上的所有 Ruby Gem。我没有时间去寻找修复:我实际上只有四天的时间来构建这个应用程序。

最佳答案

您可以在 Assets 管道中使用 erb,但您必须记住它只渲染一次,永远,而不是为每个用户渲染一次,所以即使有一个 @user 变量(不会有),它永远不会改变。您可以在 coffee 文件中使用 erb 来处理路由路径和环境变量之类的事情,但不能使用诸如用户特定的配置和 JS 的动态更改之类的事情。无论如何,这是不好的做法。

您真正应该做的是使用 javascript 库来读取 cookie,而不是尝试使用 rails 来读取(这将使您能够访问一些您似乎正在尝试做的事情)。当您需要更多动态行为时,您应该将数据属性或其他值呈现到 html DOM 本身并使用 javascript 读取它。

看看这个 cookie 库:https://github.com/carhartl/jquery-cookie

通过快速谷歌搜索,还有许多其他内容可供查看。

socket.onopen = =>
  console.log("Connection Open")
  init = {
    sender: "cp"
    action: "init"
    user:  $.cookie('user_id')
    token:  $.cookie('remember_token')
  }

有几种方法可以使用 JS 为您的 View 呈现新标记。一种方法是使用 js 模板。我是这里的 hamlcoffeeassets 库的忠实粉丝:https://github.com/netzpirat/haml_coffee_assets虽然它使用 haml 作为 View ,而不是 ERB。还有 ERB 变体。

您可以像这样向 app/assets/templates/friend.jst.hamlc 添加一些标记:

%p This is my friend markup #{@friend.name}

然后你可以像这样从你的 JS 渲染它:

$('#friends').append(JST['templates/friend'](friend: {name: 'Bob'}))

这会将您的模板中的标记附加到您传递的内插值中。在我的示例中,您最终会在 #friends 容器中使用此标记:

<p>This is my friend markup Bob</p>

或者,您可以通过 Rails 将您想要的部分作为字符串呈现到您的 JSON 响应中,然后将其插入到您的文档中...

所以你的 JS 可能看起来像这样:

socket.onmessage = (m)=>
  console.log("Recieved: #{m.data}")
  msg = m.data.JSON.parse
  switch msg.action
    when "ret_init"

    when "friend_udt"
      refreshFriend(msg.friendHTML)

refreshFriend(html) ->
  $('#friends').html(html)

更新

关于您的 ERB 问题...首先,您的部分是非常低效的,每次渲染它时都会对数据库进行四次类似的调用。 haml_coffee_assets 用于 haml 标记语言(我更喜欢 ERB),如果您想要 ERB,请改用 eco:https://github.com/sstephenson/eco

如果你想在 JS 中呈现它,那么你需要通过通知数据响应将这个“ friend 关系”数据作为 JSON 发送,在呈现 javascript 时你无权访问事件记录或任何 Controller 方法或实例变量partials - 它们不会返回到服务器,它们只使用您当时的 javascript 可以访问的内容。

关于javascript - 在 View 中包含带有 ERB 的 Coffeescript 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19717731/

相关文章:

javascript - Firebase:在成功回调中使用新创建的 key

javascript - 加载必要 JSON 数据的最佳实践 : jquery's $(document). read() 钩子(Hook)?在页面的 <HEAD> 中?

ruby-on-rails - 成功的 heroku 运行 rake db :migrate but columns don't seem to work

sql-server - 用于 Rails 的 SQL Server 适配器

javascript - 如何从 JSON 响应中获取数据?

PHP:长轮询和 Comet 相关

javascript - 随机选择剩余的 div Javascript

javascript - Chrome 扩展程序 : How to send data from Panel Window to Popup?

ruby-on-rails - Heroku调试

javascript - 带数据库的 AJAX Servlet