Конвейер ресурсов Rails 3.1: как загрузить скрипты, специфичные для контроллера?

Если я создам новый контроллер в Rails 3.1, также автоматически добавится файл javascript с именем контроллера. Во-первых, я думал, что этот файл javascript будет использоваться только при вызове соответствующего контроллера.

По умолчанию в файле application.js есть инструкция //= require_tree ., которая включает в себя каждый файл javascript на нем.

Как я могу загрузить только конкретный контроллер script?

Ответ 1

Чтобы загрузить только нужный файл name_of_the_js_file.js:

  • удалите //=require_tree из application.js

  • сохраните файл js (который вы хотите загрузить при загрузке определенной страницы) в конвейере активов

  • добавить помощника в application_helper.rb

    def javascript(*files)
      content_for(:head) { javascript_include_tag(*files) }
    end
    
  • введите в свой макет:

    <%= yield(:head) %>
    
  • Добавьте это в свой файл вида:

    <% javascript 'name_of_the_js_file' %>
    

Тогда это должно быть нормально

Ответ 2

Элегантным решением для этого является требование имени контроллера в вашем javascript_include_tag

см. http://apidock.com/rails/ActionController/Metal/controller_name/class

<%= javascript_include_tag "application", controller_name %>

имя_контроллера .js будет загружено и находится в активе также, поэтому вы можете потребовать от него другие файлы.

Пример: рендеринг автомобилей # index даст

<%= javascript_include_tag "application", "cars" %>

где cars.js может содержать

//= require wheel
//= require tyre

Наслаждайтесь!

Ответ 3

Я всегда включаю это в мои файлы макета. Он может объединить ваши js в действие

<%= javascript_include_tag params[:controller] if AppName::Application.assets.find_asset("#{params[:controller]}.js") %>
<%= javascript_include_tag "#{params[:controller]}_#{params[:action]}"  if AppName::Application.assets.find_asset("#{params[:controller]}_#{params[:action]}.js") %>

Ответ 4

Ваша проблема может быть решена по-разному.

Динамически добавлять активы

Пожалуйста, учтите, что это нехорошее решение для режима производства, потому что спецификации вашего контроллера не будут предварительно скомпилированы!

  • Добавьте к нашему прикладному помощнику следующий метод:

    module ApplicationHelper
        def include_related_asset(asset)
        #          v-----{Change this}
            if !YourApp::Application.assets.find_asset(asset).nil?
                case asset.split('.')[-1]
                    when 'js'
                        javascript_include_tag asset
                    when 'css'
                        stylesheet_link_tag asset
                end
            end
        end
    end
    
  • Вызовите вспомогательный метод в layout -file:

    <%= include_related_asset(params[:controller].to_param + '_' + params[:action].to_param . 'js') %>
    
  • Создайте определенные активы для действий вашего контроллера. E. g. controller_action.js

Пожалуйста, не забудьте изменить YourApp на имя вашего приложения.

Использовать yield

  • Добавьте <%= yield :head%> в свой макет.
  • Включите свои активы из ваших видов действий:

    <% content_for :head do %>
    <%= javascript_include_tag 'controller_action' %>
    <% end %>
    

Дополнительную информацию см. в Rails guide.

Ответ 5

Другой вариант - использовать pluggable_js gem.

Ответ 6

Мне нравится решение albandiguer. С помощью которых я обнаружил, что активы javascript/coffeescript не индивидуально предварительно скомпилированы. Который вызывает всевозможные ошибки, пытающиеся использовать javascript_path. Я поделюсь своим решением этой проблемы после того, как я затрону проблему, о которой упоминалось в его комментариях. В основном речь идет только о частичном наборе контроллеров с именами файлов JavaScript.

Итак, я создал помощник приложения, чтобы определить, существует ли файл в каталоге javascript независимо от расширения. coffee/.js:

module ApplicationHelper
  def javascript_asset_path(basename)
    Sprockets::Rails::Helper.assets.paths.select{|i|
      i =~ /javascript/ and i =~ /#{Rails.root}/
    }.each do |directory|
      if Dir.entries(directory).map {|i| i.split('.')[0]}.compact.
          include? basename
        return File.join(directory, basename)
      end
    end
    nil
  end
