Skip to content

Commit

Permalink
Add *_url helpers to get the full assets URL
Browse files Browse the repository at this point in the history
Adds `image_url`, `javascript_url`, `stylesheet_url`, `audio_url`,
`video_url`, and `font_url` to assets tag helper. These URL helpers will
return the full path to your assets. This is useful when you are going
to reference this asset from external host.
  • Loading branch information
sikachu committed Feb 4, 2012
1 parent 20bc3d4 commit bcd3b87
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 2 deletions.
4 changes: 4 additions & 0 deletions actionpack/CHANGELOG.md
@@ -1,5 +1,9 @@
## Rails 4.0.0 (unreleased) ##

* Adds `image_url`, `javascript_url`, `stylesheet_url`, `audio_url`, `video_url`, and `font_url`
to assets tag helper. These URL helpers will return the full path to your assets. This is useful
when you are going to reference this asset from external host. *Prem Sichanugrist*

* Default responder will now always use your overridden block in `respond_with` to render your response. *Prem Sichanugrist*

* Allow `value_method` and `text_method` arguments from `collection_select` and
Expand Down
32 changes: 32 additions & 0 deletions actionpack/lib/action_view/helpers/asset_tag_helper.rb
Expand Up @@ -278,6 +278,13 @@ def image_path(source)
end
alias_method :path_to_image, :image_path # aliased to avoid conflicts with an image_path named route

# Computes the full URL to an image asset in the public images directory.
# This will use +image_path+ internally, so most of their behaviors will be the same.
def image_url(source)
URI.join(current_host, path_to_image(source)).to_s
end
alias_method :url_to_image, :image_url # aliased to avoid conflicts with an image_url named route

# Computes the path to a video asset in the public videos directory.
# Full paths from the document root will be passed through.
# Used internally by +video_tag+ to build the video path.
Expand All @@ -293,6 +300,13 @@ def video_path(source)
end
alias_method :path_to_video, :video_path # aliased to avoid conflicts with a video_path named route

# Computes the full URL to a video asset in the public videos directory.
# This will use +video_path+ internally, so most of their behaviors will be the same.
def video_url(source)
URI.join(current_host, path_to_video(source)).to_s
end
alias_method :url_to_video, :video_url # aliased to avoid conflicts with an video_url named route

# Computes the path to an audio asset in the public audios directory.
# Full paths from the document root will be passed through.
# Used internally by +audio_tag+ to build the audio path.
Expand All @@ -308,6 +322,13 @@ def audio_path(source)
end
alias_method :path_to_audio, :audio_path # aliased to avoid conflicts with an audio_path named route

# Computes the full URL to a audio asset in the public audios directory.
# This will use +audio_path+ internally, so most of their behaviors will be the same.
def audio_url(source)
URI.join(current_host, path_to_audio(source)).to_s
end
alias_method :url_to_audio, :audio_url # aliased to avoid conflicts with an audio_url named route

# Computes the path to a font asset in the public fonts directory.
# Full paths from the document root will be passed through.
#
Expand All @@ -322,6 +343,13 @@ def font_path(source)
end
alias_method :path_to_font, :font_path # aliased to avoid conflicts with an font_path named route

# Computes the full URL to a font asset in the public fonts directory.
# This will use +font_path+ internally, so most of their behaviors will be the same.
def font_url(source)
URI.join(current_host, path_to_font(source)).to_s
end
alias_method :url_to_font, :font_url # aliased to avoid conflicts with an font_url named route

# Returns an html image tag for the +source+. The +source+ can be a full
# path or a file that exists in your public images directory.
#
Expand Down Expand Up @@ -463,6 +491,10 @@ def multiple_sources_tag(type, sources)
tag(type, options)
end
end

def current_host
url_for(:only_path => false)
end
end
end
end
Expand Up @@ -87,6 +87,13 @@ def javascript_path(source)
end
alias_method :path_to_javascript, :javascript_path # aliased to avoid conflicts with a javascript_path named route

# Computes the full URL to a javascript asset in the public javascripts directory.
# This will use +javascript_path+ internally, so most of their behaviors will be the same.
def javascript_url(source)
URI.join(current_host, path_to_javascript(source)).to_s
end
alias_method :url_to_javascript, :javascript_url # aliased to avoid conflicts with a javascript_url named route

# Returns an HTML script tag for each of the +sources+ provided.
#
# Sources may be paths to JavaScript files. Relative paths are assumed to be relative
Expand Down
Expand Up @@ -65,6 +65,13 @@ def stylesheet_path(source)
end
alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route

# Computes the full URL to a stylesheet asset in the public stylesheets directory.
# This will use +stylesheet_path+ internally, so most of their behaviors will be the same.
def stylesheet_url(source)
URI.join(current_host, path_to_stylesheet(source)).to_s
end
alias_method :url_to_stylesheet, :stylesheet_url # aliased to avoid conflicts with a stylesheet_url named route

# Returns a stylesheet link tag for the sources specified as arguments. If
# you don't specify an extension, <tt>.css</tt> will be appended automatically.
# You can modify the link attributes by passing a hash as the last argument.
Expand Down
131 changes: 129 additions & 2 deletions actionpack/test/template/asset_tag_helper_test.rb
Expand Up @@ -88,6 +88,18 @@ def teardown
%(path_to_javascript("/super/xmlhr.js")) => %(/super/xmlhr.js)
}

JavascriptUrlToTag = {
%(javascript_url("xmlhr")) => %(http://www.example.com/javascripts/xmlhr.js),
%(javascript_url("super/xmlhr")) => %(http://www.example.com/javascripts/super/xmlhr.js),
%(javascript_url("/super/xmlhr.js")) => %(http://www.example.com/super/xmlhr.js)
}

UrlToJavascriptToTag = {
%(url_to_javascript("xmlhr")) => %(http://www.example.com/javascripts/xmlhr.js),
%(url_to_javascript("super/xmlhr")) => %(http://www.example.com/javascripts/super/xmlhr.js),
%(url_to_javascript("/super/xmlhr.js")) => %(http://www.example.com/super/xmlhr.js)
}

JavascriptIncludeToTag = {
%(javascript_include_tag("bank")) => %(<script src="/javascripts/bank.js" type="text/javascript"></script>),
%(javascript_include_tag("bank.js")) => %(<script src="/javascripts/bank.js" type="text/javascript"></script>),
Expand Down Expand Up @@ -119,6 +131,20 @@ def teardown
%(path_to_stylesheet('/dir/file.rcss')) => %(/dir/file.rcss)
}

StyleUrlToTag = {
%(stylesheet_url("bank")) => %(http://www.example.com/stylesheets/bank.css),
%(stylesheet_url("bank.css")) => %(http://www.example.com/stylesheets/bank.css),
%(stylesheet_url('subdir/subdir')) => %(http://www.example.com/stylesheets/subdir/subdir.css),
%(stylesheet_url('/subdir/subdir.css')) => %(http://www.example.com/subdir/subdir.css)
}

UrlToStyleToTag = {
%(url_to_stylesheet("style")) => %(http://www.example.com/stylesheets/style.css),
%(url_to_stylesheet("style.css")) => %(http://www.example.com/stylesheets/style.css),
%(url_to_stylesheet('dir/file')) => %(http://www.example.com/stylesheets/dir/file.css),
%(url_to_stylesheet('/dir/file.rcss')) => %(http://www.example.com/dir/file.rcss)
}

StyleLinkToTag = {
%(stylesheet_link_tag("bank")) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />),
%(stylesheet_link_tag("bank.css")) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />),
Expand Down Expand Up @@ -149,6 +175,20 @@ def teardown
%(path_to_image("/dir/xml.png")) => %(/dir/xml.png)
}

ImageUrlToTag = {
%(image_url("xml")) => %(http://www.example.com/images/xml),
%(image_url("xml.png")) => %(http://www.example.com/images/xml.png),
%(image_url("dir/xml.png")) => %(http://www.example.com/images/dir/xml.png),
%(image_url("/dir/xml.png")) => %(http://www.example.com/dir/xml.png)
}

UrlToImageToTag = {
%(url_to_image("xml")) => %(http://www.example.com/images/xml),
%(url_to_image("xml.png")) => %(http://www.example.com/images/xml.png),
%(url_to_image("dir/xml.png")) => %(http://www.example.com/images/dir/xml.png),
%(url_to_image("/dir/xml.png")) => %(http://www.example.com/dir/xml.png)
}

ImageLinkToTag = {
%(image_tag("xml.png")) => %(<img alt="Xml" src="/images/xml.png" />),
%(image_tag("rss.gif", :alt => "rss syndication")) => %(<img alt="rss syndication" src="/images/rss.gif" />),
Expand Down Expand Up @@ -189,6 +229,20 @@ def teardown
%(path_to_video("/dir/xml.ogg")) => %(/dir/xml.ogg)
}

VideoUrlToTag = {
%(video_url("xml")) => %(http://www.example.com/videos/xml),
%(video_url("xml.ogg")) => %(http://www.example.com/videos/xml.ogg),
%(video_url("dir/xml.ogg")) => %(http://www.example.com/videos/dir/xml.ogg),
%(video_url("/dir/xml.ogg")) => %(http://www.example.com/dir/xml.ogg)
}

UrlToVideoToTag = {
%(url_to_video("xml")) => %(http://www.example.com/videos/xml),
%(url_to_video("xml.ogg")) => %(http://www.example.com/videos/xml.ogg),
%(url_to_video("dir/xml.ogg")) => %(http://www.example.com/videos/dir/xml.ogg),
%(url_to_video("/dir/xml.ogg")) => %(http://www.example.com/dir/xml.ogg)
}

VideoLinkToTag = {
%(video_tag("xml.ogg")) => %(<video src="/videos/xml.ogg" />),
%(video_tag("rss.m4v", :autoplay => true, :controls => true)) => %(<video autoplay="autoplay" controls="controls" src="/videos/rss.m4v" />),
Expand All @@ -206,7 +260,7 @@ def teardown
%(video_tag(["multiple.ogg", "multiple.avi"], :size => "160x120", :controls => true)) => %(<video controls="controls" height="120" width="160"><source src="/videos/multiple.ogg" /><source src="/videos/multiple.avi" /></video>)
}

AudioPathToTag = {
AudioPathToTag = {
%(audio_path("xml")) => %(/audios/xml),
%(audio_path("xml.wav")) => %(/audios/xml.wav),
%(audio_path("dir/xml.wav")) => %(/audios/dir/xml.wav),
Expand All @@ -220,6 +274,20 @@ def teardown
%(path_to_audio("/dir/xml.wav")) => %(/dir/xml.wav)
}

AudioUrlToTag = {
%(audio_url("xml")) => %(http://www.example.com/audios/xml),
%(audio_url("xml.wav")) => %(http://www.example.com/audios/xml.wav),
%(audio_url("dir/xml.wav")) => %(http://www.example.com/audios/dir/xml.wav),
%(audio_url("/dir/xml.wav")) => %(http://www.example.com/dir/xml.wav)
}

UrlToAudioToTag = {
%(url_to_audio("xml")) => %(http://www.example.com/audios/xml),
%(url_to_audio("xml.wav")) => %(http://www.example.com/audios/xml.wav),
%(url_to_audio("dir/xml.wav")) => %(http://www.example.com/audios/dir/xml.wav),
%(url_to_audio("/dir/xml.wav")) => %(http://www.example.com/dir/xml.wav)
}

AudioLinkToTag = {
%(audio_tag("xml.wav")) => %(<audio src="/audios/xml.wav" />),
%(audio_tag("rss.wav", :autoplay => true, :controls => true)) => %(<audio autoplay="autoplay" controls="controls" src="/audios/rss.wav" />),
Expand All @@ -242,6 +310,14 @@ def test_path_to_javascript_alias_for_javascript_path
PathToJavascriptToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_javascript_url
JavascriptUrlToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_url_to_javascript_alias_for_javascript_url
UrlToJavascriptToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_javascript_include_tag_with_blank_asset_id
ENV["RAILS_ASSET_ID"] = ""
JavascriptIncludeToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
Expand Down Expand Up @@ -349,6 +425,15 @@ def test_path_to_stylesheet_alias_for_stylesheet_path
PathToStyleToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_stylesheet_url
ENV["RAILS_ASSET_ID"] = ""
StyleUrlToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_url_to_stylesheet_alias_for_stylesheet_url
UrlToStyleToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_stylesheet_link_tag
ENV["RAILS_ASSET_ID"] = ""
StyleLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
Expand Down Expand Up @@ -433,6 +518,14 @@ def test_path_to_image_alias_for_image_path
PathToImageToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_image_url
ImageUrlToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_url_to_image_alias_for_image_url
UrlToImageToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_image_alt
[nil, '/', '/foo/bar/', 'foo/bar/'].each do |prefix|
assert_equal 'Rails', image_alt("#{prefix}rails.png")
Expand Down Expand Up @@ -478,6 +571,14 @@ def test_path_to_video_alias_for_video_path
PathToVideoToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_video_url
VideoUrlToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_url_to_video_alias_for_video_url
UrlToVideoToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_video_tag
VideoLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
Expand All @@ -490,6 +591,14 @@ def test_path_to_audio_alias_for_audio_path
PathToAudioToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_audio_url
AudioUrlToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_url_to_audio_alias_for_audio_url
UrlToAudioToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end

def test_audio_tag
AudioLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
Expand Down Expand Up @@ -573,7 +682,6 @@ def test_caching_image_path_with_caching_and_proc_asset_host_using_request
end
end


@controller.request.stubs(:ssl?).returns(false)
assert_equal "http://assets15.example.com/images/xml.png", image_path("xml.png")

Expand Down Expand Up @@ -1141,6 +1249,22 @@ def test_should_compute_proper_path_with_asset_host_and_default_protocol
assert_dom_equal(%(<img alt="Mouse2" onmouseover="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse_over2.png'" onmouseout="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse2.png'" src="gopher://assets.example.com/collaboration/hieraki/images/mouse2.png" />), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png")))
end

def test_should_compute_proper_url_with_asset_host
@controller.config.asset_host = "assets.example.com"
assert_dom_equal(%(<link href="http://www.example.com/collaboration/hieraki" rel="alternate" title="RSS" type="application/rss+xml" />), auto_discovery_link_tag)
assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_url("xmlhr"))
assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_url("style"))
assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_url("xml.png"))
end

def test_should_compute_proper_url_with_asset_host_and_default_protocol
@controller.config.asset_host = "assets.example.com"
@controller.config.default_asset_host_protocol = :request
assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_url("xmlhr"))
assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_url("style"))
assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_url("xml.png"))
end

def test_should_ignore_asset_host_on_complete_url
@controller.config.asset_host = "http://assets.example.com"
assert_dom_equal(%(<link href="http://bar.example.com/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag("http://bar.example.com/stylesheets/style.css"))
Expand All @@ -1154,16 +1278,19 @@ def test_should_ignore_asset_host_on_scheme_relative_url
def test_should_wildcard_asset_host_between_zero_and_four
@controller.config.asset_host = 'http://a%d.example.com'
assert_match(%r(http://a[0123].example.com/collaboration/hieraki/images/xml.png), image_path('xml.png'))
assert_match(%r(http://a[0123].example.com/collaboration/hieraki/images/xml.png), image_url('xml.png'))
end

def test_asset_host_without_protocol_should_be_protocol_relative
@controller.config.asset_host = 'a.example.com'
assert_equal 'gopher://a.example.com/collaboration/hieraki/images/xml.png', image_path('xml.png')
assert_equal 'gopher://a.example.com/collaboration/hieraki/images/xml.png', image_url('xml.png')
end

def test_asset_host_without_protocol_should_be_protocol_relative_even_if_path_present
@controller.config.asset_host = 'a.example.com/files/go/here'
assert_equal 'gopher://a.example.com/files/go/here/collaboration/hieraki/images/xml.png', image_path('xml.png')
assert_equal 'gopher://a.example.com/files/go/here/collaboration/hieraki/images/xml.png', image_url('xml.png')
end

def test_assert_css_and_js_of_the_same_name_return_correct_extension
Expand Down
24 changes: 24 additions & 0 deletions railties/guides/source/action_view_overview.textile
Expand Up @@ -585,6 +585,14 @@ Computes the path to an image asset in the +public/images+ directory. Full paths
image_path("edit.png") # => /images/edit.png
</ruby>

h5. image_url

Computes the url to an image asset in the +public/images+ directory. This will call +image_path+ internally and merge with your current host or your asset host.

<ruby>
image_url("edit.png") # => http://www.example.com/images/edit.png
</ruby>

h5. image_tag

Returns an html image tag for the source. The source can be a full path or a file that exists in your +public/images+ directory.
Expand Down Expand Up @@ -629,6 +637,14 @@ Computes the path to a JavaScript asset in the +public/javascripts+ directory. I
javascript_path "common" # => /javascripts/common.js
</ruby>

h5. javascript_url

Computes the url to a JavaScript asset in the +public/javascripts+ directory. This will call +javascript_path+ internally and merge with your current host or your asset host.

<ruby>
javascript_url "common" # => http://www.example.com/javascripts/common.js
</ruby>

h5. stylesheet_link_tag

Returns a stylesheet link tag for the sources specified as arguments. If you don't specify an extension, +.css+ will be appended automatically.
Expand Down Expand Up @@ -659,6 +675,14 @@ Computes the path to a stylesheet asset in the +public/stylesheets+ directory. I
stylesheet_path "application" # => /stylesheets/application.css
</ruby>

h5. stylesheet_url

Computes the url to a stylesheet asset in the +public/stylesheets+ directory. This will call +stylesheet_path+ internally and merge with your current host or your asset host.

<ruby>
stylesheet_url "application" # => http://www.example.com/stylesheets/application.css
</ruby>

h4. AtomFeedHelper

h5. atom_feed
Expand Down

0 comments on commit bcd3b87

Please sign in to comment.