Конвейер ресурсов Rails 3.1: как загрузить скрипты для контроллера? - PullRequest
76 голосов
/ 04 июля 2011

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

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

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

Ответы [ 6 ]

122 голосов
/ 23 июля 2011

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

  1. удалить //=require_tree из application.js

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

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

    def javascript(*files)
      content_for(:head) { javascript_include_tag(*files) }
    end
    
  4. добавьте в свой макет:

    <%= yield(:head) %>
    
  5. добавьте это в свой файл просмотра:

    <% javascript 'name_of_the_js_file' %>
    

Тогда все должно быть в порядке

83 голосов
/ 20 октября 2011

Элегантное решение для этого - указать имя контроллера в вашем javascript_include_tag

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

<%= javascript_include_tag "application", controller_name %>

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

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

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

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

//= require wheel
//= require tyre

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

28 голосов
/ 22 октября 2012

Я всегда включаю это в мои файлы макета. Это может охватить ваши 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") %>
6 голосов
/ 25 июня 2012

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

Динамическое добавление ресурсов

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

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

    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
    
  2. Вызовите метод помощника в вашем layout -файле:

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

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

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

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

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

Пожалуйста, ознакомьтесь с Rails-руководствами для получения дополнительной информации.

3 голосов
/ 05 ноября 2014

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

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

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

<%= javascript_include_tag 'event' %>

Я получаю:

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

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

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

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/

1 голос
/ 09 августа 2013

Недавно я нашел простой подход к использованию сгенерированных скриптов для конкретного контроллера. Я использую для этого решения 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...

Это все.

...