Pull to refresh

Comments 17

Кто-нибудь напишет перевод этой статьи на Хабр?
Джем интересный, а что генерирует хелпер javascript_pluggable_tag? Если он подключает js файл, то нужно будет указать его в массиве precompile в production.rb.
А если вместо подключения файла просто вызывать нужную функцию js? Ведь тогда не нужно будет делать лишний запрос.
javascript_pluggable_tag – это javascript_include_tag, который подключает js только при наличии файла по пути: Rails.root + "app/assets/javascripts/pluggable/#{controller}/#{action}.js.coffee". Поэтому вы правы – в продакшн среде должна присутствовать строка: config.assets.precompile += %w(pluggable/*). Об этом написано в ридми джема. Не стал включать в статью, чтобы не перегружать информацией.

Можно было бы вызвать функцию напрямую из вью, но решение с использованием генератора избавляет от написания дополнительного кода и сохраняет вью чистым. Я подумал, что лишний запрос будет не таким страшным, поскольку в файле находится всего-лишь вызов функции, и это не должно сильно повлиять на производительность.
Я имею ввиду, что вью оставим чистым, но вместо javascript_include_tag('...') сделаем: javascript_tag "Post.index()"
В этом случае не нужно вносить объявление файла в массив precompile и нет еще одного запроса. =)
Я подумал автоматизировать процесс, чтобы вам не писать javascript_tag. А лишний запрос мне показался нестрашным.
javascript_tag писать не нужно, я не очень ясно выразился. Мы по прежнему в layout пишем <%= javascript_pluggable_tag %>, но суть хелпера меняется. Вот посмотрим код метода:

def javascript_pluggable_tag
  controller = params[:controller]
  action = define_pair_action

  if File.exist?(Rails.root + "app/assets/javascripts/pluggable/#{controller}/#{action}.js.coffee")
    javascript_include_tag "pluggable/#{controller}/#{action}"
  end
end

Можно написать альтернативный метод:

def javascript_pluggable_call
  controller = params[:controller]
  action = define_pair_action

  javascript_tag "#{ controller.camelize }.#{ action }()"
end

Таким образом все скрипты попадают в один скомпилированный application.js

Другое дело если скрипт достаточно большой и применяется лишь изредка (например настройка и вызов TinyMCE, CKEditor, Fineuploader и т.п.), то файл можно подгружать отдельно, тогда нам кроме application.js нужно подгружать например posts/new.js

Предлагаю сделать 2 хелпера, чтобы можно было выбирать подгружать отдельный файл или вызывать функцию, передавать хелперам что-нибудь типа only:… и except:… как необязательные параметры (или тоже самое реализовать в инициализаторе).

Для отдельного большого скрипта для определенного набора страниц:
javascript_pluggable_tag only: %w(posts/new*)

Для вызова функции для определенного набора страниц:
javascript_pluggable_call except: %w(users/*)
Ну это же просто прекрасно, спасибо большое, зреет новая версия.

Есть мысль оставить один хелпер, а текущий генератор подточить для большого скрипта.
Хелпер будет выглядеть примерно так:

def javascript_pluggable_tag
  controller = params[:controller]
  action = define_pair_action

  if File.exist?(Rails.root + "app/assets/javascripts/pluggable/#{controller}/#{action}.js.coffee")
    javascript_include_tag "pluggable/#{controller}/#{action}"
  else
    javascript_tag "#{controller.camelize}.#{action}();"
  end
end

Таким образом, если файл существует, то подключится большой скрипт, в противном случае вызовется функция.
По моему мнению, использование данного плагина — излишнее усложнение. И добавление пары строк (решение с javascript_include_tag) чище.

Но минус такого подхода в том, что скрипты, относящиеся определенному контроллеру, не находятся в одном месте (а значит тяжелее искать и разбираться). В довесок, если кусок кода большой, то мы теряем преимущества пайплайна.

Неясные аргументы, есть примеры?

И второе, а что если скрипт нужно подключить не только на определенной странице, но и только если у пользователя есть определенная роль в приложении?
На самом деле я и мои коллеги часто сталкиваемся с тем, что забываем сделать в нужной вьюхе (обычно вложенные partials) требуемый javascript_include_tag или вызов других функций. Некоторое количество времени на отладку все-таки можно сэкономить.

Что касается роли, тут нужно расширять функции джема, например можно реализовать DSL в инициализаторе для определения условий подключения отдельно скомпилированного файла или вызова функции, в хелпер можно передавать дополнительные параметры, если требуется.
Неясные аргументы, есть примеры?

Может это дело вкуса, но мне показалось очень удобным, когда все скрипты находятся в "#{params[:controller]}.js.coffee". Часть из них общие, часть подключаемые. Так проще разобраться. Преимущества пайплайна очевидны, а голый javascript_include_tag делает дополнительный запрос на сервер. Это может отразиться на производительности, если кусок кода большой. В джеме просто вызывается функция, которая хранится в application.js.

Относительно роли, спасибо, об этом не подумал. Последую совету owls.
Может это дело вкуса, но мне показалось очень удобным, когда все скрипты находятся в "#{params[:controller]}.js.coffee".

Согласен, но это больше дело дисциплины разработчиков при соблюдении конвенций именования и расположения кода, или нет? :)

Преимущества пайплайна очевидны, а голый javascript_include_tag делает дополнительный запрос на сервер. Это может отразиться на производительности, если кусок кода большой.

Также ничего не мешает добавить скрипт (или манифест аналогичный application.js) подключенный через javascript_include_tag к config.assets.precompile. А дополнительный запрос будет в обоих случаях.
Если я правильно понял суть джема состоит в том, что вам не нужно подключать скрипт во views, а только объявить в layout, такие вьюхи немного легче поддерживать, мне нравится этот подход тем, что логика js полностью отделяется от разметки в представлениях.
Использование обычного javascript_include_tag никак не позволит вам хранить все в "#{params[:controller]}.js.coffee". Да, запрос будет в обоих случаях. Здесь вся соль в том, что вызывается функция из application.js а не скрипт из отдельного файла.

Джем – это лишь предложение чуть получше организовать подключаемый js. Запускать генераторы и объявлять функции должно быть проще, чем писать все самому.
Есть gem styx, предназначенный для этой же цели.
Только там весь JS собирается в один файл вместо подключения отдельных файлов на отдельных страницах, просто при переходе на определённую страницу вызывается определённая функция. И не надо, соответственно, ничего в config.assets.precompile добавлять.
Здесь двоякий вопрос. Одно дело когда нужно структурировать js-код.
Другое дело — подключать определенные js-файлы только на определенных страницах (и/или для определенных пользователей). Например, ckeditor имеет тонну js и используется только админами приложения. Соответственно загружать для обычных пользователей эту кучу js не стоит.
Ну если есть js, нужный только админам, то можно просто сделать отдельный js-манифест для админки. Там, конечно, уже отдельный вопрос, нужен ли в манифесте ckeditor.
Sign up to leave a comment.

Articles