如何在使用Javascript和ERB模板(Rails)时保持DRY

use*_*154 8 javascript model-view-controller ruby-on-rails dry mustache

我正在构建一个Rails应用程序,它使用Pusher来使用Web套接字将更新直接推送到客户端.在javascript中:

channel.bind('tweet-create', function(tweet){ //when a tweet is created, execute the following code:
  $('#timeline').append("<div class='tweet'><div class='tweeter'>"+tweet.username+"</div>"+tweet.status+"</div>");
});
Run Code Online (Sandbox Code Playgroud)

这是令人讨厌的代码和演示混合.所以自然的解决方案是使用javascript模板.也许生态或胡子:

//store this somewhere convenient, perhaps in the view folder:
tweet_view = "<div class='tweet'><div class='tweeter'>{{tweet.username}}</div>{{tweet.status}}</div>"

channel.bind('tweet-create', function(tweet){ //when a tweet is created, execute the following code:
    $('#timeline').append(Mustache.to_html(tweet_view, tweet)); //much cleaner
});
Run Code Online (Sandbox Code Playgroud)

这很好,除了我重复自己.胡子模板与我已编写的用于从服务器呈现HTML的ERB模板99%相同.小胡子和ERB模板的预期输出/目的是100%相同:将tweet对象转换为tweet html.

消除这种重复的最佳方法是什么?

更新:即使我回答了我自己的问题,我真的希望看到其他人的其他想法/解决方案 - 因此是赏金!

Wil*_*Ayd 5

imo最简单的方法是在创建新推文时使用AJAX更新页面.这需要创建两个文件,第一个是标准的html.erb文件,第二个是js.erb文件.html.erb将是标准表单,它可以迭代并显示从数据库中提取后的所有推文.js.erb文件将是您在创建时附加新推文的简单javascript,即:

$('#timeline').append("<div class='tweet'><div class='tweeter'><%= tweet.username %></div><%= tweet.status %></div>")
Run Code Online (Sandbox Code Playgroud)

在您的新推文的表单中,您需要添加:

:remote => true
Run Code Online (Sandbox Code Playgroud)

这将启用AJAX.然后在创建操作中,您需要添加如下代码:

def create
...Processing logic...
  respond_to do |format|
    format.html { redirect_to tweets_path }
    format.js
  end
end
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如果你发布一个启用了AJAX形式的推文,它会通过运行create.js.erb中的任何代码来响应调用(这将是$('#timeline').来自上面的代码) .否则它将重定向到您想要发送它的任何地方(在这种情况下,推文的"索引").这是实现你想要做的最干净,最清晰的方式.

  • 那么你可以做的是在两者之间有一个第三个共享部分(shared/_tweet_item.html.erb).所以例如在你的html文件中你可以做一个渲染'<%= render:partial =>'shared/tweet_item',:collection => @tweets_array%>'这将迭代你的数组中所有推文的部分.同样在你的create.js.erb文件中,你可以做类似'$("timeline")的事情.append("<%= escape_javascript(render('shared/tweet_item',@ tweet))%>")'将附加给你一个@tweet实例变量的新部分 (2认同)