Ошибка «Не удается найти переменную» в Rails 3.1 и Coffeescript

#javascript #ruby-on-rails #coffeescript

#javascript #ruby-на-рельсах #coffeescript #ruby-on-rails

Вопрос:

В моем приложении есть представления, которые ссылаются на мой application.js файл, содержащий функции, которые я использую во всем моем приложении.

Я только что установил Rails 3.1 release candidate после использования edge версии 3.1. Пока я не установил RC, у меня не было никаких проблем, но теперь я получаю эту ошибку:

Ошибка ReferenceError: не удается найти переменную: indicator_tag

indicator_tag — это функция, которую я определил в application.js . Единственное отличие, которое я замечаю в файле javascript, заключается в том, что теперь все мои функции обернуты в:

 (function() { ... }).call(this);
  

Я так понимаю, это для определения области видимости переменной? Но может ли это помешать моим страницам использовать эти переменные? И прежде чем кто-либо спросит, я убедился, что пути javascript указаны правильно в моих тегах include.

Комментарии:

1. Вы пытаетесь сослаться на indicator_tag из файла, отличного от application.js.coffee?

2. Нет, это в application.js.coffee.

3. Не могли бы вы вставить содержимое вашего скрипта?

4. Вы пытаетесь вызвать indicator_tag из встроенных скриптов, на ваш взгляд?

5. Не встроенный, а отдельный файл javascript только для этой страницы. Тег include для этого файла находится ниже тега для application.js . Вот содержимое этого файла pastie.org/1957528

Ответ №1:

По умолчанию каждый файл CoffeeScript компилируется в замыкание. Вы не сможете взаимодействовать с функциями из другого файла, если не экспортируете их в глобальную переменную. Я бы рекомендовал сделать что-то вроде этого:

Поверх каждого файла coffeescript добавьте строку типа

 window.Application ||= {}
  

Это гарантирует постоянное присутствие приложения с глобальным именем.

Теперь для каждой функции, которую вам потребуется вызвать из другого файла, определите их как

 Application.indicator_tag = (el) ->
  ...
  

и вызываем их с помощью

 Application.indicator_tag(params)
  

Комментарии:

1. Ответ Догберта правильный. (Обратите внимание, что в этом случае вы также могли бы использовать this / @ для экспорта переменных как глобальных, например @indicator_id = ... , поскольку оболочка CoffeeScript вызывается в глобальном контексте). Причина, по которой вы столкнулись с этим только сейчас, заключается в том, что более ранние версии Rails 3.1 отключили оболочку CoffeeScript. Это поведение было классифицировано как ошибка и исправлено для RC1: github.com/rails/rails/issues/1125

2. Я бы дал вам 10 секунд, если бы мог, за этот ответ. Большое спасибо.

Ответ №2:

Решение Догберта — отличный вариант, если у вас очень сложный сервер JS. Однако есть гораздо более простое решение, если у вас есть только несколько функций, с которыми вы работаете. Просто добавьте их непосредственно в объект window, вот так:

 window.indicator_tag = (el) ->
  ...
  

Тогда вы сможете использовать свои функции из любого места без необходимости оборачивать их в другой объект.

Комментарии:

1. Что плохого в том, чтобы обернуть их в другой объект? Если вы хотите избежать ввода «Application», назовите это «App». Контекст часто действительно полезен в любом случае, когда вы просто читаете код…

2. И я бы добавил, чем это «окно». это то же самое, что «@», не так ли?