略過至內容 略過至搜尋

Action View 資源 URL 輔助函式

此模組提供用於產生資源路徑及 URL 的方法。

image_path("rails.png")
# => "/assets/rails.png"

image_url("rails.png")
# => "http://www.example.com/assets/rails.png"

使用資源主機

預設情況下,Rails 在 public 資料夾中的目前主機上連結至這些資源,但您可以將 Rails 設定為從專用資源伺服器連結至資源,方法是在應用程式設定中設定 ActionController::Base.asset_host,通常是在 config/environments/production.rb 中。例如,您會以這種方式定義 assets.example.com 為您的資源主機,在您的環境特定設定檔的 configure 區塊內或在 config/application.rb 中。

config.action_controller.asset_host = "assets.example.com"

Helpers 將這點納入考量

image_tag("rails.png")
# => <img src="http://assets.example.com/assets/rails.png" />
stylesheet_link_tag("application")
# => <link href="http://assets.example.com/assets/application.css" rel="stylesheet" />

瀏覽器對單一主機開啟有限數量的同時連線。實際數量會依據瀏覽器和版本而異。此限制可能會導致一些資源下載必須等到前一個資源完成後才能開始。您可以在 asset_host 中使用 %d 萬用字元,以將請求分散到四個主機上。例如,assets%d.example.com 會將資源請求分散在「assets0.example.com」…「assets3.example.com」上。

image_tag("rails.png")
# => <img src="http://assets0.example.com/assets/rails.png" />
stylesheet_link_tag("application")
# => <link href="http://assets2.example.com/assets/application.css" rel="stylesheet" />

這可能會改善您應用程式的資源載入效能。不過,這種組合的額外連線負擔 (DNS、SSL) 和瀏覽器的整體連線限制,也有可能讓這種解決方案變慢。您需要在套用這個變更前後,仔細衡量目標瀏覽器的實際效能。

要實作對應的主機,您可以設定四個實際主機,或使用萬用字元 DNS 將萬用字元轉向單一資源主機。您可以從您的 ISP 中取得更多有關設定您的 DNS CNAME 記錄的資訊。

注意:這純粹是瀏覽器效能最佳化,並非用於伺服器負載平衡。請參閱 www.die.net/musings/page_load_time 取得背景資訊,並參閱 www.browserscope.org/?category=network 取得連線限制資料。

或者,您可以透過將 asset_host 設定為類似以下內容的程序,對資源主機產生更大的控制權:

ActionController::Base.asset_host = Proc.new { |source|
  "http://assets#{OpenSSL::Digest::SHA256.hexdigest(source).to_i(16) % 2 + 1}.example.com"
}
image_tag("rails.png")
# => <img src="http://assets1.example.com/assets/rails.png" />
stylesheet_link_tag("application")
# => <link href="http://assets2.example.com/assets/application.css" rel="stylesheet" />

以上的範例產生的是「assets1.example.com」和「assets2.example.com」。如果需要少於/多於四個主機、自訂主機名稱等,這種選項會很有用。

您看到的程序使用 source 參數。那是一個字串,包含資源的絕對路徑,例如「/assets/rails.png」

 ActionController::Base.asset_host = Proc.new { |source|
   if source.end_with?('.css')
     "http://stylesheets.example.com"
   else
     "http://assets.example.com"
   end
 }
image_tag("rails.png")
# => <img src="http://assets.example.com/assets/rails.png" />
stylesheet_link_tag("application")
# => <link href="http://stylesheets.example.com/assets/application.css" rel="stylesheet" />

或者,您可以要求 request 提供第二個參數。這一點特別適用於從受 SSL 保護的網頁提供資源。以下的程序範例停用了對於 HTTPS 連線的資源主機,但仍會傳送來自資源主機的純 HTTP 請求的資源。如果您沒有每個資源主機的 SSL 憑證,這種技術可讓您避免用戶端中關於混合媒體的警告。請注意,request 參數可能會不予提供,例如當資源使用 bin/rails assets:precompile 指令進行預編譯時。務必使用 Proc 代替 lambda,因為 Proc 允許參數遺失並將參數設定為 nil

