Генерация JavaScript в помощниках Синатры - PullRequest
3 голосов
/ 13 мая 2011

Я использую Haml в качестве языка шаблонов в веб-приложении на основе Sinatra, и у меня возникают проблемы при создании массива JavaScript на основе информации из модели базы данных. По сути, я пытаюсь сгенерировать массив JavaScript, состоящий из имен пользователей, для использования в виджете автозаполнения jQuery-UI.

Я попробовал следующий код, но он не работал.

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

После прочтения большинство людей предлагают сделать что-нибудь, что включает в себя оценку Ruby (то есть что-нибудь с префиксом '-' в Haml) вместо помощника. Итак, учитывая это, кто-нибудь может объяснить мне, как генерировать JavaScript с помощью вспомогательного метода?

Ответы [ 2 ]

4 голосов
/ 14 мая 2011

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

2 голосов
/ 14 мая 2011

Вместо того, чтобы вспомогательный метод генерировал 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 });
  }); 
...