Rails 将重复的 js.erb 代码包装到函数中

rails wrapping duplicate js.erb code into function

提问人:Sean Magyar 提问时间:2/10/2016 更新时间:2/10/2016 访问量:974

问:

我有一个带有自定义推送器聊天的 rails 应用程序,其中聊天消息将由 AJAX 为发送方加载,并通过推送器套接字为接收方加载。

在我的 create.js.erb 文件中,我目前有重复的代码,我不知道在 js.erb 模板中包装一段代码的最佳方法是什么。

sby能告诉我,如何正确地摆脱重复吗?广播函数前面的代码与包装到广播函数中的代码相同。

create.js.erb

//first part is AJAX, only goes to sender
var id = "<%= @conversation.id %>";
var chatbox = $(".chatboxcontent");
var sender_id = "<%= @message.user.id %>";
var receiver_id = $('meta[name=user-id]').attr("content");

if (event.handled !== true) {

   $message = $('<%= j render @message %>');
   chatbox.append($message);
   chatbox.scrollTop(chatbox[0].scrollHeight);

   $(".chatboxtextarea").val("");
   $(".chatboxtextarea").focus();
   $(".chatboxtextarea").css('height', '44px');
   var timeField = ($message).find('.timefield');
   var nameField = ($message).find('#chatname');
   var createdAt = timeField.attr('datetime');
   var momentCreatedAt = moment(createdAt).format('hh:mm A');
   timeField.remove();
   $( "<span class='newtime'>" + " • " + momentCreatedAt + "</span>" ).insertAfter(nameField);

   if(sender_id != receiver_id) {
     chatbox.children().last().removeClass("self").addClass("other");
     chatbox.scrollTop(chatbox[0].scrollHeight);
   }
   event.handled = true;
}

//only broadcasted to receiver, sender is getting the message via the prev AJAX
<% broadcast_to_conversation(@conversation.id, @receiver_id) do %>
  var id = "<%= @conversation.id %>";
  var chatbox = $(".chatboxcontent");
  var sender_id = "<%= @message.user.id %>";
  var receiver_id = $('meta[name=user-id]').attr("content");

  if (event.handled !== true) {

    $message = $('<%= j render @message %>');
    chatbox.append($message);
    chatbox.scrollTop(chatbox[0].scrollHeight);

    $(".chatboxtextarea").val("");
    $(".chatboxtextarea").focus();
    $(".chatboxtextarea").css('height', '44px');
    var timeField = ($message).find('.timefield');
    var nameField = ($message).find('#chatname');
    var createdAt = timeField.attr('datetime');
    var momentCreatedAt = moment(createdAt).format('hh:mm A');
    timeField.remove();
    $( "<span class='newtime'>" + " • " + momentCreatedAt + "</span>" ).insertAfter(nameField);

    if(sender_id != receiver_id) {
        chatbox.children().last().removeClass("self").addClass("other");
        chatbox.scrollTop(chatbox[0].scrollHeight);
    }

    event.handled = true;
  }
<% end %>
javascript jquery ruby-on-rails ajax unobtrusive-javascript

评论

0赞 Alankar More 2/10/2016
您可以创建一个函数并在其中放置通用代码。
0赞 Oleh Sobchuk 2/10/2016
将其删除以分离函数application.js
0赞 Sean Magyar 2/10/2016
伙计们,你能提供代码示例吗?我知道我应该把它放到一个函数中,只是不确定如何

答:

2赞 Dieter Pisarewski 2/10/2016 #1

1. 解决方案

您可以创建一个部分并渲染它两次:

_chatbox.js.erb

var id = "<%= @conversation.id %>";
var sender_id = "<%= @message.user.id %>";
var receiver_id = $('meta[name=user-id]').attr("content");
var chatbox = $(".chatboxcontent");

if (event.handled !== true) {

  $message = $('<%= j render @message %>');
  chatbox.append($message);
  chatbox.scrollTop(chatbox[0].scrollHeight);

  $(".chatboxtextarea").val("");
  $(".chatboxtextarea").focus();
  $(".chatboxtextarea").css('height', '44px');
  var timeField = ($message).find('.timefield');
  var nameField = ($message).find('#chatname');
  var createdAt = timeField.attr('datetime');
  var momentCreatedAt = moment(createdAt).format('hh:mm A');
  timeField.remove();
  $( "<span class='newtime'>" + " • " + momentCreatedAt + "</span>" ).insertAfter(nameField);

  if(sender_id != receiver_id) {
    chatbox.children().last().removeClass("self").addClass("other");
    chatbox.scrollTop(chatbox[0].scrollHeight);
  }
  event.handled = true;
}

create.js.erb

<%= render "chatbox" %>

<% broadcast_to_conversation(@conversation.id, @receiver_id) do %>
  <%= render "chatbox" %>
<% end %>

2. 解决方案

但更好的解决方案是将通用代码提取到一个 javascript 函数中,并使用您从控制器获得的数据来参数化此函数。在这种情况下,您可以更好地重用应用程序其他部分的代码。

在控制器中:

def create
  #...
  @chatbox_params = {id: @conversation.id, sender_id: @message.user.id}
  #...
end

应用程序.js

function chatbox(params){
  var receiver_id = $('meta[name=user-id]').attr("content");
  var chatbox     = $(".chatboxcontent");

  if (event.handled !== true) {
    chatbox.append(params.message);
    chatbox.scrollTop(chatbox[0].scrollHeight);

    $(".chatboxtextarea").val("");
    $(".chatboxtextarea").focus();
    $(".chatboxtextarea").css('height', '44px');
    var timeField = (params.message).find('.timefield');
    var nameField = (params.message).find('#chatname');
    var createdAt = timeField.attr('datetime');
    var momentCreatedAt = moment(createdAt).format('hh:mm A');
    timeField.remove();
    $( "<span class='newtime'>" + " • " + momentCreatedAt + "</span>" ).insertAfter(nameField);

    if(params.sender_id != receiver_id) {
      chatbox.children().last().removeClass("self").addClass("other");
      chatbox.scrollTop(chatbox[0].scrollHeight);
    }
    event.handled = true;
  }
}

create.js.erb

var chatboxParams     = JSON.parse('<%= @chatbox_params.to_json %>');
chatboxParams.message = $('<%= j render @message %>');

chatbox(chatboxParams);

<% broadcast_to_conversation(@conversation.id, @receiver_id) do %>
  chatbox(chatboxParams);
<% end %>

评论

0赞 Sean Magyar 2/10/2016
节食者,不错的解决方案!我看到了将参数放入控制器背后的想法,但是为什么您将消息提取为chatboxParams.message?
0赞 Dieter Pisarewski 2/10/2016
我提取了所有在 ruby 中可变的参数(来自控制器)。其他参数不依赖于服务器逻辑,它们只是 javascript 语句。当然,你应该更了解如何设计你的 API。这只是一个例子。
0赞 Sean Magyar 2/10/2016
Dieter,对于可能找到这篇文章的人,你能更新你的答案并将 vars 放入 <% broadcast_to......功能也一样?我想否则不会找到 chatParams,因为广播函数将在其他地方调用。