rails / sprockets

Rack-based asset packaging system
MIT License
947 stars 788 forks source link

4.0 error undefined method start_with? #632

Closed jason-hobbs closed 4 years ago

jason-hobbs commented 4 years ago

When I run rspec or rails server with sprockets updated to 4.0 I get: undefined method `start_with?' for #

/Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/uri_utils.rb:78:in `valid_asset_uri?'

I have no idea what this is referring to in my code. I had no issues with sprockets 3.7.2

schneems commented 4 years ago

Hello, please follow the issue template, without an example app there's not a very large chance that i'll be able to help.

### Expected behavior

Tell us what should happen

### Actual behavior

Tell us what happens instead

### System configuration

- Sprockets version
- Ruby version

### Example App

Please provide an [example app](https://www.codetriage.com/example_app) that reproduces the problem. This will save maintainers time so they can spend it fixing your issues instead of trying to build a reproduction case from sparse instructions.

To create an example app, make an application locally that uses your same version of Sprockets. Add files to reproduce the problem. Once you've reproduced the problem add instructions on how to run your example app to a README.md file. Then commit everything to git and push to a new project on github. Once you've pushed your app add a link back to this issue.

[More information about example apps](https://www.codetriage.com/example_app)
ahorek commented 4 years ago

@jason-hobbs you probably have a pattern like this somewhere in your code base

Rails.application.configure do
  config.assets.precompile.concat [
    proc do |logical_path, filename|
      true # logic
    end
  ]
end

@schneems is that something that suppose to work in the first place?

schneems commented 4 years ago

is that something that suppose to work in the first place?

In general we're pushing people to move to the manifest.js https://schneems.com/2017/11/22/self-hosted-config-introducing-the-sprockets-manifestjs/ . I don't have a more concrete answer here. I looked in the code and I don't see where we would be calling a proc with 4.0 so I'm assuming it's removal was intentional.

I do know that LOOSE_APP_ASSETS was originally a proc in rails-sprockets but then it was moved over to use the manifest.js. I honestly don't know where in the code in 3.x supported that ability so I don't know where to start looking to tell you when it changed and if it was truly intentional.

schneems commented 4 years ago

Okay in our docs "How Sprockets Work" talk from Rafael. I think this is intentional, but I don't know why we didn't deprecate the interface first.


Sprockets has special support for Procs on the precompilation. Before, in Sprockets version 3, we had this code that is telling us to precompile all the known JavaScript and stylesheet files in the app directory.

LOOSE_APP_ASSETS = lambda do |logical_path, filename|
  filename.start_with?(::Rails.root.join('app/assets').to_s) &&
    !['.js', '.css', ''].include?(File.extname(logical_path))
end

config.assets.precompile = [LOOSE_APP_ASSETS, /(?:\/|\\|\A)application\.(.css|js)$/]

As you can see, the code above is not easy to understand, so in Sprockets version 4, we have a new syntax for that shown below:

// app/assets/config/manifest.js
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
//= link my_engine

// my_engine/app/assets/config/my_engine.js
//= link_tree ../images/bootstrap

It's called the link directive, so it's easier to understand what's going on there. You can actually see that all the images in the image directory is going to be precompiled just as the JavaScript and the style sheets do. One can use this directive to compose new libraries. I have that link to my engine that's also defining its own manifest file. It's now easy to understand and to compose. Not that we are going to remove the precompile list, but these new directives are there to help to build the precompile list. We have all these directives by default in Sprockets and later we will explain how you can extend the directives to create your own.

schneems commented 4 years ago

Okay, so here's the integration point with Sprockets and sprockets-rails

      @precompiled_assets ||= assets_manifest.find(config.assets.precompile).map(&:logical_path).to_set

The precompile array gets passed into the Manifest#find function which then does things like check for formatting, this is from the 3.x branch https://github.com/rails/sprockets/blob/4174470846e4b338bd854ad5d662f6f6268a7336/lib/sprockets/manifest.rb#L121-L150

It uses a lot of files in the legacy file https://github.com/rails/sprockets/blob/3.x/lib/sprockets/legacy.rb

If there's an interface people are using that is not supported in 4.0 then we need to deprecate it and cut a release of 3.x so at least some people get a little heads up. I'm still not sure exactly where the proc support exists.

geoffharcourt commented 4 years ago

I don't have a proc (that I know of) related to assets, and I've been getting the same error while trying to port our Sprockets 3.x setup to 4.0. I'm looking into a smaller, reproducible test case. We're running Rails 6.0.0.

geoffharcourt commented 4 years ago

I suspect that in our case this might come from ActiveAdmin:

https://github.com/activeadmin/activeadmin/blob/9a33a081c99d9aa19045d46155ffe5f51ea76710/lib/active_admin/engine.rb

jason-hobbs commented 4 years ago

@jason-hobbs you probably have a pattern like this somewhere in your code base

Rails.application.configure do
  config.assets.precompile.concat [
    proc do |logical_path, filename|
      true # logic
    end
  ]
end

@schneems is that something that suppose to work in the first place?

I have nothing like that in my app.

jason-hobbs commented 4 years ago

Here is more of the error:

Failure/Error: str.start_with?("file://".freeze) && parse_asset_uri(str) ? true : false

      ActionView::Template::Error:
        undefined method `start_with?' for #<Proc:0x00007fb892962448>
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/uri_utils.rb:78:in `valid_asset_uri?'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/resolve.rb:27:in `resolve'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/base.rb:79:in `find_asset'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/base.rb:88:in `find_all_linked_assets'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/manifest.rb:125:in `block (2 levels) in find'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/safe_task_executor.rb:24:in `block in execute'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/synchronization/mutex_lockable_object.rb:41:in `block in synchronize'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/synchronization/mutex_lockable_object.rb:41:in `synchronize'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/synchronization/mutex_lockable_object.rb:41:in `synchronize'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/safe_task_executor.rb:19:in `execute'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/promise.rb:563:in `block in realize'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:348:in `run_task'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:337:in `block (3 levels) in create_worker'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `loop'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `block (2 levels) in create_worker'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `catch'
      # /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `block in create_worker'
      # ------------------
      # --- Caused by: ---
      # NoMethodError:
      #   undefined method `start_with?' for #<Proc:0x00007fb892962448>
      #   /Users/jasonhobbs/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/uri_utils.rb:78:in `valid_asset_uri?'
majksner commented 4 years ago

I'm getting same error on Rails 6, Rails 5 is fine.

➜ RAILS_ENV=staging bundle exec rake assets:precompile --trace
** Invoke assets:precompile (first_time)
** Invoke assets:environment (first_time)
** Execute assets:environment
** Invoke environment (first_time)
** Execute environment
** Invoke yarn:install (first_time)
** Execute yarn:install
** Execute assets:precompile
rake aborted!
NoMethodError: undefined method `start_with?' for /\.(?:svg|eot|woff|ttf)$/:Regexp
/app/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/uri_utils.rb:78:in `valid_asset_uri?'
/app/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/resolve.rb:27:in `resolve'
/app/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/base.rb:79:in `find_asset'
/app/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/base.rb:88:in `find_all_linked_assets'
/app/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/manifest.rb:125:in `block (2 levels) in find'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/safe_task_executor.rb:24:in `block in execute'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/synchronization/mutex_lockable_object.rb:41:in `block in synchronize'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/synchronization/mutex_lockable_object.rb:41:in `synchronize'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/synchronization/mutex_lockable_object.rb:41:in `synchronize'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/safe_task_executor.rb:19:in `execute'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/promise.rb:563:in `block in realize'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:348:in `run_task'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:337:in `block (3 levels) in create_worker'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `loop'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `block (2 levels) in create_worker'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `catch'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `block in create_worker'
Tasks: TOP => assets:precompile
ahorek commented 4 years ago

this might help you to investigate

rails c
Rails.application.config.assets.precompile.select{ |path| path.is_a?(Proc) }
=> [#<Proc:0x000000000c320198@/source/init.rb:78>]

it's an error since https://github.com/rails/sprockets/commit/8c8cccf0f554299f8be85a0b8b2fe4bc23732b4f#diff-56b8a4f4a3946e2ca1750c8580181925L24

geoffharcourt commented 4 years ago

@ahorek this was super-helpful. Our instances of this came from PGHero and Searchjoy, not from ActiveAdmin as I had suspected.

jason-hobbs commented 4 years ago

I just updated the blazer gem in my app to 2.2.1 and it fixed this issue!

schneems commented 4 years ago

It sounds like proc support was definitively removed, though i'm still not quite sure where.

We should add a deprecation in 3.x for this. I'm assuming that regex support was also removed. Surprised we didn't catch this earlier since we've been in beta since 2016.

marckohlbrugge commented 4 years ago

Just wanted to chime in and let you know that I ran into this same issue when using regexes. I think I found an article somewhere explaining how to add webfonts to the asset pipeline by adding this code to config/initializers/assets.rb

Rails.application.config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/

I have now replaced it with the following which fixed the issue for me:

Rails.application.config.assets.precompile << ["*.svg", "*.eot", "*.woff", "*.ttf"]
cassiopagnoncelli commented 4 years ago

Downgraded gem sprockets from 4.0.0 to 3.7.2

gem 'sprockets', '~> 3.7.2'
rafaelrpbelo commented 4 years ago

I am getting this error when when I'm trying to call Webpacker.manifest.lookup('somefile.js') in some initializer file.

I added line above to make ActiveAdmin work with ActionText. The development environment it goes well, but in production I'm getting error.

# config/initializers/active_admin.rb

config.register_javascript Webpacker.manifest.lookup('action_text.js')

Error that I got:

remote:        rake aborted!                                                                   
remote:        NoMethodError: undefined method `start_with?' for nil:NilClass                  
remote:        /tmp/build_7789188117c20159cb293bb59e3995ee/vendor/bundle/ruby/2.6.0/gems/sprockets-4.0.0/lib/sprockets/uri_utils.rb:78:in `valid_asset_uri?'                                   
remote:        /tmp/build_7789188117c20159cb293bb59e3995ee/vendor/bundle/ruby/2.6.0/gems/sprockets-4.0.0/lib/sprockets/resolve.rb:27:in `resolve'                                              
remote:        /tmp/build_7789188117c20159cb293bb59e3995ee/vendor/bundle/ruby/2.6.0/gems/sprockets-4.0.0/lib/sprockets/base.rb:79:in `find_asset'                                              
remote:        /tmp/build_7789188117c20159cb293bb59e3995ee/vendor/bundle/ruby/2.6.0/gems/sprockets-4.0.0/lib/sprockets/base.rb:88:in `find_all_linked_assets'                                  
remote:        /tmp/build_7789188117c20159cb293bb59e3995ee/vendor/bundle/ruby/2.6.0/gems/sprockets-4.0.0/lib/sprockets/manifest.rb:125:in `block (2 levels) in find'

This happened due I have no assets compiled yet when this code ran, so Webpacker.manifest.lokkup('action_text.js') returns nil.

Kani999 commented 4 years ago

I'm getting same error on Rails 6, Rails 5 is fine.

➜ RAILS_ENV=staging bundle exec rake assets:precompile --trace
** Invoke assets:precompile (first_time)
** Invoke assets:environment (first_time)
** Execute assets:environment
** Invoke environment (first_time)
** Execute environment
** Invoke yarn:install (first_time)
** Execute yarn:install
** Execute assets:precompile
rake aborted!
NoMethodError: undefined method `start_with?' for /\.(?:svg|eot|woff|ttf)$/:Regexp
/app/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/uri_utils.rb:78:in `valid_asset_uri?'
/app/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/resolve.rb:27:in `resolve'
/app/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/base.rb:79:in `find_asset'
/app/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/base.rb:88:in `find_all_linked_assets'
/app/.rvm/gems/ruby-2.6.5/gems/sprockets-4.0.0/lib/sprockets/manifest.rb:125:in `block (2 levels) in find'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/safe_task_executor.rb:24:in `block in execute'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/synchronization/mutex_lockable_object.rb:41:in `block in synchronize'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/synchronization/mutex_lockable_object.rb:41:in `synchronize'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/synchronization/mutex_lockable_object.rb:41:in `synchronize'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/safe_task_executor.rb:19:in `execute'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/promise.rb:563:in `block in realize'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:348:in `run_task'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:337:in `block (3 levels) in create_worker'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `loop'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `block (2 levels) in create_worker'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `catch'
/app/.rvm/gems/ruby-2.6.5/gems/concurrent-ruby-1.1.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `block in create_worker'
Tasks: TOP => assets:precompile

@majksner Did you resolve your problem? I'm currently having the same problem.

majksner commented 4 years ago

@Kani999 You have to check 3rd party gems. Some of those are culprit. Check https://github.com/rails/sprockets/issues/632#issuecomment-540032759

Kani999 commented 4 years ago

@majksner Thanks for the tip, but only thing related to mine problem I can found is Regexp /\.(?:svg|eot|woff|woff2|ttf)$/ but no info about what cause this. It will be a monkey business then.

europ commented 4 years ago

I had the same problem here (related to bootstrap).

Installing Bootstrap

I was following the installation guide available in the blog below: https://www.timdisab.com/installing-bootstrap-4-on-rails-6/

Then, I also tried to install the bootstrap using the following ruby bootstrap gems:

gem 'bootstrap-sass'
gem 'bootstrap-generators'
gem 'jquery-rails'

via command below:

bundle install
bundle exec rails generate bootstrap:install

I got the same error

ActionView::Template::Error (undefined method `start_with?' for /\.(?:svg|eot|woff|woff2|ttf)$/:Regexp)

After all, it was not working due to an incorrect gem (sprockets) version.

By downgrading the specific ruby gem (sprockets), the bootstrap was successfully added to my rails-6 project.

Enviroment

ruby ................ 2.7.1
rails ............... 6.0.3.3
gem 'sprockets' ..... 4.0.2

Error

ActionView::Template::Error (undefined method `start_with?' for /\.(?:svg|eot|woff|woff2|ttf)$/:Regexp):

sprockets (4.0.2) lib/sprockets/uri_utils.rb:78:in `valid_asset_uri?'
sprockets (4.0.2) lib/sprockets/resolve.rb:27:in `resolve'
sprockets (4.0.2) lib/sprockets/base.rb:79:in `find_asset'
sprockets (4.0.2) lib/sprockets/base.rb:88:in `find_all_linked_assets'
sprockets (4.0.2) lib/sprockets/manifest.rb:125:in `block (2 levels) in find'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb:24:in `block in execute'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:41:in `block in synchronize'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:41:in `synchronize'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:41:in `synchronize'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb:19:in `execute'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/promise.rb:563:in `block in realize'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:363:in `run_task'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:352:in `block (3 levels) in create_worker'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:335:in `loop'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:335:in `block (2 levels) in create_worker'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:334:in `catch'
concurrent-ruby (1.1.7) lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:334:in `block in create_worker'

Solution

Downgrade your sprockets gem in your Gemfile as it was suggested by @cassiopagnoncelli in https://github.com/rails/sprockets/issues/632#issuecomment-559861344

Add the following line to the Gemfile:

gem 'sprockets', '~> 3.7.2'

Then, run the following commands:

bundle update sprockets

bundle exec rake assets:precompile --trace
stereodenis commented 3 years ago

so rails now is not working with sprockets@4?

IEConsultores2020 commented 2 years ago

[osboxes@osboxes exec-central]$ bundle exec rake assets:precompile --trace Invoke assets:precompile (first_time) Invoke assets:environment (first_time) Execute assets:environment Invoke environment (first_time) Execute environment Invoke yarn:install (first_time) Execute yarn:install Execute assets:precompile rake aborted! Sprockets::FileNotFound: couldn't find file 'alchemy/admin/all.css' Checked in these paths: /home/osboxes/Railsapps/exec-central/app/assets/config /home/osboxes/Railsapps/exec-central/app/assets/fonts /home/osboxes/Railsapps/exec-central/app/assets/images /home/osboxes/Railsapps/exec-central/app/assets/javascripts /home/osboxes/Railsapps/exec-central/app/assets/stylesheets /home/osboxes/Railsapps/exec-central/vendor/assets/javascripts /home/osboxes/Railsapps/exec-central/vendor/assets/stylesheets /home/osboxes/Railsapps/exec-central/vendor/bundle/ruby/2.7.0/gems/alchemy_cms-5.2.3/app/assets/config

RoRroland commented 4 months ago

downgraded to gem 'sprockets', '~> 3.7.2' fix the issue for me. Thanks @europ

rolandoalvarado commented 4 months ago

downgraded to gem 'sprockets', '~> 3.7.2' fix the issue for me. Thanks @europ