这让我头疼不已......
所以我有一个应用程序,需要一个侧边栏,列出与用户的播放器有关的各种信息。这个侧边栏的一部分是朋友列表。现在,当玩家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不允许您在资产管道中使用ERB,因此该文件必须位于 < strong>文件无法访问控制器中声明的变量或使用app/views/layouts
。render
方法(或大多数其他ERB方法)。
事情就是这样:我不能在我的application.html.erb
文件中包含所述文件,我查看了使用AJAX请求该文件,但据我所知,这将立即执行一次Javascript,而且我需要其中的方法可以不断更新侧栏。
是否有任何方法可以包含此文件,以便它可以与ERB和CoffeScript一起使用,以便它可以持续提供给页面?我误解了整个AJAX请求方法吗?
<小时/> 感谢@nzifnab对JS的帮助。现在我的朋友们看起来像这样:
<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
宝石吗?
<小时/> 接着发生轻微的切线:
答案 0 :(得分:3)
你可以在资产管道中使用erb
,但你必须记住它只会被渲染为ONCE,EVER,而不是每个用户一次,所以即使有@user
变量也是如此(它不会有),它永远不会改变。您可以在咖啡文件中使用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为视图呈现新标记。一种方法是使用js模板。我是hamlcoffeeassets
库的忠实粉丝:https://github.com/netzpirat/haml_coffee_assets虽然它使用haml作为视图,而不是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中渲染它,那么你需要通过通知数据响应将这个“朋友关系”数据作为JSON发送,你在渲染javascript时无法访问活动记录或任何控制器方法或实例变量部分 - 他们没有回到服务器,他们只使用你当时的javascript可访问的内容。
答案 1 :(得分:0)
这应该真的转到app/assets/javascripts/cp.js.coffee.erb
,你可以在资产管道中使用erb(参见here)确保你正确拼写coffee
扩展名!
这样做,你应该可以通过ajax调用它而不会出现问题,路径为/assets/cp.js
。
答案 2 :(得分:0)
试试这个宝石:&#39; coffeebeans&#39;
将您的咖啡文件命名为&#34; some_file.html.erb&#34;
<%= coffeescript_tag_do %>
# your coffee script here ...
<% end %>
在另一个erb文件中:
<%= render file: '.../some_file' %>