Ajax更新后是否可以使用ERB/slim模板而不是EJS(JST)



我看到了很多关于这个主题的问题,但没有明确的解决方案。我有一个Rails 3.2应用程序,它利用了ERB/slim和Coffeescrapt/EJS/Backbone。我继承了这个代码库,所以其中一些外围设备有点让我不知所措。

问题

我的venue视图有一个部分显示提交给venuetipstips的列表具有JavaScript提供的"排序"功能。关联的CoffeeScript文件具有事件侦听器,用于单击"最近"one_answers"流行"的链接。点击后,JS会做一些工作,并利用Rails范围来调用列表。我构建这个tips列表以包含更多的数据,特别是包含Rails助手time_ago_in_words。原始代码使用Javascripts/templates资产目录中的JST/EJS模板更新了包含提示的div。

这些是我遇到的具体问题:

  1. 如果我将.erb添加到文件链中(在更新EJS解释器以寻找不同的求值和插值模式以避免与erb冲突之后),我可以求值基本的Ruby表达式。然而,分部无法访问JavaScript引用的相同tip变量。我知道这是因为Rails是服务器端,JS是客户端。共识似乎是否定的,但有没有一种方法可以将这些数据传输到Rails
  2. 虽然可以计算基本的Ruby表达式(例如Time.now),但像time_ago_in_words这样的Rails助手失败了,抱怨该方法对于类是未定义的,尽管我绝对传入了正确的日期对象。在这个.EJS.ERB链中可以不评估Rails/helpers吗
  3. 如果有一种方法可以在执行排序后引用加载时使用的原始ERB/slim部分,我可以避免所有这些问题。这可能吗?现在,调用的Coffeescript文件使用renderJST来调用EJS模板。是否可以以某种方式引用原始分部,但使用更新的排序

以下是相关代码。

##show.html.erb (venue)##
#tips
p.sort.span4
| Sort by: 
= link_to 'Recent', '#', class: 'selected', id: 'sort-tips-recent'
|  | 
= link_to 'Popularity', '#', id: 'sort-tips-popularity'
#tip-list
= render resource.tips.by_recent

##tip_list_view.js.coffee##
class CS.TipListView extends Backbone.View
el: "#tip_module"
events:
"click #sort-tips-recent": "sortByRecent"
"click #sort-tips-popularity": "sortByPopularity"
initialize: ->
console.log("ERROR: View must be initialized with a model") unless @model
@model.bind('reset', @render)
render: =>
tips = @model.map (tip) -> JST['templates/tip'](tip: tip)
@$('#tip-list').html(tips.join("n"))
sortByRecent: (e) ->
e.preventDefault()
@model.enableSortRecent()
@updateSelectedFilter('recent')
sortByPopularity: (e) ->
e.preventDefault()
@model.enableSortPopularity()
@updateSelectedFilter('popularity')
updateSelectedFilter: (sort) ->
@$('p.sort a').removeClass('selected')
@$("p.sort a#sort-tips-#{sort}").addClass('selected')

##tip.jst.ejs.erb (called from tip_list_view.js.coffee after sort change##
<div class="tip">
<p class="tip-author">
<$= tip.get('user').username $>
</p>
<p class="tip-timestamp">
Eventually, time goes here
</p>
<p class="tip-likes pull-right">
<$= tip.upvoteCountText() $>
</p>
<p id="<$= tip.domId() $>">
<$= tip.get('text') $>
<$ if(tip.get('can_upvote')) { $>
<a href="<$= tip.upvoteUrl() $>">upvote</a>
<$ } $>
</p>
<div>

我在这里完全不知所措——我们非常感谢所有的帮助。让我知道,如果有任何其他细节或代码,我可以提供背景。提前感谢!

使用ejs.erb,Rails正在生成模板,但不知道您将使用它做什么。然后,您的Backbone应用程序通过ajax从Rails获取提示,并相应地填充模型。然后是你的主干应用程序来填充和呈现模板。Rails不能参与其中,至少在主干网期望json然后呈现模板的配置中不会。一切都发生在前端。

你唯一能做的就是让Rails在json中给你助手的结果。我猜你有一个Tip.rb模型,它应该实现:

include ActionView::Helpers::DateHelper
...
def as_json(options = {})
{
:name => self.name,
... (all the model attributes that you want to expose)
:date_age => time_ago_in_words self.created_at
}
end

话虽如此,我将def使用客户端解决方案,这也是因为:http://rails-bestpractices.com/posts/105-not-use-time_ago_in_words

最新更新