aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/validations/association_validation_test.rb
blob: 768fbc5b0a2b566391dcbb8a22e0bc895222b046 (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
# encoding: utf-8
require "cases/helper"
require 'models/topic'
require 'models/reply'
require 'models/owner'
require 'models/pet'
require 'models/man'
require 'models/interest'

class AssociationValidationTest < ActiveRecord::TestCase
  fixtures :topics, :owners

  repair_validations(Topic, Reply, Owner)

  def test_validates_size_of_association
    assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
    o = Owner.new('name' => 'nopets')
    assert !o.save
    assert o.errors[:pets].any?
    o.pets.build('name' => 'apet')
    assert o.valid?
  end

  def test_validates_size_of_association_using_within
    assert_nothing_raised { Owner.validates_size_of :pets, :within => 1..2 }
    o = Owner.new('name' => 'nopets')
    assert !o.save
    assert o.errors[:pets].any?

    o.pets.build('name' => 'apet')
    assert o.valid?

    2.times { o.pets.build('name' => 'apet') }
    assert !o.save
    assert o.errors[:pets].any?
  end

  def test_validates_associated_many
    Topic.validates_associated(:replies)
    Reply.validates_presence_of(:content)
    t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
    t.replies << [r = Reply.new("title" => "A reply"), r2 = Reply.new("title" => "Another reply", "content" => "non-empty"), r3 = Reply.new("title" => "Yet another reply"), r4 = Reply.new("title" => "The last reply", "content" => "non-empty")]
    assert !t.valid?
    assert t.errors[:replies].any?
    assert_equal 1, r.errors.count  # make sure all associated objects have been validated
    assert_equal 0, r2.errors.count
    assert_equal 1, r3.errors.count
    assert_equal 0, r4.errors.count
    r.content = r3.content = "non-empty"
    assert t.valid?
  end

  def test_validates_associated_one
    Reply.validates :topic, :associated => true
    Topic.validates_presence_of( :content )
    r = Reply.new("title" => "A reply", "content" => "with content!")
    r.topic = Topic.create("title" => "uhohuhoh")
    assert !r.valid?
    assert r.errors[:topic].any?
    r.topic.content = "non-empty"
    assert r.valid?
  end

  def test_validates_associated_marked_for_destruction
    Topic.validates_associated(:replies)
    Reply.validates_presence_of(:content)
    t = Topic.new
    t.replies << Reply.new
    assert t.invalid?
    t.replies.first.mark_for_destruction
    assert t.valid?
  end

  def test_validates_associated_with_custom_message_using_quotes
    Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
    Topic.validates_presence_of :content
    r = Reply.create("title" => "A reply", "content" => "with content!")
    r.topic = Topic.create("title" => "uhohuhoh")
    assert !r.valid?
    assert_equal ["This string contains 'single' and \"double\" quotes"], r.errors[:topic]
  end

  def test_validates_associated_missing
    Reply.validates_presence_of(:topic)
    r = Reply.create("title" => "A reply", "content" => "with content!")
    assert !r.valid?
    assert r.errors[:topic].any?

    r.topic = Topic.find :first
    assert r.valid?
  end

  def test_validates_size_of_association_utf8
    with_kcode('UTF8') do
      assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
      o = Owner.new('name' => 'あいうえおかきくけこ')
      assert !o.save
      assert o.errors[:pets].any?
      o.pets.build('name' => 'あいうえおかきくけこ')
      assert o.valid?
    end
  end

  def test_validates_presence_of_belongs_to_association__parent_is_new_record
    repair_validations(Interest) do
      # Note that Interest and Man have the :inverse_of option set
      Interest.validates_presence_of(:man)
      man = Man.new(:name => 'John')
      interest = man.interests.build(:topic => 'Airplanes')
      assert interest.valid?, "Expected interest to be valid, but was not. Interest should have a man object associated"
    end
  end

  def test_validates_presence_of_belongs_to_association__existing_parent
    repair_validations(Interest) do
      Interest.validates_presence_of(:man)
      man = Man.create!(:name => 'John')
      interest = man.interests.build(:topic => 'Airplanes')
      assert interest.valid?, "Expected interest to be valid, but was not. Interest should have a man object associated"
    end
  end

end