aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/associations/required_test.rb
blob: 6cf2d8ac12194eed592fcffe9a75f6f315114a36 (plain) (blame)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# frozen_string_literal: true
require "cases/helper"

class RequiredAssociationsTest < ActiveRecord::TestCase
  self.use_transactional_tests = false

  class Parent < ActiveRecord::Base
  end

  class Child < ActiveRecord::Base
  end

  setup do
    @connection = ActiveRecord::Base.connection
    @connection.create_table :parents, force: true
    @connection.create_table :children, force: true do |t|
      t.belongs_to :parent
    end
  end

  teardown do
    @connection.drop_table "parents", if_exists: true
    @connection.drop_table "children", if_exists: true
  end

  test "belongs_to associations can be optional by default" do
    begin
      original_value = ActiveRecord::Base.belongs_to_required_by_default
      ActiveRecord::Base.belongs_to_required_by_default = false

      model = subclass_of(Child) do
        belongs_to :parent, inverse_of: false,
          class_name: "RequiredAssociationsTest::Parent"
      end

      assert model.new.save
      assert model.new(parent: Parent.new).save
    ensure
      ActiveRecord::Base.belongs_to_required_by_default = original_value
    end
  end

  test "required belongs_to associations have presence validated" do
    model = subclass_of(Child) do
      belongs_to :parent, required: true, inverse_of: false,
        class_name: "RequiredAssociationsTest::Parent"
    end

    record = model.new
    assert_not record.save
    assert_equal ["Parent must exist"], record.errors.full_messages

    record.parent = Parent.new
    assert record.save
  end

  test "belongs_to associations can be required by default" do
    begin
      original_value = ActiveRecord::Base.belongs_to_required_by_default
      ActiveRecord::Base.belongs_to_required_by_default = true

      model = subclass_of(Child) do
        belongs_to :parent, inverse_of: false,
          class_name: "RequiredAssociationsTest::Parent"
      end

      record = model.new
      assert_not record.save
      assert_equal ["Parent must exist"], record.errors.full_messages

      record.parent = Parent.new
      assert record.save
    ensure
      ActiveRecord::Base.belongs_to_required_by_default = original_value
    end
  end

  test "has_one associations are not required by default" do
    model = subclass_of(Parent) do
      has_one :child, inverse_of: false,
        class_name: "RequiredAssociationsTest::Child"
    end

    assert model.new.save
    assert model.new(child: Child.new).save
  end

  test "required has_one associations have presence validated" do
    model = subclass_of(Parent) do
      has_one :child, required: true, inverse_of: false,
        class_name: "RequiredAssociationsTest::Child"
    end

    record = model.new
    assert_not record.save
    assert_equal ["Child must exist"], record.errors.full_messages

    record.child = Child.new
    assert record.save
  end

  test "required has_one associations have a correct error message" do
    model = subclass_of(Parent) do
      has_one :child, required: true, inverse_of: false,
      class_name: "RequiredAssociationsTest::Child"
    end

    record = model.create
    assert_equal ["Child must exist"], record.errors.full_messages
  end

  test "required belongs_to associations have a correct error message" do
    model = subclass_of(Child) do
      belongs_to :parent, required: true, inverse_of: false,
      class_name: "RequiredAssociationsTest::Parent"
    end

    record = model.create
    assert_equal ["Parent must exist"], record.errors.full_messages
  end

  private

    def subclass_of(klass, &block)
      subclass = Class.new(klass, &block)
      def subclass.name
        superclass.name
      end
      subclass
    end
end