config.action_controller.asset_host = Proc.new { |source, request|
  if request && request.ssl?
    "#{request.protocol}#{request.host_with_port}"
  else
    "#{request.protocol}assets.example.com"
  end
}

您也可以實作自訂的資源主機物件,它會回應 call 呼叫,並且就像程序一樣,可以接受一個或兩個參數。

config.action_controller.asset_host = AssetHostingWithMinimumSsl.new(
  "http://asset%d.example.com", "https://asset1.example.com"
)
方法
A
C
F
I
J
P
S
U
V

常量

ASSET_EXTENSIONS = { javascript: ".js", stylesheet: ".css" }
 
ASSET_PUBLIC_DIRECTORIES = { audio: "/audios", font: "/fonts", image: "/images", javascript: "/javascripts", stylesheet: "/stylesheets", video: "/videos" }
 

將資源類型對應到公開目錄。

URI_REGEXP = %r{^[-a-z]+://|^(?:cid|data):|^//}i
 

實例公用方法

asset_path(source, options = {})

所有資源的入口點。當使用資源管線 gem(例如,propshaft 或 sprockets-rails)時,行為將會「增強」。您可以透過將 skip_pipeline: true 傳遞到選項中,來略過資源管線。

所有其他資源 *_path 輔助程式都會委派到此方法。

使用資源管線

傳遞到 asset_path 的所有選項都將會傳遞到 compute_asset_path,而後者是透過資源管線 gem 實作的。

asset_path("application.js") # => "/assets/application-60aa4fdc5cea14baf5400fba1abf4f2a46a5166bad4772b1effe341570f07de9.js"
asset_path('application.js', host: 'example.com') # => "//example.com/assets/application.js"
asset_path("application.js", host: 'example.com', protocol: 'https') # => "https://example.com/assets/application.js"

沒有資源管線(skip_pipeline: true

接受 type 選項,此選項可以指定資源的副檔名。不會執行錯誤檢查,以驗證傳遞到 asset_path 的來源是否有效,且檔案是否存在於磁碟上。

asset_path("application.js", skip_pipeline: true)                 # => "application.js"
asset_path("filedoesnotexist.png", skip_pipeline: true)           # => "filedoesnotexist.png"
asset_path("application", type: :javascript, skip_pipeline: true) # => "/javascripts/application.js"
asset_path("application", type: :stylesheet, skip_pipeline: true) # => "/stylesheets/application.css"

適用於所有資源的選項

下面列出適用於 asset_path,無論您是否使用資源管線的情境。

  • 所有完全限定的網址都會立即傳回。這會略過資源管線,且略過所有其他已說明的行為。

    asset_path("http://www.example.com/js/xmlhr.js") # => "http://www.example.com/js/xmlhr.js"
    
  • 從正斜線開頭的所有資源都假設為完整網址,且不會展開。這會略過資源管線。

    asset_path("/foo.png") # => "/foo.png"
    
  • 所有空白字串都將立即傳回。這會略過資源管線,且略過所有其他已說明的行為。

    asset_path("") # => ""
    
  • 如果 config.relative_url_root 已指定,將會在所有資源之前加上該根目錄。

    Rails.application.config.relative_url_root = "bar"
    asset_path("foo.js", skip_pipeline: true) # => "bar/foo.js"
    
  • 可以透過 config.action_controller.asset_host 指定其他資源主機,這通常與 CDN 結合使用。

    Rails.application.config.action_controller.asset_host = "assets.example.com"
    asset_path("foo.js", skip_pipeline: true) # => "http://assets.example.com/foo.js"
    
  • 副檔名可以透過 extname 手動指定。

    asset_path("foo", skip_pipeline: true, extname: ".js")     # => "/foo.js"
    asset_path("foo.css", skip_pipeline: true, extname: ".js") # => "/foo.css.js"
    
別名:path_to_asset
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 187
def asset_path(source, options = {})
  raise ArgumentError, "nil is not a valid asset source" if source.nil?

  source = source.to_s
  return "" if source.blank?
  return source if URI_REGEXP.match?(source)

  tail, source = source[/([?#].+)$/], source.sub(/([?#].+)$/, "")

  if extname = compute_asset_extname(source, options)
    source = "#{source}#{extname}"
  end

  unless source.start_with?(?/)
    if options[:skip_pipeline]
      source = public_compute_asset_path(source, options)
    else
      source = compute_asset_path(source, options)
    end
  end

  relative_url_root = defined?(config.relative_url_root) && config.relative_url_root
  if relative_url_root
    source = File.join(relative_url_root, source) unless source.start_with?("#{relative_url_root}/")
  end

  if host = compute_asset_host(source, options)
    source = File.join(host, source)
  end

  "#{source}#{tail}"
end

asset_url(source, options = {})

計算公開目錄中資源的完整網址。這會在內部使用 asset_path,因此它們大多數的行為都會相同。如果設定了 :host 選項,它會覆寫全域的 config.action_controller.asset_host 設定。

提供的所有其他選項都將會轉送到 asset_path 呼叫。

asset_url "application.js"                                 # => http://example.com/assets/application.js
asset_url "application.js", host: "http://cdn.example.com" # => http://cdn.example.com/assets/application.js
別名:url_to_asset
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 231
def asset_url(source, options = {})
  path_to_asset(source, options.merge(protocol: :request))
end

audio_path(source, options = {})

計算公開音訊目錄中音訊資源的路徑。會透過文件根目錄傳遞完整路徑。audio_tag 在內部使用,以建構音訊路徑。

audio_path("horse")                                            # => /audios/horse
audio_path("horse.wav")                                        # => /audios/horse.wav
audio_path("sounds/horse.wav")                                 # => /audios/sounds/horse.wav
audio_path("/sounds/horse.wav")                                # => /sounds/horse.wav
audio_path("http://www.example.com/sounds/horse.wav")          # => http://www.example.com/sounds/horse.wav
別名:path_to_audio
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 430
def audio_path(source, options = {})
  path_to_asset(source, { type: :audio }.merge!(options))
end

audio_url(來源, 選項 = {})

計算在 public 音訊目錄中音訊 asset 的完整網址。這將在內部使用 audio_path,因此它們大多數的行為將相同。由於 audio_url 基於 asset_url 方法,因此可以設定 :host 選項。如果設定 :host 選項,將覆寫全域 config.action_controller.asset_host 設定。

audio_url "horse.wav", host: "http://stage.example.com" # => http://stage.example.com/audios/horse.wav
也別名為:url_to_audio
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 442
def audio_url(source, options = {})
  url_to_asset(source, { type: :audio }.merge!(options))
end

compute_asset_extname(來源, 選項 = {})

計算要附加到 asset 路徑的 extname。如果什麼都不應該被增加,則傳回 nil

# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 243
def compute_asset_extname(source, options = {})
  return if options[:extname] == false
  extname = options[:extname] || ASSET_EXTENSIONS[options[:type]]
  if extname && File.extname(source) != extname
    extname
  else
    nil
  end
end

compute_asset_host(來源 = "", 選項 = {})

選取這個來源的 asset 主機。如果沒有設定主機,則傳回 nil;如果沒有設定萬用字元,則傳回主機;如果含有 %d,則傳回插補 0-3 數字的主機(數字是來源雜湊模組 4),或呼叫回應呼叫的物件(proc 或其他)上呼叫所傳回的值。

# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 277
def compute_asset_host(source = "", options = {})
  request = self.request if respond_to?(:request)
  host = options[:host]
  host ||= config.asset_host if defined? config.asset_host

  if host
    if host.respond_to?(:call)
      arity = host.respond_to?(:arity) ? host.arity : host.method(:call).arity
      args = [source]
      args << request if request && (arity > 1 || arity < 0)
      host = host.call(*args)
    elsif host.include?("%d")
      host = host % (Zlib.crc32(source) % 4)
    end
  end

  host ||= request.base_url if request && options[:protocol] == :request
  return unless host

  if URI_REGEXP.match?(host)
    host
  else
    protocol = options[:protocol] || config.default_asset_host_protocol || (request ? :request : :relative)
    case protocol
    when :relative
      "//#{host}"
    when :request
      "#{request.protocol}#{host}"
    else
      "#{protocol}://#{host}"
    end
  end
end

compute_asset_path(來源, 選項 = {})

計算至 public 目錄的 asset 路徑。外掛程式和擴充功能可以覆寫此方法以指向自訂 asset 或產生摘要路徑或查詢字串。

# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 266
def compute_asset_path(source, options = {})
  dir = ASSET_PUBLIC_DIRECTORIES[options[:type]] || ""
  File.join(dir, source)
end

font_path(來源, 選項 = {})

計算字體 asset 路徑。將傳遞文件根目錄的完整路徑。

font_path("font")                                           # => /fonts/font
font_path("font.ttf")                                       # => /fonts/font.ttf
font_path("dir/font.ttf")                                   # => /fonts/dir/font.ttf
font_path("/dir/font.ttf")                                  # => /dir/font.ttf
font_path("http://www.example.com/dir/font.ttf")            # => http://www.example.com/dir/font.ttf
也別名為:path_to_font
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 455
def font_path(source, options = {})
  path_to_asset(source, { type: :font }.merge!(options))
end

font_url(來源, 選項 = {})

計算至字體 asset 的完整網址。這將在內部使用 font_path,因此它們大多數的行為將相同。由於 font_url 基於 asset_url 方法,因此可以設定 :host 選項。如果設定 :host 選項,將覆寫全域 config.action_controller.asset_host 設定。

font_url "font.ttf", host: "http://stage.example.com" # => http://stage.example.com/fonts/font.ttf
也別名為:url_to_font
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 467
def font_url(source, options = {})
  url_to_asset(source, { type: :font }.merge!(options))
end

image_path(source, options = {})

計算影像資產的路徑。文件的完整路徑將通過。由 image_tag 內部使用來建立影像路徑。

image_path("edit")                                         # => "/assets/edit"
image_path("edit.png")                                     # => "/assets/edit.png"
image_path("icons/edit.png")                               # => "/assets/icons/edit.png"
image_path("/icons/edit.png")                              # => "/icons/edit.png"
image_path("http://www.example.com/img/edit.png")          # => "http://www.example.com/img/edit.png"

如果您的影像作為應用程式的資源,此方法可能會與其命名路由相衝突。提供別名 path_to_image 用於避免這個情況。Rails 內部使用此別名,並鼓勵外掛程式作者採用此作法。

另一個別名:path_to_image
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 378
def image_path(source, options = {})
  path_to_asset(source, { type: :image }.merge!(options))
end

image_url(source, options = {})

計算影像資產的完整 URL。這會在內部使用 image_path,因此大部分的行為將相同。由於 image_url 是以 asset_url 方法為基礎,因此您可以設定 :host 選項。如果設定 :host 選項,則其會覆寫全域設定 config.action_controller.asset_host

image_url "edit.png", host: "http://stage.example.com" # => http://stage.example.com/assets/edit.png
另一個別名:url_to_image
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 390
def image_url(source, options = {})
  url_to_asset(source, { type: :image }.merge!(options))
end

javascript_path(source, options = {})

計算 public javascript 目錄中 JavaScript 資產的路徑。如果 source 檔案名稱沒有附檔名,將追加 .js (除了明確的 URI)。文件的完整路徑將通過。由 javascript_include_tag 內部使用來建立腳本路徑。

javascript_path "xmlhr"                              # => /assets/xmlhr.js
javascript_path "dir/xmlhr.js"                       # => /assets/dir/xmlhr.js
javascript_path "/dir/xmlhr"                         # => /dir/xmlhr.js
javascript_path "http://www.example.com/js/xmlhr"    # => http://www.example.com/js/xmlhr
javascript_path "http://www.example.com/js/xmlhr.js" # => http://www.example.com/js/xmlhr.js
另一個別名:path_to_javascript
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 321
def javascript_path(source, options = {})
  path_to_asset(source, { type: :javascript }.merge!(options))
end

javascript_url(source, options = {})

計算 public javascript 目錄中 JavaScript 資產的完整 URL。這會在內部使用 javascript_path,因此大部分的行為將相同。由於 javascript_url 是以 asset_url 方法為基礎,因此您可以設定 :host 選項。如果設定 :host 選項,則其會覆寫全域設定 config.action_controller.asset_host

javascript_url "js/xmlhr.js", host: "http://stage.example.com" # => http://stage.example.com/assets/js/xmlhr.js
另一個別名:url_to_javascript
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 333
def javascript_url(source, options = {})
  url_to_asset(source, { type: :javascript }.merge!(options))
end

path_to_asset(source, options = {})

別名:asset_path

path_to_audio(source, options = {})

別名:audio_path

path_to_font(source, options = {})

別名:font_path

path_to_image(source, options = {})

別名:image_path

path_to_javascript(source, options = {})

path_to_stylesheet(source, options = {})

path_to_video(source, options = {})

別名:video_path

public_compute_asset_path(source, options = {})

stylesheet_path(source, options = {})

計算 public stylesheets 目錄中樣式表資產的路徑。如果 source 檔名沒有副檔名,會附加 .css(明確定義的 URI 例外)。會傳遞文件根目錄的完整路徑。stylesheet_link_tag 內部使用它來建置樣式表路徑。

stylesheet_path "style"                                  # => /assets/style.css
stylesheet_path "dir/style.css"                          # => /assets/dir/style.css
stylesheet_path "/dir/style.css"                         # => /dir/style.css
stylesheet_path "http://www.example.com/css/style"       # => http://www.example.com/css/style
stylesheet_path "http://www.example.com/css/style.css"   # => http://www.example.com/css/style.css
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 348
def stylesheet_path(source, options = {})
  path_to_asset(source, { type: :stylesheet }.merge!(options))
end

stylesheet_url(source, options = {})

計算 public stylesheets 目錄中樣式表資產的完整 URL。這會在內部使用 stylesheet_path,因此它們大多數的行為都會相同。由於 stylesheet_url 是根據 asset_url 方法,因此您可以設定 :host 選項。如果設定 :host 選項,它會覆寫全域 config.action_controller.asset_host 設定。

stylesheet_url "css/style.css", host: "http://stage.example.com" # => http://stage.example.com/assets/css/style.css
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 360
def stylesheet_url(source, options = {})
  url_to_asset(source, { type: :stylesheet }.merge!(options))
end

url_to_asset(source, options = {})

別名:asset_url

url_to_audio(source, options = {})

別名:audio_url

url_to_font(source, options = {})

別名:font_url

url_to_image(source, options = {})

別名:image_url

url_to_javascript(source, options = {})

url_to_stylesheet(source, options = {})

url_to_video(source, options = {})

別名:video_url

video_path(source, options = {})

計算 public videos 目錄中視訊資源的路徑。將從文件根目錄傳遞完整路徑。由 video_tag 內部使用以建立視訊路徑。

video_path("hd")                                            # => /videos/hd
video_path("hd.avi")                                        # => /videos/hd.avi
video_path("trailers/hd.avi")                               # => /videos/trailers/hd.avi
video_path("/trailers/hd.avi")                              # => /trailers/hd.avi
video_path("http://www.example.com/vid/hd.avi")             # => http://www.example.com/vid/hd.avi
也稱為別名:path_to_video
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 404
def video_path(source, options = {})
  path_to_asset(source, { type: :video }.merge!(options))
end

video_url(source, options = {})

計算 public videos 目錄中視訊資源的完整 URL。這將在內部使用 video_path,因此它們的大部分行為將相同。由於 video_url 是基於 asset_url 方法,因此您可以設定 :host 選項。如果設定了 :host 選項,它會覆寫全域性的 config.action_controller.asset_host 設定。

video_url "hd.avi", host: "http://stage.example.com" # => http://stage.example.com/videos/hd.avi
也稱為別名:url_to_video
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 416
def video_url(source, options = {})
  url_to_asset(source, { type: :video }.merge!(options))
end