简体   繁体   English

如何告诉rails不要在我的应用程序中预编译/缓存.js.erb文件?

[英]How do I tell rails not to precompile/cache a .js.erb file in my app?

I have a messages.js.erb file in my app/assets/javascripts/channels folder that should generate code to take each chatroom from the database and create channel subscriptions for that chatroom. 我的app / assets / javascripts / channels文件夹中有一个messages.js.erb文件,该文件应生成代码以从数据库中获取每个聊天室并为该聊天室创建频道订阅。

Here is my messages.js.erb file 这是我的messages.js.erb文件

//**app/assets/javascripts/channels/messages.js.erb**

$(document).on('turbolinks:load', function() {
  submitNewMessage();
});

<% Chatroom.all.each do |chatroom| %>
  App['room' + <%=chatroom.id%>] = App.cable.subscriptions.create({channel: 'MessagesChannel', room: <%=chatroom.id%>}, {
  received: function(data) {
   $("[data-chatroom='" + this.chatroomId + "']").removeClass('hidden');
    return $("[data-chatroom='" + this.chatroomId + "']").append(data.message);
  },

  setChatroomId: function(chatroomId) {
    this.chatroomId = chatroomId;
  }
});

<% end %>

function submitNewMessage(){
  //console.log(uid);
  $('textarea#message_content').keydown(function(event) {
    if (event.keyCode === 13) {
        var msg = event.target.value;
        var chatroomId = $("[data-chatroom]").data().chatroom;
        var uid = $('#uid').val();
        //console.log(uid);
        App['room' + chatroomId].setChatroomId(chatroomId);
        App['room' + chatroomId].send({message: msg, chatroom_id: chatroomId, user_id: uid});
        $('[data-textarea="message"]').val(" ");
        return false;
     }
  });
}

Preferably, this file should reload every time a new chatroom is created, but rails is caching( precompiling? ) the file( asset? ) after first load and serving it at every request. 优选地,每次创建新聊天室时都应该重新加载该文件,但是在首次加载并且在每次请求时为其提供服务时,rails正在高速缓存( precompiling? )文件( asset? )。

So, the problem is: Every time a new chatroom is created, if I want it to stream (ie, be able to post messages to be streamed instantly to every participant of that chatroom), I need to change the file manually (by adding whitespace, or adding comments or logging to console, something ) and save it so that rails thinks that the file has changed and reloads it, thereby iterating over all the Chatroom s again which contains the newly created chatroom too. 所以,问题是:每次创建一个新的聊天室时,如果我想让它流式传输(即能够发送消息立即流式传输给该聊天室的每个参与者),我需要手动更改文件(通过添加空格,或添加注释或记录到控制台, something )并保存它,以便rails认为文件已更改并重新加载它,从而再次遍历包含新创建的聊天Chatroom的所有Chatroom室。

