Механизм ассетов в 3.1 сильно упростил жизнь большим проектам, но при этом немножко усложнил маленьким. При использовании встроенных генераторов, рельсы как и прежде создают отдельный файл для каждого контроллера, вот только теперь содержимое этих файлов появляется по-умолчанию на абсолютно всех страницах. Если в случае с SCSS это только помогает, навязывая правильное структурирование, то что делать с JS?
Если проект большой и вы используете для массивного JS какой-нибудь клиентский фреймворк вроде Backbone – отлично! Он будет лучше загружаться и сам решит где и как ему работать. Но что если нужно всего-лишь подключать небольшое количество кода для конкретных страниц? То есть даже не controller'ов, а скорее action'ов. И желательно чтобы когда таких кусочков стало больше 5 код не превратился в спагетти. С этим может помочь маленьий гем Styx.
Styx умеет не только вызывать конкретный код для конкретного action'а, но и передавать в него данные из Ruby. Приготовления:
Если у нас есть контроллер FoosController, который мы создали с помощью `rails g foos', то его стараниями у нас также есть не только app/controllers/foos_controller.rb, но и app/assets/javascripts/foos.js.coffee. Вот как должен выглядеть последний:
Обратите внимание, что все методы (кроме общего initialize) принимают параметр data. По умолчанию это пустой объект {}, но его можно легко пополнить со стороны руби как прямо в контроллере, так и во view:
Теперь мы получим в data:
Вот и все, что нужно, чтобы вызвать наш код. Благодаря тому, что JS собирается в один файл и подключается целиком, вы легко можете описывать ваш повторяющийся код в классах (именно классах, благодаря Coffee) и вызывать их на нужных страницах с помощью Initializer'ов. И в качестве приятного бонуса – никаких больше дампов ".to_json" для передачи данных в JS в ваших представлениях :).
Если проект большой и вы используете для массивного JS какой-нибудь клиентский фреймворк вроде Backbone – отлично! Он будет лучше загружаться и сам решит где и как ему работать. Но что если нужно всего-лишь подключать небольшое количество кода для конкретных страниц? То есть даже не controller'ов, а скорее action'ов. И желательно чтобы когда таких кусочков стало больше 5 код не превратился в спагетти. С этим может помочь маленьий гем Styx.
Styx умеет не только вызывать конкретный код для конкретного action'а, но и передавать в него данные из Ruby. Приготовления:
# Gemfile
gem 'styx'
# app/controllers/application_controller.rb или нужный вам controller
class ApplicationController
include Styx::Initializer
end
# app/views/application.html.erb
<%= javascript_include_tag "application" %>
<%= styx_initialize %>
<%= csrf_meta_tags %>
Если у нас есть контроллер FoosController, который мы создали с помощью `rails g foos', то его стараниями у нас также есть не только app/controllers/foos_controller.rb, но и app/assets/javascripts/foos.js.coffee. Вот как должен выглядеть последний:
# Класс называется по имени контроллера в неймспейсе Styx.Initializers.
@Styx.Initializers.Foos =
initialize: ->
console.log 'Этот метод будет вызван при попадании в любой action контроллера foos сразу после парсинга тега <head>'
index: (data) ->
console.log 'Этот метод будет вызван при попадании в /foos/ сразу после парсинга тега <head>'
show: (data) -> $ ->
console.log 'А вот таким образом (при использовании jQuery) можно вызвать метод после загрузки страницы /foos/... (см. jQuery.ready())'
Обратите внимание, что все методы (кроме общего initialize) принимают параметр data. По умолчанию это пустой объект {}, но его можно легко пополнить со стороны руби как прямо в контроллере, так и во view:
# app/controllers/foos_controller.rb
class ApplicationController
def index
styx_initialize_with :foo => 'bar', :and => {:habrahabr => 'rockz!'}
end
end
# app/views/foos/index.html.erb
<%- styx_initialize_with :something => 'very important' %>
Теперь мы получим в data:
{"foo": "bar", "and": {"habrahabar": "rocks!"}, "something": "very important"}
Вот и все, что нужно, чтобы вызвать наш код. Благодаря тому, что JS собирается в один файл и подключается целиком, вы легко можете описывать ваш повторяющийся код в классах (именно классах, благодаря Coffee) и вызывать их на нужных страницах с помощью Initializer'ов. И в качестве приятного бонуса – никаких больше дампов ".to_json" для передачи данных в JS в ваших представлениях :).