end

Этот метод вернет полный путь к файлу javascript, если он существует. В противном случае он возвращает nil. Поэтому, следуя комментарию Pencilcheck, вы можете добавить этот метод для условного включения:

<%= javascript_include_tag(controller_name) if javascript_asset_path(controller_name) %>

И теперь у вас есть надлежащее условное включение. Теперь о выпуске предварительно скомпилированных активов. Обычно для оптимизации вы не хотите, чтобы активы предварительно скомпилированы индивидуально. Однако вы можете сделать это, если вам нужно:

# Live Compilation
config.assets.compile = true

Вы можете добавить это в свой конфигурационный файл среды. Сначала проверьте его в файле среды разработки. Опять же, это необоснованно. Конвейер Rails использует Sprockets для оптимизации всего:

Sprockets загружает указанные файлы, обрабатывает их, если необходимо, объединяет их в один файл и затем сжимает их (если Rails.application.config.assets.compress - это правда). Отправляя один файл а не многие, время загрузки страниц может быть значительно уменьшено потому что браузер делает меньше запросов. Сжатие также уменьшает размер файла, что позволяет браузеру быстрее загружать их.

ПОЖАЛУЙСТА, ПРОЧИТАЙТЕ документацию для получения дополнительной информации о механизме Звездочки (Asset Pipeline) http://guides.rubyonrails.org/asset_pipeline.html

Активы не прекомпилируются отдельно. Например, когда я пытаюсь:

<%= javascript_include_tag 'event' %>

Я получаю:

Звездочки:: Rails:: Helper:: AssetFilteredError: отфильтрован объект и не будет обслуживаться: добавьте Rails.application.config.assets.precompile += %w( event.js ) в config/initializers/assets.rb и перезагрузите Сервер

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

Чтобы получить список имен контроллеров, я буду использовать экологовый пример:

all_controllers =  Dir[
    Rails.root.join('app/controllers/*_controller.rb')
  ].map { |path|
    path.match(/(\w+)_controller.rb/); $1
  }.compact

И теперь, чтобы получить имя всех файлов javascript, которые соответствуют базовому имени контроллера, вы можете использовать следующее:

javascripts_of_controllers = Sprockets::Rails::Helper.assets.paths.select{|a_path|
    a_path =~ /javascript/ and a_path =~ /#{Rails.root}/
  }.map {|a_path|
    Dir.entries(a_path)
  }.flatten.delete_if {|the_file|
    !the_file['.js']
  }.collect {|the_file|
    the_file if all_controllers.any? {|a_controller| the_file[a_controller]}
  }

Затем вы можете попробовать:

# config/initializers/assets.rb
Rails.application.config.assets.precompile += javascripts_of_controllers

Это даст вам список всех файлов javascript, без пути к каталогу, которые соответствуют имени вашего контроллера. Обратите внимание, что если имя вашего контроллера множественное, должно быть также имя javascript. Также обратите внимание, если контроллер сингулярный, а файл javascript - множественное число, это все равно будет включать его, поскольку the_file[a_controller] будет успешным с частичным совпадением.

Не стесняйтесь попробовать это в настройке Rails.application.config.assets.precompile. Я знаю, что это правильно отображает список файлов. Но я оставлю вас проверить это. Дайте мне знать, если есть какие-то нюансы, связанные с прекомпиляцией этого пути, поскольку мне любопытно.

Для очень подробного объяснения того, как активы прекомпилируют этот блог: http://www.sitepoint.com/asset-precompile-works-part/

Ответ 7

Недавно я нашел простой подход к использованию сгенерированных скриптов для конкретного контроллера. Я использую для этого решения gem gon. Добавить в контроллер:

class HomesController < ApplicationController
  before_filter :remember_controller

  private

  def remember_controller
    gon.controller = params[:controller]
  end
end

После этого откройте homes.js.cofee и добавьте в начало файла:

jQuery ->
  if gon.controller == "sermons"
    # Place all functions here...

Вот и все.