Refactor AssetUrlHelper #7927

Merged
merged 16 commits into from Oct 15, 2012

6 participants

@josh
Ruby on Rails member

Follow up #7923. Theres a couple things happening here.

asset_path, asset_url

Originally inspired the current sprockets rails plugin, bd38d9f adds general purpose asset_path and asset_url helpers. All the other helpers simply funnel through this main point. Makes it possible for extensions to change the behavior of all the helpers w/o redefining each.

Remove AssetPaths

There doesn't not a whole lot of documentation indicating that this class was ever okay to use publicly. And theres no tests asserting it either. Just 🔥ing it.

The core of it is replaced by inline helper methods, compute_asset_path and compute_asset_host. Both these methods should now be considered public. Apps or plugins can call them directly or override them to change there behavior.

Isolate old asset id code

I've move all the old asset id mtime query stuff into a separate module, AssetIdHelper. It uses the now compute_asset_path to set itself up.

Since this is now modular, it wouldn't be a bad time to kill it or move it out into an optional plugin. I'd like to get @dhh's take on this.

  • 🔥 it
  • extract it into a plugin
  • or just leave it as is

Bonus

You should be able to include ActionView::Helpers::AssetUrlHelper into AC::Base just fine now.

/cc @dhh @steveklabnik @guilleiguaran @rafaelfranca

josh added some commits Oct 12, 2012
@josh josh Add asset_path and asset_url helpers bd38d9f
@josh josh Refactor AssetUrlHelper to make it friendly for plugins and extensions
Add asset_path/url helper for a consolidated entry point
Expose compute_asset_path as a public API
Expose compute_asset_host as a public API
Move RAILS_ASSET_ID to its own module, AssetIdHelper
Removed AV::AssetPaths
1e2b0ce
@josh josh Ensure AssetUrlHelper can be mixed into AC::Base c3cff4d
@josh josh JAVASCRIPTS_DIR, STYLESHEETS_DIR, ASSETS_DIR don't even exist anymore dee3a19
@josh josh and 2 others commented on an outdated diff Oct 12, 2012
actionpack/lib/action_view/helpers/asset_url_helper.rb
end
alias_method :url_to_font, :font_url # aliased to avoid conflicts with an font_url named route
private
- def asset_paths
- @asset_paths ||= AssetTagHelper::AssetPaths.new(config, controller)
- end
-
- def current_host
- url_for(:only_path => false)
+ # Get current request if self is a controller. If self is a
+ # view, check the parent controller's request.
+ def asset_request
+ if respond_to?(:request)
+ request
+ elsif respond_to?(:controller) && controller.respond_to?(:request)
+ controller.request
+ end
@josh
Ruby on Rails member
josh added a line comment Oct 12, 2012

This actually seems kinda silly. Is there not a unified way to access request on both the controller and the view?

@rafaelfranca
Ruby on Rails member
rafaelfranca added a line comment Oct 12, 2012

Unfortunately not. 😢

@pixeltrix
Ruby on Rails member
pixeltrix added a line comment Oct 14, 2012

If not how come I can do <%= request.inspect %> in an ERb template? It's the same context isn't it? I can also call request from a helper.

@rafaelfranca
Ruby on Rails member
rafaelfranca added a line comment Oct 14, 2012

@pixeltrix right. You can do this inside a view/helper because ControllerHelper defines this. We can make AssetUrlHelper depend of ControllerHelper but I don't think is a good idea since we want to include this helper inside AC

@pixeltrix
Ruby on Rails member
pixeltrix added a line comment Oct 14, 2012

@rafaelfranca I guessed there was a delegate somewhere. Is there any place where AssetUrlHelper is included that either doesn't include ControllerHelper or request is available? The only one I can think of it Action Mailer but controller is not defined there either so I'm not sure that the elsif branch is ever called.

@rafaelfranca
Ruby on Rails member
rafaelfranca added a line comment Oct 14, 2012

I think the only places in Action Mailer too. Maybe in some tests.

@pixeltrix
Ruby on Rails member
pixeltrix added a line comment Oct 15, 2012

I just commented out the elsif branch and ran the Action Pack test suite - no errors.

@rafaelfranca
Ruby on Rails member
rafaelfranca added a line comment Oct 15, 2012

Good. Lets nuke this elsif

@josh
Ruby on Rails member
josh added a line comment Oct 15, 2012

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@rafaelfranca rafaelfranca commented on an outdated diff Oct 12, 2012
actionpack/lib/action_view/helpers/asset_id_helper.rb
+ # different times - say to handle a temporary spike in load - then the
+ # asset time stamps will be out of sync. In a setup like this you may want
+ # to set the way that asset paths are generated yourself.
+ #
+ # Altering the asset paths that Rails generates can be done in two ways.
+ # The easiest is to define the RAILS_ASSET_ID environment variable. The
+ # contents of this variable will always be used in preference to
+ # calculated timestamps. A more complex but flexible way is to set
+ # <tt>ActionController::Base.config.asset_path</tt> to a proc
+ # that takes the unmodified asset path and returns the path needed for
+ # your asset caching to work. Typically you'd do something like this in
+ # <tt>config/environments/production.rb</tt>:
+ #
+ # # Normally you'd calculate RELEASE_NUMBER at startup.
+ # RELEASE_NUMBER = 12345
+ # config.action_controller.asset_path = proc { |asset_path|
@rafaelfranca
Ruby on Rails member
rafaelfranca added a line comment Oct 12, 2012

