db_migration.rb 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. # require all database migrations so we can test them without manual require
  2. Rails.root.join('db', 'migrate').children.each do |migration|
  3. require migration.to_s
  4. end
  5. module DbMigrationHelper
  6. # Provides a helper method to execute a migration for the current class.
  7. # Make sure to define type: :db_migration in your RSpec.describe call.
  8. #
  9. # @param [Symbol] direction the migration should take (:up or :down)
  10. # @yield [instance] Yields the created instance of the
  11. # migration to allow expectations or other changes to it
  12. #
  13. # @example
  14. # migrate
  15. #
  16. # @example
  17. # migrate(:down)
  18. #
  19. # @return [nil]
  20. def migrate(direction = :up)
  21. instance = described_class.new
  22. yield(instance) if block_given?
  23. instance.suppress_messages do
  24. instance.migrate(direction)
  25. end
  26. end
  27. # Provides a helper method to remove foreign_keys if exist.
  28. # Make sure to define type: :db_migration in your RSpec.describe call
  29. # and add `self.use_transactional_tests = false` to your context.
  30. #
  31. # ATTENTION: We do not use the same arguments as the internally
  32. # used methods since giving a table name
  33. # as a second argument as e.g.
  34. # `remove_foreign_key(:online_notifications, :users)`
  35. # doesn't remove the index at first execution on at least MySQL
  36. #
  37. # @param [Symbol] from_table the name of the table with the foreign_key column
  38. # @param [Symbol] column the name of the foreign_key column
  39. #
  40. # @example
  41. # witout_foreign_key(:online_notifications, column: :user_id)
  42. #
  43. # @return [nil]
  44. def witout_foreign_key(from_table, column:)
  45. suppress_messages do
  46. break if !foreign_key_exists?(from_table, column: column)
  47. remove_foreign_key(from_table, column: column)
  48. end
  49. end
  50. # Enables the usage of `ActiveRecord::Migration` methods.
  51. #
  52. # @see ActiveRecord::Migration
  53. #
  54. # @example
  55. # remove_foreign_key(:online_notifications, :users)
  56. #
  57. # @return [nil]
  58. def method_missing(method, *args, &blk)
  59. ActiveRecord::Migration.send(method, *args, &blk)
  60. rescue NoMethodError
  61. super
  62. end
  63. # Enables the usage of `ActiveRecord::Migration` methods.
  64. #
  65. # @see ActiveRecord::Migration
  66. #
  67. # @example
  68. # remove_foreign_key(:online_notifications, :users)
  69. #
  70. # @return [nil]
  71. def respond_to_missing?(*)
  72. true
  73. end
  74. # Provides a helper method to check if migration class adds a foreign key.
  75. # Make sure to define type: :db_migration in your RSpec.describe call
  76. # and add `self.use_transactional_tests = false` to your context.
  77. #
  78. # @param [Symbol] from_table the name of the table with the foreign_key column
  79. # @param [Symbol] column the name of the foreign_key column
  80. #
  81. # @example
  82. # adds_foreign_key(:online_notifications, column: :user_id)
  83. #
  84. # @return [nil]
  85. def adds_foreign_key(from_table, column:)
  86. witout_foreign_key(from_table, column: column)
  87. suppress_messages do
  88. expect do
  89. migrate
  90. end.to change {
  91. foreign_key_exists?(from_table, column: column)
  92. }
  93. end
  94. end
  95. def self.included(base)
  96. # Execute in RSpec class context
  97. base.class_exec do
  98. # This method simulates a system that is is already initialized
  99. # aka `Setting.exists?(name: 'system_init_done')`
  100. # It's possible to simulate a not yet initialized system by adding the
  101. # meta tag `system_init_done` to `false` to the needing example:
  102. #
  103. # @example
  104. # it 'does stuff in an unitialized system', system_init_done: false do
  105. #
  106. before(:each) do |example|
  107. initialized = example.metadata.fetch(:system_init_done, true)
  108. system_init_done(initialized)
  109. end
  110. end
  111. end
  112. end
  113. RSpec.configure do |config|
  114. config.include DbMigrationHelper, type: :db_migration
  115. end