Ruby on Rails执行rake db:migrate报can't modify frozen Hash错误
Ruby on Rails 执行rake db:migrate抛出FrozenError问题及解决方案
我参照教程配置Ruby on Rails数据库迁移,使用的Rake版本为13.0.6,运行rake db:migrate --trace时抛出如下错误,已尝试搜索线上解决方案未解决:
** Invoke db:migrate (first_time) ** Invoke db:load_config (first_time) ** Invoke environment (first_time) ** Execute environment ** Execute db:load_config ** Execute db:migrate rake aborted! FrozenError: can't modify frozen Hash: {:adapter=>"mysql2", :database=>"library_development", :username=>"root", :password=>["password"], :host=>"localhost"} C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-mysql2-adapter-0.0.3/lib/active_record/connection_adapters/mysql2_adapter.rb:11:in `mysql2_connection' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:882:in `public_send' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:882:in `new_connection' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:926:in `checkout_new_connection' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:905:in `try_to_checkout_new_connection' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:866:in `acquire_connection' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:588:in `checkout' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:428:in `connection' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:1128:in `retrieve_connection' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/connection_handling.rb:327:in `retrieve_connection' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/connection_handling.rb:283:in `connection' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/tasks/database_tasks.rb:237:in `migrate' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/railties/databases.rake:92:in `block (3 levels) in <main>' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/railties/databases.rake:90:in `each' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/activerecord-6.1.4.1/lib/active_record/railties/databases.rake:90:in `block (2 levels) in <main>' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:281:in `block in execute' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:281:in `each' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:281:in `execute' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:219:in `block in invoke_with_call_chain' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `synchronize' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `invoke_with_call_chain' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:188:in `invoke' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:160:in `invoke_task' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `block (2 levels) in top_level' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `each' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `block in top_level' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:125:in `run_with_threads' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:110:in `top_level' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:83:in `block in run' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:186:in `standard_exception_handling' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:80:in `run' C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/rake-13.0.6/exe/rake:27:in `<top (required)>' C:/Ruby30-x64/bin/rake:23:in `load' C:/Ruby30-x64/bin/rake:23:in `<main>' Tasks: TOP => db:migrate
相关配置文件
database.yml
# SQLite. Versions 3.8.0 and up are supported. # gem install sqlite3 # # Ensure the SQLite 3 gem is defined in your Gemfile # gem 'sqlite3' # default: &default adapter: sqlite3 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: # <<: *default # database: db/development.sqlite3 adapter: mysql2 database: library_development username: root password: [password] host: localhost # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: db/test.sqlite3 production: <<: *default database: db/production.sqlite3
books.rb 迁移文件
class Books < ActiveRecord::Migration[6.1] def self.up create_table :books do |t| t.column :title, :string, :limit => 32, :null => false t.column :price, :float t.column :subject_id, :integer t.column :description, :text t.column :created_at, :timestamp end end def self.down drop_table :books end end
subjects.rb 迁移文件
class Subjects < ActiveRecord::Migration[6.1] def self.up create_table :subjects do |t| t.column :name, :string end Subject.create :name => "Physics" Subject.create :name => "Mathematics" Subject.create :name => "Chemistry" Subject.create :name => "Psychology" Subject.create :name => "Geography" end def self.down drop_table :subjects end end
MySQL权限配置说明
配置权限时,教程给出的授权语句中root处提示报错,内容大致为“root is not valid at this position for this server version”,因此没有使用教程提供的语句:
mysql> grant all privileges on library_development.* to 'root'@'localhost' identified by 'password'; Query OK, 0 rows affected (0.00 sec)
实际执行的SQL语句为:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON library_development.* TO 'root'@'localhost';
修复方案
错误根因有两个,和MySQL权限配置无关,你执行的权限语句是MySQL 8.0+的标准写法,没有问题:
- database.yml密码格式错误:你写的
password: [password]会被YAML解析为数组,而mysql2适配器需要字符串类型的密码,修改为password: "你的实际密码"即可,不要加方括号。 - 依赖包冲突:你安装了废弃的
activerecord-mysql2-adaptergem,Rails 6.1已经原生支持mysql2适配器,不需要额外安装该包。打开Gemfile删除gem 'activerecord-mysql2-adapter'相关行,仅保留gem 'mysql2', '~> 0.5',执行bundle install更新依赖。
完成上述修改后重新运行rake db:migrate即可正常执行。
内容的提问来源于stack exchange,提问作者qccaprospect
相关产品推荐
相关产品推荐