Is this still valid after this pull request?

@rafaelfranca
Ruby on Rails member
rafaelfranca added a line comment Oct 12, 2012

Yes it is and the answer is here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@rafaelfranca
Ruby on Rails member

About AssetIdHelper I would extract it to a plugin.

@rafaelfranca
Ruby on Rails member

Awesome work!!!

I'm giving my 👍. I just want to wait @dhh to take a look on this one, specially on the AssetIdHelper.

@robin850 robin850 commented on the diff Oct 14, 2012
actionpack/lib/action_view/helpers/asset_url_helper.rb
+ # will use +asset_path+ internally, so most of their behaviors
+ # will be the same.
+ def asset_url(source, options = {})
+ path_to_asset(source, options.merge(:protocol => :request))
+ end
+ alias_method :url_to_asset, :asset_url # aliased to avoid conflicts with an asset_url named route
+
+ # Maps asset types to public directory.
+ ASSET_PUBLIC_DIRECTORIES = {
+ audio: '/audios',
+ font: '/fonts',
+ image: '/images',
+ javascript: '/javascripts',
+ stylesheet: '/stylesheets',
+ video: '/videos'
+ }
@robin850
Ruby on Rails member
robin850 added a line comment Oct 14, 2012

Very nice ! :) ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@carlosantoniodasilva carlosantoniodasilva commented on an outdated diff Oct 15, 2012
actionpack/lib/action_view/helpers/asset_url_helper.rb
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.
# 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
+ def font_url(source, options = {})
+ url_to_asset(source, {type: :font}.merge(options))
@carlosantoniodasilva
Ruby on Rails member

These merge calls in the methods above could be actually merge!, to avoid creating two of them on every call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@carlosantoniodasilva
Ruby on Rails member

Cool 👍. Looks fine for a plugin imo.

@dhh
Ruby on Rails member

I'm wondering who would even use the AssetId plugin? Are we talking about people holding out and not going with the asset pipeline? I don't think it's a reasonable assumption to run Rails 4.0 without the asset pipeline, or an alternative, and want Rails to provide AssetIds. I say nuke the fucker. If anyone really does turn out to need it, we can point them to the code that was 🔥'ed and they can make their own.

@rafaelfranca
Ruby on Rails member

@dhh yes we are taling about people who not use asset pipeline. If this is the direction that we want to follow so lets 💥 it.

@dhh
Ruby on Rails member
@josh
Ruby on Rails member

Kinda stuck on the railties tests. They load sprockets-rails which depends on the old AssetPaths api.

Whats the best way to update this stuff w/o making the build red? Maybe create a new branch on sprockets-rails that works w/ this pull?

@rafaelfranca
Ruby on Rails member

We will need to update the sprockets-rails project to not use this API. cc @guilleiguaran

@josh josh referenced this pull request in rails/sprockets-rails Oct 15, 2012
Merged

Use new asset url helper apis #23

@guilleiguaran
Ruby on Rails member

This needs rebase 😁

@guilleiguaran
Ruby on Rails member

@josh btw, I think sass-rails is also depending in AssetsPath API

@josh
Ruby on Rails member

@guilleiguaran don't see any calls there. Also, you should be able to remove most of that plugin. The builtin sass stuff works pretty damn well.

@josh
Ruby on Rails member

Aight, railties tests finally finished here.

What order should the branches be merged?

@rafaelfranca rafaelfranca merged commit 046ab84 into rails:master Oct 15, 2012
@rafaelfranca
Ruby on Rails member

Merged. Thanks

@rafaelfranca rafaelfranca added a commit that referenced this pull request Oct 18, 2012
@rafaelfranca rafaelfranca Add CHANGELOG entry for #7927
Removed the asset_path configuration from the guides and added an entry
in the upgrading_ruby_on_rails guide

[ci skip]
e627834
@rafaelfranca rafaelfranca added a commit that referenced this pull request Oct 18, 2012
@rafaelfranca rafaelfranca Add more CHANGELOG entries from #7927
Also remove references for RAILS_ASSET_ID from the guides

[ci skip]
d7f8b2a
@jejacks0n

Josh, just wanted to understand this commit -- I know it's from 3 months ago, but I'm seeing what appears to be a bug with rendering assets from views within an engine.. I'm using javascript_include_tag, and they get prepended with wherever that engine was mounted at within the rails app.

I would appreciate you taking a look at an issue I created in rails/sprockets-rails, and a project that exhibits the issue.

When an engine is mounted within an application using mount Foo::Engine => "/path" then request.try(:script_name) will return "/path" -- this results in the asset urls being incorrectly prepended with /path/assets.

Thanks.

EDIT: #8712

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment