Skip to content
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 is nil in production #237

Closed
kirs opened this issue Apr 18, 2015 · 21 comments
Closed

Rails.application.assets is nil in production #237

kirs opened this issue Apr 18, 2015 · 21 comments

Comments

@kirs
Copy link
Member

kirs commented Apr 18, 2015

Now in sprockets-rails 3 app.assets is set only in case when assets.compile option is enabled (https://github.com/rails/sprockets-rails/blob/master/lib/sprockets/railtie.rb#L142).

By default in Rails this option is set to false in production environment: https://github.com/rails/rails/blob/master/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt#L27

This leads us to the bug when some gem calls Rails.application.assets.resolve("asset.js") in production environment and the NoMethodError is raised.

@josh does it sounds like a bug?

@josh
Copy link
Contributor

josh commented Apr 18, 2015

Thats right.

assets.compile = false is supposed to completely disable asset compilation. This prevents inadvertent calls to sprockets in production.

So it sounds like using those gems may have been behaving poorly in production before.

@rafaelfranca
Copy link
Member

Yeah. That looks right to me too.

@kirs do you know why the gem is doing that?

@kirs
Copy link
Member Author

kirs commented Apr 26, 2015

@rafaelfranca that is react-rails, for instance: https://github.com/reactjs/react-rails/blob/master/lib/react/rails/railtie.rb#L15

They do it inside lambda, but it's still being called in production with application.assets is nil.

@matthewd
Copy link
Member

ISTM the ideal would be for us to provide an application.assets that knows how to look things up from the manifest, without doing any new compilation.

That way we could help people ignore implementation details (that, IMO, they shouldn't need to care about) like where on the filesystem the assets actually live -- basically providing a more-suitably-shaped API around just using File.read.

@josh
Copy link
Contributor

josh commented May 6, 2015

It seems like this is being fixed on the react-rails side.

@josh josh closed this as completed May 6, 2015
sikachu added a commit to sikachu/sprockets-redirect that referenced this issue Jan 26, 2016
Sprockets Rails now unset `Rails.application.assets` when
`config.assets.compile` is false, causing an issue as we were relying on
that hash. The workaround here is to read the manifest file directly
by using `Sprockets::Railtie.build_manifest`.

Also adding Rails 4.2 using Sprockets Rails 2.3 to the build matrix.

See issue rails/sprockets-rails#237 for more detail.

Fix #12
sikachu added a commit to sikachu/sprockets-redirect that referenced this issue Jan 26, 2016
Sprockets Rails now unset `Rails.application.assets` when
`config.assets.compile` is false, causing an issue as we were relying on
that hash. The workaround here is to read the manifest file directly
by using `Sprockets::Railtie.build_manifest`.

Note that this patch requires the manifest file to exists, so you have
to run `rake assets:precompile` to generate the manifest file first.

Also adding Rails 4.2 using Sprockets Rails 2.3 to the build matrix.

See issue rails/sprockets-rails#237 for more detail.

Fix #12
sikachu added a commit to sikachu/sprockets-redirect that referenced this issue Jan 26, 2016
Sprockets Rails now unset `Rails.application.assets` when
`config.assets.compile` is false, causing an issue as we were relying on
that hash. The workaround here is to read the manifest file directly
by using `Sprockets::Railtie.build_manifest`.

Note that this patch requires the manifest file to exists, so you have
to run `rake assets:precompile` to generate the manifest file first.

Also adding Rails 4.2 using Sprockets Rails 2.3 to the build matrix.

See issue rails/sprockets-rails#237 for more detail.

Fix #12
beausmith added a commit to din-co/d2 that referenced this issue Feb 29, 2016
@matfiz
Copy link

matfiz commented Mar 31, 2016

Just as the reference for people trying to fix it in the local codebase after the update. The easy fix is to replace Rails.application.assets.find_asset("#{asset_name}") with Rails.application.assets_manifest.files.values.map{|v| v['logical_path']}.include?('#{asset_name}')

@Grammarella
Copy link

matfiz, thank you very much for the helpful workaround.

@matheusvetor
Copy link

Hello, my approach is different. I need to use compiled asset inline on production.
My layout uses all content inline. I need to use this way because i have a ruby client which get the html and shows on Raspberry PI.

doctype html
html lang="pt"
  head
    meta charset="utf-8"

  css:
    #{App::Application.assets["static.css"].to_s.html_safe}


  body
    header
      .top.full.left
        img(src="data:image/png;base64, #{@title_news_encoded}" class="margin-title-news left")
        img(src="data:image/png;base64, #{@text_encoded}" class="margin-text-news left")

        img(src="data:image/png;base64, #{@logo_big_encoded}" class="margin-logo-news right")
    section
      = yield

On my old Rails 4.2 app this works fine in both development and production. On my new Rails 5 app this only works on development.
Now on development App::Application.assets["static.css"] returns a Sprockets::Asset.

An additional information: My new App runs on Heroku

@fxtentacle
Copy link

fxtentacle commented Jul 12, 2016

Thanks @rafaelfranca. Rails.application.assets_manifest.find_sources('asset.js').first seems to return exactly what Rails.application.assets['asset.js'].to_s used to produce and it works both in dev and prod :)

@rafaelfranca
Copy link
Member

And doesn't compile the asset in production.

prakashmurthy referenced this issue in prakashmurthy/princely Aug 19, 2016
@hoanghuynh
Copy link

Thanks @rafaelfranca @fxtentacle that works for me!

@allenmackley
Copy link

@fxtentacle your solution worked great for me, thanks.

I had to modify it slightly by putting html_safe to this line:
return asse.to_s.html_safe if asse

And then in production.rb

config.assets.compile = true
config.assets.css_compressor = :sass

@nasa42
Copy link

nasa42 commented Jan 18, 2017

If you are looking for an exact replacement for asset = Rails.application.assets.find_asset(name), (i.e., a method that returns a Sprockets::Asset object, so that you can have access to methods like content_type), use asset = Rails.application.assets_manifest.find(name).first.

@nzifnab
Copy link

nzifnab commented Mar 30, 2017

@nasa42 Rails.application.assets_manifest.find(name).first gives the error:

"Sprockets::Error: manifest requires environment for compilation" which makes it sound like it's trying to recompile...

@nasa42
Copy link

nasa42 commented Mar 31, 2017

@nzifnab Sorry, we are no longer using that line in our app, so I don't have any more information about it.

@grosser
Copy link

grosser commented May 4, 2017

FYI I needed to find files that are not part of the manifest ... so switching to looking through gem dirs instead:

# clunky asset finder ... see https://github.com/rails/sprockets-rails/issues/237 for more
# jquery.js -> <GEM_HOME>/ruby/2.3.0/gems/rails-assets-jquery-2.2.1/app/assets/javascripts/jquery.js
def resolve_javascript(file)
  paths = Gem::Specification.stubs.map(&:full_gem_path)
  Dir.glob("{#{paths.join(",")}}/app/assets/javascripts/#{file}").first || raise("Could not find #{file}")
end

@mrsimo
Copy link

mrsimo commented Jun 15, 2017

We needed to access a compiled file within another file during precompilation, so Rails.application.assets_manifest didn't work the first time you run assets:precompile.

We solved this by doing this:

Sprockets::Railtie.build_environment(Rails.application, true)[file_name].to_s

In case anyone is in the same situation that we are.

coordt pushed a commit to CityOfBoston/successlink-frontend that referenced this issue Jan 18, 2018
coordt pushed a commit to CityOfBoston/successlink-frontend that referenced this issue Jan 18, 2018
According to this comment (rails/sprockets-rails#237 (comment)), the committed changed here is the exact replacement for the previously used method.
scott-ad-riley added a commit to moneyadviceservice/rad_consumer that referenced this issue Feb 1, 2018
In sprockets v3, when running the rails application in production mode,
`Rails.application.assets` returns nil (see:
rails/sprockets-rails#237).

The result of this returning nil would mean that when the layout file is
executed by the ruby interpreter, it would attempt to call `[]` on
`nil`, which results in the page 500ing.
scott-ad-riley added a commit to moneyadviceservice/rad_consumer that referenced this issue Feb 1, 2018
In sprockets v3, when running the rails application in production mode,
`Rails.application.assets` returns nil (see:
rails/sprockets-rails#237).

The result of this returning nil would mean that when the layout file is
executed by the ruby interpreter, it would attempt to call `[]` on
`nil`, which results in the page 500ing.
mlandauer added a commit to openaustralia/planningalerts that referenced this issue Nov 29, 2018
This will compile every time while sending the mail which is not ideal
but at least this appears to work after upgrading to rails 5
rails/sprockets-rails#237 (comment)
@tom-brown
Copy link

tom-brown commented Dec 7, 2018

I found ways to check for assets in both development and production (heroku) in Rails 5.2, but neither works in both environments, so I added an application helper like this:

def image_exists?(path)
    if Rails.env == "development" && Rails.application.assets.find_asset(path)
      return true
    elsif Rails.env == "production" && Rails.application.assets_manifest.assets[path]
      return true
    else
      return false
    end
 end

Now I can check if an image_exists in both production and development before calling image_tag. The root of the problem is image_tag throws an exception if the image doesn't exist....why not just respond nil???

etienneCharignon added a commit to betagouv/eva-serveur that referenced this issue Oct 12, 2020
En production, quand l'asset pipeline est désactivé
(config.assets.compile = false), les assets peuvent être retrouvés avec
la propriété `Rails.application.assets_manifest`.

rails/sprockets-rails#237 (comment)
etienneCharignon added a commit to betagouv/eva-serveur that referenced this issue Oct 12, 2020
En production, quand l'asset pipeline est désactivé
(config.assets.compile = false), les assets peuvent être retrouvés avec
la propriété `Rails.application.assets_manifest`.

rails/sprockets-rails#237 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests