ActiveRecord::Migration.maintain_test_schema!

测试gem: rspec-rails

问题描述

在使用 rspec-rails 进行测试时,出现了以下错误

ruby 复制代码
ActiveRecord::StatementInvalid: UndefinedFunction: ERROR: function init_id() does not exist

这个错误与数据库架构有关。

schema.rb中

create_table "users", id: :string, default: -> { "init_id()" }, force: :cascade do |t|

解决办法

为了解决这个问题,你需要在 config/environments/test.rb 文件中添加以下配置:

ruby 复制代码
config.active_record.schema_format = :sql

这会将数据库架构格式更改为 SQL 格式,以避免出现错误。

问题原因

这个问题的根本原因在于,在运行RSpec测试时,rspec-rails 试图更新数据库架构,但默认情况下,Rails 使用 schema.rb 文件来表示数据库架构,而不是 SQL 文件。因此,需要将配置更改为使用 SQL 格式的架构。

具体代码分析

rails_helper.rb

ruby 复制代码
# Checks for pending migrations and applies them before tests are run.
# If you are not using ActiveRecord, you can remove these lines.
ActiveRecord::Migration.maintain_test_schema!

active_record/migration.rb 源码中

ruby 复制代码
 def maintain_test_schema! #:nodoc:
   if ActiveRecord::Base.maintain_test_schema
     suppress_messages { load_schema_if_pending! }
   end
 end

继续追溯代码:

ruby 复制代码
      def load_schema_if_pending!
        # 获取数据库配置信息
        current_db_config = Base.connection_db_config
        # 读取Rails.env 中的配置信息
        all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
        # 检查是否需要更新数据库架构(重点注意)
        needs_update = !all_configs.all? do |db_config|
          Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord::Base.schema_format)
        end
        # 如果需要更新的话,清楚所有的连接,并且执行bin/rails db:test:prepare
        if needs_update
          # Roundtrip to Rake to allow plugins to hook into database initialization.
          root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
          FileUtils.cd(root) do
            Base.clear_all_connections!
            system("bin/rails db:test:prepare")
          end
        end

        # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
        Base.establish_connection(current_db_config)

        check_pending!
      end

ActiveRecord::Base.schema_format

这个设置有两个选项:

  • :sql:当设置为 :sql 时,数据库架构将以数据库特定的 SQL 语句的形式导出。这意味着导出的文件将包含数据库特定的 SQL 命令,可以在相同类型的数据库中使用。

  • :ruby:当设置为 :ruby 时,数据库架构将以 ActiveRecord::Schema 的格式导出。这是一个通用的格式,可以加载到支持迁移的任何数据库中。这允许您在不同的数据库适配器之间共享相同的数据库架构定义,例如在开发和测试环境中使用不同的数据库

  • 默认使用ruby。

  • :ruby 格式下导出数据库架构时,通常不会包括数据库中定义的函数(方法)。这是因为 :ruby 格式主要用于导出数据库表格的结构和约束,以及与 ActiveRecord 迁移相关的信息,而不包括数据库中的自定义函数、存储过程或触发器。

相关推荐
数据库学啊17 分钟前
国产时序数据库哪个靠谱
数据库·时序数据库
网安老伯25 分钟前
什么是网络安全?网络安全包括哪几个方面?学完能做一名黑客吗?
linux·数据库·python·web安全·网络安全·php·xss
瀚高PG实验室41 分钟前
postgresql日期/时间数据类型中有无时区的差异使用
数据库·postgresql·瀚高数据库
Elastic 中国社区官方博客1 小时前
Elasticsearch 中的文档级基于属性的访问控制 - ABAC
大数据·数据库·elasticsearch·搜索引擎·全文检索
数据库学啊1 小时前
国产时序数据库供应商排名
数据库·时序数据库
汽车仪器仪表相关领域1 小时前
MTX-AL:传统指针美学与现代数字科技的完美融合 - 模拟宽带空燃比计
大数据·人工智能·科技·单元测试·汽车·压力测试·可用性测试
songtaiwu1 小时前
golang开发日常注意
开发语言·数据库·golang
NineData1 小时前
NineData社区版V4.7.0发布!新增MySQL至TiDB等6条数据复制对比链路,SQL窗口新增谷歌云6种数据源类型
数据库·dba
乄bluefox2 小时前
如何快速迁移redis - RedisShake(RDB方式)
数据库·redis·缓存
踢球的打工仔2 小时前
mysql外键
数据库·mysql