1

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

问题

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

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

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

这是相关的代码。

  ##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>

在这里绝对不知所措 - 非常感谢任何和所有帮助。如果我可以为背景提供任何其他细节或代码,请告诉我。提前致谢!

4

1 回答 1

1

使用您的 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

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

于 2012-11-27T23:26:49.740 回答