• ActiveRecord::Migration.maintain_test_schema!


    测试gem: rspec-rails

    问题描述

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

    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 文件中添加以下配置:

    config.active_record.schema_format = :sql

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

    问题原因

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

    具体代码分析

    rails_helper.rb

    1. # Checks for pending migrations and applies them before tests are run.
    2. # If you are not using ActiveRecord, you can remove these lines.
    3. ActiveRecord::Migration.maintain_test_schema!

    active_record/migration.rb 源码中

    1. def maintain_test_schema! #:nodoc:
    2. if ActiveRecord::Base.maintain_test_schema
    3. suppress_messages { load_schema_if_pending! }
    4. end
    5. end

    继续追溯代码:

    1. def load_schema_if_pending!
    2. # 获取数据库配置信息
    3. current_db_config = Base.connection_db_config
    4. # 读取Rails.env 中的配置信息
    5. all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
    6. # 检查是否需要更新数据库架构(重点注意)
    7. needs_update = !all_configs.all? do |db_config|
    8. Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord::Base.schema_format)
    9. end
    10. # 如果需要更新的话,清楚所有的连接,并且执行bin/rails db:test:prepare
    11. if needs_update
    12. # Roundtrip to Rake to allow plugins to hook into database initialization.
    13. root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
    14. FileUtils.cd(root) do
    15. Base.clear_all_connections!
    16. system("bin/rails db:test:prepare")
    17. end
    18. end
    19. # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
    20. Base.establish_connection(current_db_config)
    21. check_pending!
    22. end

    ActiveRecord::Base.schema_format

    这个设置有两个选项:

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

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

    • 默认使用ruby。

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

     

  • 相关阅读:
    Pytest系列-fixture的详细使用和结合conftest.py的详细使用(3)
    第十四届中国深圳创新创业大赛坪山预选赛区暨2022年“坪山高新区杯”创新创业大赛获奖名单的通知
    Python基础(七):条件语句深入了解
    认识数据分析
    node工程中package.json文件作用是什么?里面的^尖括号和~波浪号是什么意思?
    innovus:stripe下不放std cell的命令
    Linux| jq命令对JSON格式数据操作
    Python——弹幕词频统计及其文本分析(绘制词云)(含源代码)
    GO的继承重写多态反射学习
    java秋招面试一
  • 原文地址:https://blog.csdn.net/noob_cherry/article/details/132838482