2012-11-27 65 views
1

我已經看到很多圍繞這個話題的問題,但沒有確定的解決方案。我有一個利用ERB/slim和Coffeescript/EJS/Backbone的Rails 3.2應用程序。我繼承了這個代碼庫,所以這些外圍設備有些超出我的想象。Ajax更新後可以使用ERB/slim模板而不是EJS(JST)嗎?

問題

venue視圖具有顯示已提交給venuetips的截面。 tips列表具有JavaScript提供的「排序」功能。關聯的CoffeeScript文件具有用於「最近」和「流行」鏈接點擊的事件偵聽器。點擊後,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),但Rails助手(如time_ago_in_words)失敗,抱怨該方法對於該類未定義,儘管我絕對傳遞了適當的日期對象。不能在這個.EJS.ERB鏈中評估Rails/helper嗎?
  3. 如果在執行排序後有一種方法可以引用原始ERB /苗條部分,那麼我可以規避所有這些問題。這可能嗎?現在,調用的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> 

在這裏絕對是一個損失 - 任何和所有的幫助,非常感謝。讓我知道如果有任何其他細節或代碼我可以提供背景。提前致謝!

+0

的解決方案似乎是有點哈克,特別是更新方法。對此,我還不清楚如何獲取JS可以訪問的數據,例如created_at,並將其傳遞給time_ago_in_words的評估。 – justinraczak

回答

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

+0

這工作出色,謝謝!我也很欣賞指向最佳實踐的想法。鑑於我有多新(特別是JS),我現在要堅持這種解決方法,因爲性能還不是我的問題,但稍後會重構使用客戶端解決方案的最佳實踐。再次感謝您的幫助,真的非常感謝! – justinraczak

相關問題