Проблема в том, что вы не можете использовать обычные функции 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` метод . Любые методы, определенные в этом блоке, будут доступны в ваших представлениях:
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_name
- метод объекта User
, который возвращает имя для печати) или, возможно, измените вспомогательный метод для извлечения строки, которую вы хотите использовать.