New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rails.application.assets.find_asset and 3.0.0 #311

Closed
maia opened this Issue Jan 17, 2016 · 13 comments

Comments

Projects
None yet
4 participants
@maia

maia commented Jan 17, 2016

Until 2.3.3 I was able to use the following in application.slim to load controller-specific js/css:

== stylesheet_link_tag params[:controller] if ::Rails.application.assets.find_asset("#{params[:controller]}.css")

With the update to 3.0.0, Rails.application.assets.find_asset() seems to return nil in production:

ActionView::Template::Error (undefined method `find_asset' for nil:NilClass)

How would I need to change my code to let add controller-specific css/js? So far, I've only found mileszs/wicked_pdf/issues/476 suggesting to use assets.compile = true and also links a rather complicated commit. I'm unsure if it's a workaround and what the recommended way is. If the best solution is to not have controller-specific css/js but to put everything in a single file, that's fine with me too.

@mattbrictson

This comment has been minimized.

Show comment
Hide comment
@mattbrictson

mattbrictson Jan 17, 2016

One way might be to use the asset_path helper to test existence of the asset. It returns different things based on whether it can find the asset.

If the asset does not exist (i.e. it is not precompiled):

asset_path("does-not-exist.css")
# => "/does-not-exist.css"

Whereas if the asset does exist:

asset_path("application.css")
# => "/assets/application-46ae33e78e504ff295219f41d63c79719d062e48dc0c07bd9b6f7bcad72c6636.css"

One way might be to use the asset_path helper to test existence of the asset. It returns different things based on whether it can find the asset.

If the asset does not exist (i.e. it is not precompiled):

asset_path("does-not-exist.css")
# => "/does-not-exist.css"

Whereas if the asset does exist:

asset_path("application.css")
# => "/assets/application-46ae33e78e504ff295219f41d63c79719d062e48dc0c07bd9b6f7bcad72c6636.css"
@maia

This comment has been minimized.

Show comment
Hide comment
@maia

maia Jan 17, 2016

Thanks. I've now also found the suggestion of using assets_manifest[filename], but I'm unsure which solution is just a workaround that might break any time soon, and which is the suggested way to go.

maia commented Jan 17, 2016

Thanks. I've now also found the suggestion of using assets_manifest[filename], but I'm unsure which solution is just a workaround that might break any time soon, and which is the suggested way to go.

@mattbrictson

This comment has been minimized.

Show comment
Hide comment
@mattbrictson

mattbrictson Jan 17, 2016

Yes, assets_manifest is a cleaner solution. It took me a few tries to figure out the API. You can use it like this:

Rails.application.assets_manifest.assets["application.css"]
=> "application-46ae33e78e504ff295219f41d63c79719d062e48dc0c07bd9b6f7bcad72c6636.css"
Rails.application.assets_manifest.assets["does-not-exist.css"]
=> nil

Yes, assets_manifest is a cleaner solution. It took me a few tries to figure out the API. You can use it like this:

Rails.application.assets_manifest.assets["application.css"]
=> "application-46ae33e78e504ff295219f41d63c79719d062e48dc0c07bd9b6f7bcad72c6636.css"
Rails.application.assets_manifest.assets["does-not-exist.css"]
=> nil
@rafaelfranca

This comment has been minimized.

Show comment
Hide comment
@rafaelfranca

rafaelfranca Jan 17, 2016

Member

Yes. assets_manifest is the public api for that. It is already present in the view layer so you don't need to use Rails application

Member

rafaelfranca commented Jan 17, 2016

Yes. assets_manifest is the public api for that. It is already present in the view layer so you don't need to use Rails application

@maia

This comment has been minimized.

Show comment
Hide comment
@maia

maia Jan 19, 2016

@rafaelfranca and @mattbrictson : Thanks for your input, but unfortunately I cannot get this to work using sprockets 3.5.2 and sprockets-rails 3.0.0, in development mode I'm seeing the following:

# in application.slim:
== stylesheet_link_tag params[:controller] if assets_manifest["#{params[:controller]}.css"]

# which raises:
undefined method `[]' for #<Sprockets::Manifest:0x007facd97e8280>

# and in console even application.css isn't available, trying both syntaxes:
> Rails.application.assets_manifest.assets["application.css"]
=> nil
> Rails.application.assets_manifest["application.css"]
NoMethodError: undefined method `[]' for #<Sprockets::Manifest:0x007f8629b59760>

Is this only supposed to work in production mode, and if yes, how would I need to check for the existence of a controller-specific .css or .js that works in both production and development mode? Thanks!

maia commented Jan 19, 2016

@rafaelfranca and @mattbrictson : Thanks for your input, but unfortunately I cannot get this to work using sprockets 3.5.2 and sprockets-rails 3.0.0, in development mode I'm seeing the following:

# in application.slim:
== stylesheet_link_tag params[:controller] if assets_manifest["#{params[:controller]}.css"]

# which raises:
undefined method `[]' for #<Sprockets::Manifest:0x007facd97e8280>

# and in console even application.css isn't available, trying both syntaxes:
> Rails.application.assets_manifest.assets["application.css"]
=> nil
> Rails.application.assets_manifest["application.css"]
NoMethodError: undefined method `[]' for #<Sprockets::Manifest:0x007f8629b59760>

Is this only supposed to work in production mode, and if yes, how would I need to check for the existence of a controller-specific .css or .js that works in both production and development mode? Thanks!

@mattbrictson

This comment has been minimized.

Show comment
Hide comment
@mattbrictson

mattbrictson Jan 19, 2016

undefined method '[]'

You need assets_manifest.assets[...], not assets_manifest[...].

[is there a solution that] works in both production and development mode?

I haven't figured this out either.

undefined method '[]'

You need assets_manifest.assets[...], not assets_manifest[...].

[is there a solution that] works in both production and development mode?

I haven't figured this out either.

@maia

This comment has been minimized.

Show comment
Hide comment
@maia

maia Jan 19, 2016

@mattbrictson I updated my comment, I did try both. The previous suggestion was made by @rafaelfranca at #294.

maia commented Jan 19, 2016

@mattbrictson I updated my comment, I did try both. The previous suggestion was made by @rafaelfranca at #294.

@maia

This comment has been minimized.

Show comment
Hide comment
@maia

maia Jan 21, 2016

@rafaelfranca what's your suggestion on how to check for existence of a controller-specific .css or .js that works in both production and development mode? Thanks!

maia commented Jan 21, 2016

@rafaelfranca what's your suggestion on how to check for existence of a controller-specific .css or .js that works in both production and development mode? Thanks!

@rafaelfranca

This comment has been minimized.

Show comment
Hide comment
@rafaelfranca

rafaelfranca Jan 21, 2016

Member

My suggestion is don't do that. Really, this add a complexity to your system that is not wort. If you really want to do that you can use resolve_asset_path. It is private API and may break in the next release. And no, we don't plan to support this kind of feature for the long term. I personally consider it a bad practice so I prefer to no support it in this gem.

Member

rafaelfranca commented Jan 21, 2016

My suggestion is don't do that. Really, this add a complexity to your system that is not wort. If you really want to do that you can use resolve_asset_path. It is private API and may break in the next release. And no, we don't plan to support this kind of feature for the long term. I personally consider it a bad practice so I prefer to no support it in this gem.

@maia

This comment has been minimized.

Show comment
Hide comment
@maia

maia Jan 21, 2016

Thanks, that's fine with me – I've merged all my controller-specific css and upgraded to 3.0.0 without problems.

maia commented Jan 21, 2016

Thanks, that's fine with me – I've merged all my controller-specific css and upgraded to 3.0.0 without problems.

@miks

This comment has been minimized.

Show comment
Hide comment
@miks

miks Jan 26, 2016

Till now if I had something like 10 controllers with unique js for each, it was very simple to include js only if it exists. How can this be bad practise? I guess it's bad practise to include 10 controller specific js assets and use only one of them (in the meantime all 10 js is running onReady handlers, searching for controller specific DOM/etc..).

miks commented Jan 26, 2016

Till now if I had something like 10 controllers with unique js for each, it was very simple to include js only if it exists. How can this be bad practise? I guess it's bad practise to include 10 controller specific js assets and use only one of them (in the meantime all 10 js is running onReady handlers, searching for controller specific DOM/etc..).

@miks

This comment has been minimized.

Show comment
Hide comment
@miks

miks Feb 15, 2016

@rafaelfranca do you have other suggestion than compile all javascripts in one big file?

miks commented Feb 15, 2016

@rafaelfranca do you have other suggestion than compile all javascripts in one big file?

@miks

This comment has been minimized.

Show comment
Hide comment
@miks

miks Feb 15, 2016

Also discovered problem when assets is not explicitly cleared. Assets now is returning previous version that does not exists anymore ex. Rails.application.assets_manifest.assets["does-not-exist-anymore.css"].
If I understand correctly, before 3.x sprockets resolved assets upon existing path in application not compiled assets.

miks commented Feb 15, 2016

Also discovered problem when assets is not explicitly cleared. Assets now is returning previous version that does not exists anymore ex. Rails.application.assets_manifest.assets["does-not-exist-anymore.css"].
If I understand correctly, before 3.x sprockets resolved assets upon existing path in application not compiled assets.

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