Module: Merb::AssetsMixin
- Includes:
- Merb::Assets::AssetHelpers
- Defined in:
- merb-assets/lib/merb-assets/assets_mixin.rb
Overview
Implementation: very redundant, most things are just copy/paste with JS and CSS changed.
The AssetsMixin module provides a number of helper methods to views for linking to assets and other pages, dealing with JavaScript and CSS.
Merb provides views with convenience methods for links images and other assets.
External JavaScript and Stylesheets
You can use #require_js(:prototype) or #require_css(:shinystyles)
from any view or layout, and the scripts will only be included once
in the head of the final page. To get this effect, the head of your
layout you will need to include a call to #include_required_js and
#include_required_css.
# File: app/views/layouts/application.html.erb
<html>
<head>
<%= include_required_js %>
<%= include_required_css %>
</head>
<body>
<%= catch_content :layout %>
</body>
</html>
# File: app/views/whatever/_part1.herb
<% require_js 'this' -%>
<% require_css 'that', 'another_one' -%>
# File: app/views/whatever/_part2.herb
<% require_js 'this', 'something_else' -%>
<% require_css 'that' -%>
# File: app/views/whatever/index.herb
<%= partial(:part1) %>
<%= partial(:part2) %>
# Will generate the following in the final page...
<html>
<head>
<script src="/javascripts/this.js" type="text/javascript"></script>
<script src="/javascripts/something_else.js" type="text/javascript"></script>
<link href="/stylesheets/that.css" media="all" rel="Stylesheet" type="text/css"/>
<link href="/stylesheets/another_one.css" media="all" rel="Stylesheet" type="text/css"/>
</head>
.
.
.
</html>
See each method's documentation for more information.
Bundling Asset Files
The key to making a fast web application is to reduce both the amount of data transfered and the number of client-server interactions. While having many small, module Javascript or stylesheet files aids in the development process, your web application will benefit from bundling those assets in the production environment.
An asset bundle is a set of asset files which are combined into a single file. This reduces the number of requests required to render a page, and can reduce the amount of data transfer required if you're using gzip encoding.
Asset bundling is always enabled in production mode, and can be optionally
enabled in all environments by setting the :bundle_assets value
in config/merb.yml to true.
In the development environment, this:
js_include_tag :prototype, :lowpro, :bundle => true
will produce two <script> elements. In the production mode, however, the
two files will be concatenated in the order given into a single file,
all.js, in the public/javascripts directory.
To specify a different bundle name:
css_include_tag :typography, :whitespace, :bundle => :base
css_include_tag :header, :footer, :bundle => "content"
css_include_tag :lightbox, :images, :bundle => "lb.css"
(base.css, content.css, and lb.css will all be
created in the public/stylesheets directory.)
Callbacks
To use a Javascript or CSS compressor, like JSMin or YUI Compressor:
Merb::Assets::JavascriptAssetBundler.add_callback do |filename|
system("/usr/local/bin/yui-compress #{filename}")
end
Merb::Assets::StylesheetAssetBundler.add_callback do |filename|
system("/usr/local/bin/css-min #{filename}")
end
These blocks will be run after a bundle is created.
Bundling Required Assets
Combining the #require_css and #require_js helpers with bundling can be problematic. You may want to separate out the common assets for your application -- Javascript frameworks, common CSS, etc. -- and bundle those in a "base" bundle. Then, for each section of your site, bundle the required assets into a section-specific bundle.
N.B.: If you bundle an inconsistent set of assets with the same name, you will have inconsistent results. Be thorough and test often.
In your application layout:
js_include_tag :prototype, :lowpro, :bundle => :base
In your controller layout:
require_js :bundle => :posts
Constant Summary
- ABSOLUTE_PATH_REGEXP =
%r{^#{Merb::Const::HTTP}s?://}
Constants included from Merb::Assets::AssetHelpers
Merb::Assets::AssetHelpers::ASSET_FILE_EXTENSIONS
Class Method Summary (collapse)
-
+ (Boolean) append_random_query_string?(intention, allow_default = true)
This tests whether a random query string shall be appended to a URL.
-
+ (Boolean) append_timestamp_query_string?(intention, allow_default = true)
This tests whether a timestamp query string shall be appended to a URL.
Instance Method Summary (collapse)
-
- (Boolean) asset_exists?(asset_type, asset_path)
Tests whether a give asset exists in the file system.
-
- (String) auto_link
Automatically generates links for CSS and JS.
-
- (String) auto_link_css
Generate HTML tags for including CSS.
-
- (String) auto_link_js
Generate HTML tags for including JS.
-
- (Array<String>) auto_link_paths
Auxiliary method to get all possible asset paths for the current controller/action.
-
- (String) css_include_tag(*stylesheets)
Generate CSS include tag(s).
- - (Object) escape_js(javascript)
-
- (String) image_tag(img, opts = {})
Generate an IMG tag.
-
- (String) include_required_css(options = {})
A method used in the layout of an application to create `` tags for CSS stylesheets required in in templates and subtemplates using #require_css.
-
- (String) include_required_js(options = {})
A method used in the layout of an application to create `` tags to include JavaScripts required in in templates and subtemplates using #require_js.
- - (Object) js(data)
-
- (String) js_include_tag(*scripts)
Generate JavaScript include tag(s).
- - (Object) link_to(name, url = '', opts = {})
-
- (Object) require_css(*css)
The require_css method can be used to require any CSS file anywhere in your templates.
-
- (Object) require_js(*js)
The
require_jsmethod can be used to require any JavaScript file anywhere in your templates. -
- (Object) required_css(options = {})
All css files to include, without duplicates.
-
- (Object) required_js(options = {})
All javascript files to include, without duplicates.
-
- (Array<String>, String) uniq_css_path(*assets)
Full unique paths to assets OR a plain string if only a single path is requested.
-
- (Array<String>, String) uniq_css_tag(*assets)
Like #css_include_tag, but with a unique path.
-
- (Array<String>, String) uniq_js_path(*assets)
Full unique paths to assets OR a plain string if only a single path is requested.
-
- (Array<String>, String) uniq_js_tag(*assets)
Like #js_include_tag, but with a unique path.
-
- (Array<String>, String) uniq_path(*assets)
Full unique paths to assets OR a plain string if only a single path is requested.
Methods included from Merb::Assets::AssetHelpers
Class Method Details
+ (Boolean) append_random_query_string?(intention, allow_default = true)
This tests whether a random query string shall be appended to a URL.
Basically, you tell it your intention and if it's ok to use default
config values, and it will either use your intention or the value
set in Merb::Config[:reload_templates].
145 146 147 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 145 def self.append_random_query_string?(intention, allow_default = true) intention.nil? && allow_default ? Merb::Config[:reload_templates] : intention end |
+ (Boolean) append_timestamp_query_string?(intention, allow_default = true)
This tests whether a timestamp query string shall be appended to a URL.
161 162 163 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 161 def self.(intention, allow_default = true) intention.nil? && allow_default ? Merb::Plugins.config[:asset_helpers][:asset_timestamp] : intention end |
Instance Method Details
- (Boolean) asset_exists?(asset_type, asset_path)
Tests whether a give asset exists in the file system.
220 221 222 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 220 def asset_exists?(asset_type, asset_path) File.exists?(Merb.root / asset_path(asset_type, asset_path, true)) end |
- (String) auto_link
Automatically generates links for CSS and JS.
We want all possible matches in the FileSys up to the action name. So given:
controller_name="namespace/controller"action_name="action"
if all files are present should generate link/script tags for:
namespace.(css|js)namespace/controller.(css|js)namespace/controller/action.(css|js)
The reason for separating #auto_link for CSS and JS is performance concerns with page loading. So if you only need one, look at #auto_link_css and #auto_link_js.
188 189 190 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 188 def auto_link [auto_link_css, auto_link_js].join(Merb::Const::NEWLINE) end |
- (String) auto_link_css
Generate HTML tags for including CSS.
197 198 199 200 201 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 197 def auto_link_css auto_link_paths.map do |path| asset_exists?(:stylesheet, path) ? css_include_tag(path) : nil end.compact.join(Merb::Const::NEWLINE) end |
- (String) auto_link_js
Generate HTML tags for including JS.
208 209 210 211 212 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 208 def auto_link_js auto_link_paths.map do |path| asset_exists?(:javascript, path) ? js_include_tag(path) : nil end.compact.join(Merb::Const::NEWLINE) end |
- (Array<String>) auto_link_paths
Auxiliary method to get all possible asset paths for the current controller/action.
228 229 230 231 232 233 234 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 228 def auto_link_paths paths = (controller_name / action_name).split(Merb::Const::SLASH) first = paths.shift paths.inject( [first] ) do |memo, val| memo.push [memo.last, val].join(Merb::Const::SLASH) end end |
- (String) css_include_tag(*stylesheets)
Generate CSS include tag(s).
Parameters are the same as for #js_include_tag.
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 584 def css_include_tag(*stylesheets) = stylesheets.last.is_a?(Hash) ? stylesheets.pop : {} return nil if stylesheets.empty? css_prefix = [:prefix] || Merb::Plugins.config[:asset_helpers][:css_prefix] css_suffix = [:suffix] || Merb::Plugins.config[:asset_helpers][:css_suffix] if (bundle_name = [:bundle]) && Merb::Assets.bundle? && stylesheets.size > 1 bundler = Merb::Assets::StylesheetAssetBundler.new(bundle_name, *stylesheets) bundled_asset = bundler.bundle! return css_include_tag(bundled_asset) end = "" reload = .delete(:reload) = .delete(:timestamp) for stylesheet in stylesheets href = css_prefix.to_s + asset_path(:stylesheet, stylesheet) if css_suffix ext_length = ASSET_FILE_EXTENSIONS[:stylesheet].length + 1 href.insert(-ext_length,css_suffix) end href = append_query_string(href, reload, ) attrs = { :href => href, :type => "text/css", :rel => "Stylesheet", :charset => [:charset] || "utf-8", :media => [:media] || :all } << %Q{<link #{attrs.to_xml_attributes} />} end return end |
- (Object) escape_js(javascript)
322 323 324 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 322 def escape_js(javascript) (javascript || '').gsub('\\','\0\0').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" } end |
- (String) image_tag(img, opts = {})
Generate an IMG tag.
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 291 def image_tag(img, opts={}) return "" if img.blank? if img[0].chr == Merb::Const::SLASH opts[:src] = "#{Merb::Config[:path_prefix]}#{img}" else opts[:path] ||= if img =~ ABSOLUTE_PATH_REGEXP absolute = true '' else "#{Merb::Config[:path_prefix]}/images/" end opts[:src] ||= opts.delete(:path) + img end opts[:src] = append_query_string(opts[:src], opts.delete(:reload), opts.delete(:timestamp), !absolute) %{<img #{ opts.to_xml_attributes } />} end |
- (String) include_required_css(options = {})
A method used in the layout of an application to create <link>
tags for CSS stylesheets required in in templates and subtemplates
using #require_css.
452 453 454 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 452 def include_required_css( = {}) required_css().map { |req_js| css_include_tag(*req_js) }.join end |
- (String) include_required_js(options = {})
A method used in the layout of an application to create <script> tags
to include JavaScripts required in in templates and subtemplates using
#require_js.
424 425 426 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 424 def include_required_js( = {}) required_js().map { |req_js| js_include_tag(*req_js) }.join end |
- (Object) js(data)
336 337 338 339 340 341 342 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 336 def js(data) if data.respond_to? :to_json data.to_json else data.inspect.to_json end end |
- (String) js_include_tag(*scripts) - (String) js_include_tag(*scripts, opts)
Generate JavaScript include tag(s).
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 512 def js_include_tag(*scripts) = scripts.last.is_a?(Hash) ? scripts.pop : {} return nil if scripts.empty? js_prefix = [:prefix] || Merb::Plugins.config[:asset_helpers][:js_prefix] js_suffix = [:suffix] || Merb::Plugins.config[:asset_helpers][:js_suffix] if (bundle_name = [:bundle]) && Merb::Assets.bundle? && scripts.size > 1 bundler = Merb::Assets::JavascriptAssetBundler.new(bundle_name, *scripts) bundled_asset = bundler.bundle! return js_include_tag(bundled_asset) end = "" for script in scripts src = js_prefix.to_s + asset_path(:javascript, script) if js_suffix ext_length = ASSET_FILE_EXTENSIONS[:javascript].length + 1 src.insert(-ext_length,js_suffix) end src = append_query_string(src, .delete(:reload), .delete(:timestamp)) attrs = { :src => src, :type => "text/javascript", :charset => [:charset] || "utf-8" } << %Q{<script #{attrs.to_xml_attributes}></script>} end return end |
- (Object) link_to(name, url = '', opts = {})
249 250 251 252 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 249 def link_to(name, url='', opts={}) opts[:href] ||= url %{<a #{ opts.to_xml_attributes }>#{name}</a>} end |
- (Object) require_css(*css)
The require_css method can be used to require any CSS file anywhere in
your templates. Regardless of how many times a single stylesheet is
included with require_css, Merb will only include it once in the header.
389 390 391 392 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 389 def require_css(*css) @required_css ||= [] @required_css << css end |
- (Object) require_js(*js)
The require_js method can be used to require any JavaScript file anywhere
in your templates. Regardless of how many times a single script is
included with require_js, Merb will only include it once in the header.
361 362 363 364 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 361 def require_js(*js) @required_js ||= [] @required_js << js end |
- (Object) required_css(options = {})
All css files to include, without duplicates.
397 398 399 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 397 def required_css( = {}) extract_required_files(@required_css, ) end |
- (Object) required_js(options = {})
All javascript files to include, without duplicates.
369 370 371 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 369 def required_js( = {}) extract_required_files(@required_js, ) end |
- (Array<String>, String) uniq_css_path(*assets)
Full unique paths to assets OR a plain string if only a single path is requested.
688 689 690 691 692 693 694 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 688 def uniq_css_path(*assets) paths = [] assets.flatten.each do |filename| paths.push(Merb::Assets::UniqueAssetPath.build(asset_path(:stylesheet,filename))) end paths.length > 1 ? paths : paths.first end |
- (Array<String>, String) uniq_css_tag(*assets)
Like #css_include_tag, but with a unique path.
718 719 720 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 718 def uniq_css_tag(*assets) css_include_tag(*uniq_css_path(assets)) end |
- (Array<String>, String) uniq_js_path(*assets)
Full unique paths to assets OR a plain string if only a single path is requested.
667 668 669 670 671 672 673 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 667 def uniq_js_path(*assets) paths = [] assets.flatten.each do |filename| paths.push(Merb::Assets::UniqueAssetPath.build(asset_path(:javascript,filename))) end paths.length > 1 ? paths : paths.first end |
- (Array<String>, String) uniq_js_tag(*assets)
Like #js_include_tag, but with a unique path.
705 706 707 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 705 def uniq_js_tag(*assets) js_include_tag(*uniq_js_path(assets)) end |
- (Array<String>, String) uniq_path(*assets)
Full unique paths to assets OR a plain string if only a single path is requested.
646 647 648 649 650 651 652 |
# File 'merb-assets/lib/merb-assets/assets_mixin.rb', line 646 def uniq_path(*assets) paths = [] assets.flatten.each do |filename| paths.push(Merb::Assets::UniqueAssetPath.build(filename)) end paths.length > 1 ? paths : paths.first end |