Đường dẫn nội dung Rails 3.1: cách tải các tập lệnh dành riêng cho bộ điều khiển?


76

Nếu tôi tạo một bộ điều khiển mới trong Rails 3.1, thì một tệp javascript có tên của bộ điều khiển cũng sẽ tự động được thêm vào. Đầu tiên, tôi nghĩ rằng tệp javascript này sẽ chỉ được sử dụng khi bộ điều khiển liên quan được gọi.

Theo mặc định, có hướng dẫn //= require_tree .trong application.js-tệp, bao gồm mọi tệp javascript trên cây của nó.

Làm cách nào để chỉ tải tập lệnh cụ thể của bộ điều khiển?


3
Nó có thể không phải là một ý tưởng tốt để làm điều đó. Vui lòng xem câu trả lời cho câu hỏi liên quan này: stackoverflow.com/questions/8250951/…
gdelfino

1
Viết javascript của bạn sao cho nó dành riêng cho từng trang và sau đó đừng lo lắng về thực tế là mọi thứ được trộn với nhau. Nếu đây là mã được biên dịch, đó là những gì bạn phải làm, phải không?
Ziggy

Câu trả lời:


122

Để chỉ tải tệp name_of_the_js_file.js cần thiết:

  1. loại bỏ //=require_treekhỏiapplication.js

  2. giữ tệp js của bạn (mà bạn muốn tải khi một trang cụ thể được tải) trong đường dẫn nội dung

  3. thêm một người trợ giúp vào application_helper.rb

    def javascript(*files)
      content_for(:head) { javascript_include_tag(*files) }
    end
    
  4. đưa vào bố cục của bạn:

    <%= yield(:head) %>
    
  5. thêm cái này vào tệp xem của bạn:

    <% javascript 'name_of_the_js_file' %>
    

Vậy thì nó sẽ ổn thôi


2
Cần lưu ý rằng phương pháp này hoạt động tốt trong sản xuất. Ví dụ: nếu bạn nhìn vào nguồn trong sản xuất, bạn sẽ thấy rằng tệp javascript bộ điều khiển riêng lẻ có tên chặn bộ nhớ cache thích hợp, giống như tệp application.js chính: <script src = "/ asset / mycontroller-923cef714b82e7dec46117f9aab7fb2c.js" type = "text / javascript"> </script>
cailinanne

Có vì bản thân tệp nằm trong quy trình nội dung. Chúng tôi chỉ không muốn nó được yêu cầu trong application.js.
Nguyễn Chiến Công

1
Bạn có thể cụ thể hơn không? có lẽ tôi có thể giúp.
Nguyễn Chiến Công

13
đảm bảo thêm vào config/application.rbdòng của bạn như config.assets.precompile += %w(name_of_js_file.js)hoặc bạn có thể gặp sự cố biên dịch trước như tôi đã làm. Xem thêm jalada.co.uk/2012/01/23/…
ZMorek

1
làm việc cho tôi trong đường ray 3.2.3 (yêu cầu tùy chọn config.assets.precompile này theo quy định của ZMorek trên)
Tatiana Tyu

83

Một giải pháp thanh lịch cho việc này là yêu cầu tên_điều_khiển trong javascript_include_tag của bạn

xem http://apidock.com/rails/ActionController/Metal/controller_name/class

<%= javascript_include_tag "application", controller_name %>

controller_name.js sẽ được tải và cũng nằm trong phần tử, vì vậy bạn có thể yêu cầu các tệp khác từ đây.

Ví dụ, chỉ mục hiển thị ô tô # sẽ cho

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

nơi ô tô.js có thể chứa

//= require wheel
//= require tyre

Thưởng thức !


Trong khi điều này là rõ ràng sau khi đọc nó, giải pháp không xảy ra ngay lập tức với tôi.
Andrew Burns

11
Nếu bạn không có tệp cho mỗi tệp, controller_name.jsbạn có thể gặp một số vấn đề biên dịch trước và bỏ sót bộ nhớ cache, đặc biệt nếu bạn không biên dịch trước rõ ràng mọi vấn đề trong số đó.
ZMorek

Các vấn đề biên dịch trước được giải quyết bằng cài đặt config.assets.precompile - xem nhận xét của ZMorek để có câu trả lời khác cho câu hỏi này.
Tatiana Tyu

1
Tốt hơn: <% = javascript_include_tag controller_name nếu asset_path (controller_name)%> <% = stylesheet_link_tag controller_name, phương tiện truyền thông: "tất cả" nếu asset_path (controller_name)%>
Pencilcheck

1
@Pencilcheck Giải pháp của bạn không hoạt động. asset_pathlợi nhuận luôn luôn là một con đường, thậm chí nếu các tập tin không tồn tại
Alter Lagos

28

Tôi luôn bao gồm điều này bên trong các tệp bố cục của mình. Nó có thể phạm vi hành động của js của bạn

<%= 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") %>

1
Mặc dù tôi thực sự thích điều này, nó có vẻ không hiệu quả trong quá trình sản xuất.
janosrusiczki,

Giải pháp tốt nhất, tôi cho là vậy.
installero

3
@kitsched - bạn có thể cần phải thêm toàn bộ tài sản của mình để config.assets.precompile qua một cái gì đó giống như stackoverflow.com/a/18992685/94668
TomFuertes

Cảm ơn, sẽ thử.
janosrusiczki 16/1013

Đây là giải pháp tốt nhất cho tôi. Và nó hoạt động trong sản xuất.
Jay

6

Vấn đề của bạn có thể được giải quyết theo nhiều cách khác nhau.

Thêm nội dung động

Vui lòng lưu ý rằng đây không phải là giải pháp tốt cho chế độ sản xuất, vì thông tin chi tiết về bộ điều khiển của bạn sẽ không được biên dịch trước!

  1. Thêm vào trình trợ giúp ứng dụng của chúng tôi theo phương pháp sau:

    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. Gọi phương thức trợ giúp trong layout-tệp của bạn :

    <%= include_related_asset(params[:controller].to_param + '_' + params[:action].to_param . 'js') %>
    
  3. Tạo nội dung cụ thể cho các hành động của bộ điều khiển của bạn. Ví dụ.controller_action.js

Xin đừng quên thay đổi YourApptên ứng dụng của bạn.

Sử dụng yield

  1. Thêm vào <%= yield :head%>đầu bố cục của bạn
  2. Bao gồm nội dung của bạn từ chế độ xem hành động của bạn:

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

Vui lòng xem hướng dẫn Rails để biết thêm thông tin.


3

Tôi thích giải pháp của albandiguer . Tôi thấy rằng nội dung javascript / coffeescript không được biên dịch trước riêng lẻ. Nguyên nhân gây ra tất cả các loại lỗi khi cố gắng sử dụng javascript_path. Tôi sẽ chia sẻ giải pháp của mình cho vấn đề đó sau khi tôi giải quyết vấn đề mà một vài người đã đề cập trong nhận xét của anh ấy. Chủ yếu chỉ xử lý một phần bộ điều khiển có tên tệp JavaScript.

Vì vậy, tôi đã xây dựng một trình trợ giúp ứng dụng để phát hiện xem tệp có tồn tại trong thư mục javascript bất kể phần mở rộng .coffee / .js hay không:

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

Phương thức này sẽ trả về đường dẫn đầy đủ đến tệp javascript nếu nó tồn tại. Nếu không, nó trả về nil. Vì vậy, sau nhận xét của Pencilcheck, bạn có thể thêm phương thức này cho một bao gồm có điều kiện:

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

Và bây giờ bạn có một bao gồm có điều kiện thích hợp. Bây giờ là vấn đề về nội dung được biên dịch trước. Nói chung để tối ưu hóa, bạn không muốn các nội dung được biên dịch trước riêng lẻ. Tuy nhiên, bạn có thể làm điều đó nếu bạn phải:

# Live Compilation
config.assets.compile = true

