Search
Me

Developer for Forward. Former Technical Lead at ThoughtWorks.

Recent Comments
Elsewhere

Entries in monkeypatch (1)

Thursday
08Nov2007

Watch out for the Monkey Patch

The project I’m currently working on uses both the Asset Packager and Distributed Assets to ensure we have only a few external assets, and that we can load assets across more than one host - all so that the pages for our site load nice and quick.

Unfortunately, wiring in the Asset Packager plugin caused the Distributed Assets plugin to break, and I spent an hour or two tracking it down yesterday. The cause? Asset Packager redefines the compute_public_path method.

# rewrite compute_public_path to allow us to not include the query string timestamp
# used by ActionView::Helpers::AssetTagHelper
def compute_public_path(source, dir, ext=nil, add_asset_id=true)
source = source.dup
source << ".#{ext}" if File.extname(source).blank? && ext
unless source =~ %r{^[-a-z]+://}
source = "/#{dir}/#{source}" unless source[0] == ?/
asset_id = rails_asset_id(source)
source << '?' + asset_id if defined?(RAILS_ROOT) and add_asset_id and not asset_id.blank?
source = "#{ActionController::Base.asset_host}#{@controller.request.relative_url_root}#{source}"
end
source
end

Distributed Assets works by chaining compute_public_path - decorating the calculated path, adding the asset host prefix onto the url. But, Asset Packager works by defining the method into ActionView::Base. So, when DistributedAssets::AssetTagHelper is included with ActionView::Helpers::AssetTagHelper, it chains a (now) hidden method.

But, the only places that use the new compute_public_path code inside the Asset Packager Helper (which just avoids using the query string timestamp) is within Asset Packager itself.

So, I tweaked the implementation of AssetPackageHelper to

def compute_public_path_for_packager(source, dir, ext, add_asset_id=true)
path = compute_public_path(source, dir, ext)
return path if add_asset_id
path.gsub(/\?\d+$/, '')
end

def javascript_path(source)
compute_public_path_for_packager(source, 'javascripts', 'js', false)
end

Beware the monkey patch.