#javascript #ruby #sinatra #haml
#javascript #ruby #sinatra #haml
Вопрос:
Я использую Haml в качестве языка шаблонов в веб-приложении на базе Sinatra, и у меня возникли проблемы с генерацией массива JavaScript на основе информации из модели базы данных. По сути, я пытаюсь сгенерировать массив JavaScript, состоящий из имен пользователей, для использования в виджете автозаполнения jQuery-UI.
Я попробовал следующий код, но он не сработал.
:javascript
var names = new Array;
- User.all.each do |u|
names.push(#{u})
После прочтения большинство людей предлагают делать все, что связано с вычислением Ruby (т. Е. Чего-либо с префиксом ‘-‘ в Haml) в помощнике вместо этого. Итак, учитывая это, кто-нибудь может объяснить мне, как сгенерировать JavaScript в вспомогательном методе?
Ответ №1:
Проблема здесь в том, что вы не можете использовать обычные функции 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(amp;:pretty_name)}
(где pretty_name
— это метод для User
объекта, который возвращает имя для печати), или, возможно, измените вспомогательный метод, чтобы извлечь строку, которую вы хотите использовать.
Комментарии:
1. Потрясающе, спасибо, Мэтт! Я отмечаю это как ответ, потому что в нем показано, как использовать помощник для генерации javascript для использования с haml.
Ответ №2:
Вместо того, чтобы вспомогательный метод генерировал JavaScript, вы, вероятно, хотите, чтобы он возвращал массив имен, которые затем можно использовать в качестве источника для виджета автозаполнения пользовательского интерфейса jQuery в представлении.
Итак, ваш вспомогательный метод будет выглядеть примерно так:
helpers do
# Return an array of users' names
def get_all_names
return User.all.map {|u| u.name}
end
end
И в вашем Haml:
:javascript
$(function() {
var names = #{get_all_names.to_json};
$("#widget").autocomplete({ source: names });
});
Комментарии:
1. Спасибо, Кунал! Это тоже было полезно, потому что это говорит мне, как использовать результаты из помощника в существующей функции javascript.