Bạn có thể thêm điều này làm tệp cấu hình môi trường của bạn. Kiểm tra nó trong tệp môi trường phát triển của bạn trước. Một lần nữa điều này là không nên. Đường dẫn nội dung Rails sử dụng Sprockets để tối ưu hóa mọi thứ:

Sprockets tải các tệp được chỉ định, xử lý chúng nếu cần, nối chúng thành một tệp duy nhất và sau đó nén chúng (nếu Rails.application.config.assets.compress là true). Bằng cách phân phát một tệp thay vì nhiều tệp, thời gian tải của các trang có thể giảm đáng kể vì trình duyệt đưa ra ít yêu cầu hơn. Nén cũng làm giảm kích thước tệp, cho phép trình duyệt tải chúng xuống nhanh hơn.

VUI LÒNG ĐỌC tài liệu để biết thêm chi tiết về cơ chế của Sprockets (Đường ống tài sản) http://guides.rubyonrails.org/asset_pipeline.html

Nội dung không được biên dịch trước riêng lẻ. Ví dụ khi tôi thử:

<%= javascript_include_tag 'event' %>

Tôi có:

Sprockets :: Rails :: Helper :: AssetFilteredError: Nội dung bị lọc ra và sẽ không được phân phát: thêm Rails.application.config.assets.precompile += %w( event.js )vào config/initializers/assets.rbvà khởi động lại máy chủ của bạn

Vì vậy, bạn có thể bao gồm các nội dung được biên dịch trước riêng lẻ. Chúng tôi chỉ cần thêm trình điều khiển có tên tệp javascript có liên quan vào trình khởi tạo nội dung của chúng tôi. Chúng ta có thể làm điều này theo chương trình.

Để có danh sách tên bộ điều khiển, tôi sẽ sử dụng ví dụ của ecoologic :

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

Và bây giờ để lấy tên của tất cả các tệp javascript khớp với tên cơ sở của tên bộ điều khiển, bạn có thể sử dụng như sau:

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]}
  }

Sau đó, bạn có thể thử:

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

Thao tác này sẽ giúp bạn có được danh sách tất cả các tệp javascript, không có đường dẫn thư mục, khớp với tên bộ điều khiển của bạn. Lưu ý nếu tên bộ điều khiển của bạn là số nhiều thì tên javascript cũng phải như vậy. Cũng lưu ý nếu bộ điều khiển là số ít và tệp javascript là số nhiều, điều này sẽ vẫn bao gồm nó vì the_file[a_controller]sẽ thành công trên một phần đối sánh.

Hãy thử điều này trong Rails.application.config.assets.precompilecài đặt của bạn . Tôi biết rằng điều này giúp bạn có được danh sách các tệp một cách chính xác. Nhưng tôi sẽ để bạn kiểm tra nó. Hãy cho tôi biết nếu có bất kỳ sắc thái nào liên quan đến việc biên dịch trước theo cách này khi tôi tò mò.

Để được giải thích cặn kẽ về cách biên dịch trước nội dung, hãy xem blog này: http://www.sitepoint.com/asset-precompile-works-part/


tôi nên đặt câu lệnh all_controllers và javascripts_of_controllers?
Konstantin Voronov

1
tốt. tôi đã đặt cả hai vào trình khởi tạo tài sản của mình (tài sản.rb) nhưng Sprockets :: Rails :: Helper.assets.paths ở đây không có giá trị nên tôi phải thay đổi nó thành Rails.application.config.assets.paths phần còn lại vẫn ổn. very nice giải pháp
Konstantin Voronov

1

Gần đây tôi đã tìm thấy một cách tiếp cận đơn giản để sử dụng các tập lệnh được tạo cho bộ điều khiển cụ thể. Tôi sử dụng cho gon giải pháp đó . Thêm bộ điều khiển:

class HomesController < ApplicationController
  before_filter :remember_controller

  private

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

Sau đó, mở của bạn homes.js.cofeevà thêm vào đầu tệp:

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

Đó là tất cả.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.