Otherwise, when I post(hit enter) on a message in a chatroom that is not streaming yet (because the cached version can't see it) I get a 否则,当我在一个尚未流媒体的聊天室中发布消息(点击输入)时(因为缓存版本看不到它)我得到了一个

Uncaught TypeError: Cannot read property 'setChatroomId' of undefined at HTMLTextAreaElement. 未捕获的TypeError:无法读取HTMLTextAreaElement中未定义的属性“setChatroomId”。 (messages.self-cbf13df66ead12b7956faa24e880ce07c0289634216a096fafd4ac1c6d262f43.js?body=1:436) at HTMLTextAreaElement.dispatch (jquery-1.11.3.min.self-ad66c584c2469d2bb527ba7aef5893549f1554ccc8ab3ccb43bd09ce8c3bf7a1.js?body=1:5) at HTMLTextAreaElement.r.handle (jquery-1.11.3.min.self-ad66c584c2469d2bb527ba7aef5893549f1554ccc8ab3ccb43bd09ce8c3bf7a1.js?body=1:5) 在HTMLTextAreaElement.dispatch(jQuery的1.11.3.min.self-ad66c584c2469d2bb527ba7aef5893549f1554ccc8ab3ccb43bd09ce8c3bf7a1.js体= 1〜5):(436?messages.self-cbf13df66ead12b7956faa24e880ce07c0289634216a096fafd4ac1c6d262f43.js体= 1)在HTMLTextAreaElement.r.handle(jquery的1.11 ?.3.min.self-ad66c584c2469d2bb527ba7aef5893549f1554ccc8ab3ccb43bd09ce8c3bf7a1.js体= 1:5)

in my browser console (developer tools). 在我的浏览器控制台(开发人员工具)。 The source of the error is: 错误的来源是:

Here is the generated messages.js code (repeat lines trimmed for brevity) 这是生成的messages.js代码 (为简洁而修剪重复行)

  $(document).on('turbolinks:load', function() {
      submitNewMessage();
    });



   App['room' + 1] = App.cable.subscriptions.create({channel: 'MessagesChannel', room: 1}, {
  received: function(data) {
   $("[data-chatroom='" + this.chatroomId + "']").removeClass('hidden');
    return $("[data-chatroom='" + this.chatroomId + "']").append(data.message);
  },

  setChatroomId: function(chatroomId) {
    this.chatroomId = chatroomId;
  }
});
  .
  .
  .
  .
  .
  .
  .
  App['room' + 37] = App.cable.subscriptions.create({channel: 'MessagesChannel', room: 37}, {
  received: function(data) {
   $("[data-chatroom='" + this.chatroomId + "']").removeClass('hidden');
    return $("[data-chatroom='" + this.chatroomId + "']").append(data.message);
  },

  setChatroomId: function(chatroomId) {
    this.chatroomId = chatroomId;
  }
});


function submitNewMessage(){
  //console.log(uid);
  $('textarea#message_content').keydown(function(event) {
    if (event.keyCode === 13) {
        var msg = event.target.value;
        var chatroomId = $("[data-chatroom]").data().chatroom;
        var uid = $('#uid').val();
        App['room' + chatroomId].setChatroomId(chatroomId); // <-- line 436
        App['room' + chatroomId].send({message: msg, chatroom_id: chatroomId, user_id: uid});
        $('[data-textarea="message"]').val(" ");
        return false;
     }
  });
}

I understand that this error is obvious, since App['room' + 38] hasn't been defined yet for the new chatroom with id 38 in which we are trying to post the message (here, all chatrooms with id's > 37) 我明白这个错误是显而易见的,因为App['room' + 38]尚未定义为id为38的新聊天室,我们正在尝试发布消息(此处,所有聊天室的ID大于37)

But how do I make rails understand that this file needs to be reloaded every time a new chatroom is created. 但是,如何让rails了解每次创建新聊天室时都需要重新加载此文件。 If not every time, then on every request? 如果不是每次,那么每次请求? Basically, tell rails not to precompile/cache it so I can create chatrooms and stream from them on the go? 基本上,告诉rails不要预先编译/缓存它,以便我可以在移动中创建聊天室并从中流式传输?

Move your messages.js.erb file to the lib/assets or vendor/assets directory. messages.js.erb文件移动到lib/assetsvendor/assets目录。

From the doc : 来自doc

...assets under lib/assets or vendor/assets are available for inclusion via the application manifests but no longer part of the precompile array. ... lib / assets或vendor / assets下的资产可通过应用程序清单包含但不再是预编译数组的一部分。

Make sure it's not listed in your application.js and you should be good to go. 确保它没有列在你的application.js ,你应该好好去。

I guess you used the tutorial from https://www.thegreatcodeadventure.com/rails-5-action-cable-with-multiple-chatroom-subscriptions/ which is a good one. 我想你使用的是https://www.thegreatcodeadventure.com/rails-5-action-cable-with-multiple-chatroom-subscriptions/这个教程很好。 You should solve this issue not with changing the precompile. 您应该解决此问题,而不是更改预编译。 Instead supscripe to the channels more efficiently. 而是更有效地吸收渠道。

For example execute the method from the outside. 例如,从外部执行方法。 Use a helper method to get only the needed rooms. 使用帮助方法只获取所需的房间。

subscripeToChannels(<%= raw chatrooms_for_client %>)

In the subscription method check if you do not subscribed already. 在订阅方法中检查您是否已经订阅。

for (var i = 0; i < App.cable.subscriptions.subscriptions.length; i++) {
    var s = App.cable.subscriptions.subscriptions[i]
    var JSONObject = JSON.parse(s.identifier);
    var room = JSONObject["room"];
    if (room == chatroomId)
    {
      preventMultipleSubscripe = true;
    }
  }

In case a new room got created you can execute the subscripeToChannels again in your create.js.erb file. 如果创建了新房间,您可以在create.js.erb文件中再次执行subscripeToChannels。

subscripeToChannels(<%= raw chatrooms_for_client %>)

For me, this solved it in a cleaner way 对我来说,这以更清洁的方式解决了它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM