在Sinatra助手中生成JavaScript

时间:2011-05-12 20:33:49

标签: javascript ruby sinatra haml

我在基于Sinatra的Web应用程序中使用Haml作为我的模板语言,而且我在根据数据库模型的信息生成JavaScript数组时遇到了麻烦。基本上,我正在尝试生成一个由用户名组成的JavaScript数组,以便在jQuery-UI自动完成小部件中使用。

我尝试了以下代码,但它没有用。

:javascript
  var names = new Array;
  - User.all.each do |u|
    names.push(#{u})

在阅读之后,大多数人建议做一些涉及在帮助器中评估Ruby(即在Haml中以' - '为前缀的任何东西)的任何事情。那么,鉴于此,任何人都可以向我解释如何在辅助方法中生成JavaScript吗?

2 个答案:

答案 0 :(得分:4)

这里的问题是你不能在过滤器中使用普通的haml功能(例如:javascript)。但是,过滤器中的文本需要进行正常的ruby字符串插值,即#{}内的任何内容都作为Ruby代码执行。

因此,让你的榜样发挥作用的一种方法就是:

:javascript
  var names = new Array;
  #{js = ""
  User.all.each {|u| js << "names.push(#{u})\n" }
  js}

这是相当混乱的,而整理它的方法是把它变成一个帮手。帮助程序只是在渲染过程中处于范围内的方法(因此可以在haml文件中调用),并生成一些要包含在生成的页面中的文本。

在这种情况下,您正在生成javascript,但javascript只是文本,因此没有问题。辅助方法看起来像这样:

def js_array(name, array)
  js = "var #{name} = new Array();\n"
  array.each do |i|
    js << "#{name}.push(#{i})\n"
  end
  js
end

(或者你可以创建一个文字javascript数组:

def js_array(name, array)
  js = "var #{name} = ["
  js << array.collect{|i| "\"#{i}\""}.join(",")
  js << "]"
  js
end

如果您愿意的话。)

接下来,这个方法在哪里?在Sinatra中,您可以使用'helpers` method定义辅助方法。此块中定义的任何方法都将在您的视图中提供:

helpers do
  def js_array(name, array)
    js = "var #{name} = new Array();\n"
    array.each do |i|
      js << "#{name}.push(#{i})\n"
    end
    js
  end
end

有了这个,你就可以做到

:javascript
  #{js_array("names", User.all)}

在你的haml中生成你的javascript数组。请注意,您仍然需要#{}以便执行ruby代码,只是现在您只需要在大括号之间进行一次方法调用。 :javascript过滤器会将块包装在<script><![CDATA[标记中,帮助程序将创建您想要的实际javascript。

还有一件事:在你的例子中,数组是User.all,它看起来像是对activerecord或类似的东西的调用,在这种情况下你可能没有一个字符串数组,但是有一些其他对象可能没有给出你想要的结果。您可能需要执行以下操作:

:javascript
  #{js_array("names", User.all.collect(&:pretty_name)}

(其中pretty_nameUser对象上返回打印名称的方法,或者可能更改帮助方法以提取您要使用的字符串。

答案 1 :(得分:2)

您可能希望它返回名称数组,而不是让helper方法生成JavaScript,然后可以将其用作视图中jQuery UI Autocomplete小部件的源。

所以你的帮助方法看起来像这样:

helpers do
  # Return an array of users' names
  def get_all_names
    return User.all.map {|u| u.name}
  end
end

在你的汉姆尔:

:javascript
  $(function() {
    var names = #{get_all_names.to_json};
    $("#widget").autocomplete({ source: names });
  });