Rails/Javascript: 如何将Rails变量注入(非常)简单的Javascript代码中

4

我希望在Rails中编写一个非常简单的JavaScript计算器,它将输入字段的数量乘以存储在Rails变量(@item.base_price)中的数字。

因此,在JavaScript / CoffeeScript方面,它大致如下:

# app/assets/javascript/items.js.coffee
$ -> 
  $('#item_quantity').change ->
    quantity_val = $(this).val()
    $('#total_amount').html(quantity_val * <%= I_WANT_@ITEM.BASE_PRICE_HERE %>)

我知道我可以通过在每个change()调用上使用ajax请求来完成这个操作,但我认为应该有一种优雅的、不打扰的Rails方式,不需要每次都访问服务器。非常感谢任何建议。
3个回答

6

如果你正在使用Rails 3.1,你可以利用资产管道在服务JavaScript文件之前对其进行一些预处理。只需更改文件扩展名:

items.js.coffee

to

items.js.coffee.erb

那么,您可以像在视图中使用<%= %>标签一样,在JavaScript中添加Ruby。唯一可能遇到的问题是,您的items.js文件将为应用程序的任何控制器方法的每个请求提供服务。因此,最好编写一个辅助方法,仅在实例变量初始化时返回值。

例如,在items_helper.rb中:

def item_price
    if @item
        @item.base_price
    else
        0
    end
end

编辑:有关资产管道的更多信息,请参见:

http://guides.rubyonrails.org/asset_pipeline.html


2

尽管如此,如果您将Javascript文件作为静态资源提供,这可能不是最佳选择。我通常在HTML的部分中使用script标签来放置变量。这样,JS就不必重建并且浏览器缓存也不需要无效化。例如:

<head>
  <script type="text/javascript">
    var myGlobalVariable = <%= @global_js_variable %>;
  </script>
</head>

虽然这对于保持各自名称空间中的事物不太好,但可以减少向客户端发送新JavaScript文件的开销。

只是一个想法。


1
虽然这对于保持命名空间的独立性来说不太好,但可以使用setter来保持根命名空间的清洁:SomeExistingGlobalVar.my_variable = <%= @my_variable %>; - zuba

0

使用资产管道在每个请求基础上处理带有ERB的CoffeeScript文件可能对开发来说没问题,但在生产中会成为瓶颈。

在生产中,我使用全局变量或全局变量的特定属性来减少污染。

在页面的ERB视图底部:

<script>
  //<![CDATA[
    window.MyApp = window.MyApp || {};
    window.MyApp.itemBasePrice = <%=j @item.base_price.to_json.html_safe %>;
  //]]>
</script>

将脚本放在页面底部(样式表放在顶部),因为这会导致更快的页面加载时间。

我强烈建议阅读这篇文章如何在Rails视图中安全引导JSON。在撰写本文时,Rails的最新版本在引导JSON时容易受到XSS攻击。如果只有一个简单的数字,可能不是问题。但我发现,当人们看到你的代码工作后,他们倾向于简单地将其复制/粘贴到更复杂的情况中,而不考虑后果。

或者,如果您的数据具有自然容器,则可以将其嵌入数据属性中。

<div id="item" data-base-price="<%=j @item.base_price.to_json.html_safe %>"></div>

在你的CoffeeScript中访问它:

console.log $('#item').data('basePrice')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接