提问人:John 提问时间:8/26/2023 最后编辑:John 更新时间:8/29/2023 访问量:274
运行 'rspec' 时,Rails 7 引擎中的 'FrozenError: can't modify frozen Array'
`FrozenError: can't modify frozen Array` in Rails 7 Engine when running `rspec`
问:
我刚刚将引擎从 Rails 5 升级到 Rails 7。这个错误开始出现在 Rails 6.1.7.6 中,但我认为它可能已经在 Rails 7 中修复了。
这是我运行时遇到的错误rspec
An error occurred while loading ./spec/awesome_engine/services/awesome_engine/pdf_exporter/termination_spec.rb.
Failure/Error: Rails.application.initialize!
FrozenError:
can't modify frozen Array: ["/Users/bobbert/.gem/ruby/2.7.6/gems/actiontext-7.0.7.2/app/helpers", "/Users/bobbert/.gem/ruby/2.7.6/gems/actiontext-7.0.7.2/app/models"]
# /Users/bobbert/.gem/ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/engine.rb:575:in `unshift'
# /Users/bobbert/.gem/ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/engine.rb:575:in `block in <class:Engine>'
# /Users/bobbert/.gem/ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/initializable.rb:32:in `instance_exec'
# /Users/bobbert/.gem/ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/initializable.rb:32:in `run'
# /Users/bobbert/.gem/ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/initializable.rb:61:in `block in run_initializers'
# /Users/bobbert/.gem/ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/initializable.rb:50:in `each'
# /Users/bobbert/.gem/ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/initializable.rb:50:in `tsort_each_child'
# /Users/bobbert/.gem/ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/initializable.rb:50:in `each'
# /Users/bobbert/.gem/ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/initializable.rb:50:in `tsort_each_child'
# /Users/bobbert/.gem/ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/initializable.rb:60:in `run_initializers'
# /Users/bobbert/.gem/ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/application.rb:372:in `initialize!'
# ./spec/dummy/config/environment.rb:5:in `<top (required)>'
# /Users/bobbert/.gem/ruby/2.7.6/gems/zeitwerk-2.6.11/lib/zeitwerk/kernel.rb:38:in `require'
# /Users/bobbert/.gem/ruby/2.7.6/gems/zeitwerk-2.6.11/lib/zeitwerk/kernel.rb:38:in `require'
# ./spec/spec_helper.rb:5:in `<top (required)>'
# /Users/bobbert/.gem/ruby/2.7.6/gems/zeitwerk-2.6.11/lib/zeitwerk/kernel.rb:38:in `require'
# /Users/bobbert/.gem/ruby/2.7.6/gems/zeitwerk-2.6.11/lib/zeitwerk/kernel.rb:38:in `require'
# ./spec/awesome_engine/services/awesome_engine/pdf_exporter/termination_spec.rb:1:in `<top (required)>'
...
Finished in 0.00005 seconds (files took 10.79 seconds to load)
0 examples, 0 failures, 133 errors occurred outside of examples
在尝试不同的规范时,它会多次出现,并且它总是源于规范中的第一行,然后是 ,最后是 。spec_helper.rb:5
environment.rb:5
每个规范的第一行是:
require 'spec_helper'
spec_helper.rb, Line 5
require File.expand_path("../dummy/config/environment.rb", __FILE__)
environment.rb, Line 5
Rails.application.initialize!
这是抛出错误的 Rails 代码 ():ruby/2.7.6/gems/railties-7.0.7.2/lib/rails/engine.rb:575
573 initializer :set_autoload_paths, before: :bootstrap_hook do
574 ActiveSupport::Dependencies.autoload_paths.unshift(*_all_autoload_paths)
575 ActiveSupport::Dependencies.autoload_once_paths.unshift(*_all_autoload_once_paths)
576
577 config.autoload_paths.freeze
578 config.autoload_once_paths.freeze
579 end
我一直在关注各种关于自动加载更改的 Rails 指南,包括:
- https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#autoloading-during-initialization
- https://rubyonrails.org/2021/9/3/autoloading-in-rails-7-get-ready
- https://guides.rubyonrails.org/v7.0/autoloading_and_reloading_constants.html#use-case-1-during-boot-load-reloadable-code
我还尝试了其他 Stackoverflow 问题中的建议:
- Rails:RuntimeError - 在 rails 中运行 rspec 时无法修改冻结的数组
- 无法修改冻结的数组 (TypeError) - config/application.rb:42:in '<<':
我现在已经这样做了几个小时,但没有进展。有没有人知道这里发生了什么和/或如何解决这个问题?
更新:2023 年 8 月 28 日
因此,我决定调试并单步执行代码。
总共有 573 个初始值设定项。我放置了一个断点来跟踪调用此初始值设定项的次数。这是我发现的:initializer :set_autoload_paths
engine.rb Line 574
Rails::Application.initialize! L372
Rails::Initializable::Initalizer.run_initializers L61
initializer(name: :set_autoload_paths) #initializer 103 of 573
initializer(name: :set_autoload_paths) #initializer 119 of 573
initializer(name: :set_autoload_paths) #initializer 140 of 573
initializer(name: :set_autoload_paths) #initializer 158 of 573
initializer(name: :set_autoload_paths) #initializer 171 of 573
...
在这一点上,很明显它被多次调用。因此,我决定分析数组,看看它被调用了多少次,以及谁在调用它。这是我发现的:initializers
:set_autoload_paths=>{:count=>34, :contexts=>[#<ActionView::Railtie>, #<ActiveStorage::Engine>, #<ActionCable::Engine>, #<ActionMailbox::Engine>, #<ActionText::Engine>, #<StateMachine::RailsEngine>, #<Select2::Rails::Engine>, #<Doccex::Engine>, #<SmartListing::Engine>, #<Kaminari::Engine>, #<Devise::Engine>, #<DeviseInvitable::Engine>, #<Bootstrap::Rails::Engine>, #<Bootstrap::Switch::Rails::Engine>, #<Cocoon::Engine>, #<FontAwesome::Rails::Engine>, #<Remotipart::Rails::Engine>, #<I18n::JS::Engine>, #<Jquery::Rails::Engine>, #<Jquery::Ui::Rails::Engine>, #<JsRoutes::Engine>, #<DropzonejsRails::Engine>, #<TinyMCE::Rails::Engine>, #<BootstrapDatepickerRails::Rails::Engine>, #<Bootstrap3Datetimepicker::Rails::Engine>, #<Momentjs::Rails::Engine>, #<Uri::Js::Rails::Engine>, #<Sidekiq::Rails>, #<ActsAsTaggableOn::Engine>, #<Jscolor::Rails::Engine>, #<Tribute::Engine>, #<Doorkeeper::Engine>, #<AwesomeEngine::Engine>, #<Dummy::Application>]}
它被各种引擎调用了 34 次,其中一些来自 Rails 框架,但大多数来自引擎 gemspec 中包含的第三方库。
答: 暂无答案
评论
Similarly, engines can configure that collection in the class body of the engine class or in the configuration for environments.
autoload_once_paths
autoload_once_paths
autoload_paths
engine.rb
application.rb
config/environments/test.rb
ActiveSupport::Dependencies.autoload_once_paths