summaryrefslogtreecommitdiff
path: root/spec/support_specs/database/without_check_constraint_spec.rb
blob: d78eafd4a321a9f09d32589eabff0c9f3c6f9606 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe 'Database::WithoutCheckConstraint' do
  include MigrationsHelpers

  describe '.without_check_constraint' do
    let(:connection) { ApplicationRecord.connection }
    let(:table_name) { '_test_table' }
    let(:constraint_name) { 'check_1234' }
    let(:model) { table(table_name) }

    before do
      # Drop test table in case it's left from a previous execution.
      connection.exec_query("DROP TABLE IF EXISTS #{table_name}")
      # Model has an attribute called 'name' that can't be NULL.
      connection.exec_query(<<-SQL)
        CREATE TABLE #{table_name} (
          name text
          CONSTRAINT #{constraint_name} CHECK (name IS NOT NULL)
        );
      SQL
    end

    context 'with invalid table' do
      subject do
        without_check_constraint('no_such_table', constraint_name, connection: connection) {}
      end

      it 'raises exception' do
        msg = "'no_such_table' does not exist"
        expect { subject }.to raise_error(msg)
      end
    end

    context 'with invalid constraint name' do
      subject do
        without_check_constraint(table_name, 'no_such_constraint', connection: connection) {}
      end

      it 'raises exception' do
        msg = "'#{table_name}' table does not contain constraint called 'no_such_constraint'"
        expect { subject }.to raise_error(msg)
      end
    end

    context 'with constraint' do
      subject { connection.check_constraints(table_name) }

      it 'removes inside block' do
        without_check_constraint(table_name, constraint_name, connection: connection) do
          expect(subject).to be_empty
        end
      end

      it 'restores outside block' do
        saved_constraints = subject

        without_check_constraint(table_name, constraint_name, connection: connection) do
        end

        expect(subject).to eq(saved_constraints)
      end
    end

    context 'when creating an invalid record' do
      subject(:invalid_record) { model.create!(name: nil) }

      it 'enables invalid record creation inside block' do
        without_check_constraint(table_name, constraint_name, connection: connection) do
          expect(invalid_record).to be_persisted
          expect(invalid_record.name).to be_nil
        end
      end

      it 'rolls back changes made within the block' do
        without_check_constraint(table_name, constraint_name, connection: connection) do
          invalid_record
        end
        expect(model.all).to be_empty
      end
    end
  end
end