aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/dup_test.rb
blob: a2efbf89f9922504894dc421e22951971f4e0968 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# frozen_string_literal: true

require "cases/helper"
require "models/reply"
require "models/topic"
require "models/movie"

module ActiveRecord
  class DupTest < ActiveRecord::TestCase
    fixtures :topics

    def test_dup
      assert_not_predicate Topic.new.freeze.dup, :frozen?
    end

    def test_not_readonly
      topic = Topic.first

      duped = topic.dup
      assert_not duped.readonly?, "should not be readonly"
    end

    def test_is_readonly
      topic = Topic.first
      topic.readonly!

      duped = topic.dup
      assert duped.readonly?, "should be readonly"
    end

    def test_dup_not_persisted
      topic = Topic.first
      duped = topic.dup

      assert_not duped.persisted?, "topic not persisted"
      assert duped.new_record?, "topic is new"
    end

    def test_dup_not_destroyed
      topic = Topic.first
      topic.destroy

      duped = topic.dup
      assert_not_predicate duped, :destroyed?
    end

    def test_dup_has_no_id
      topic = Topic.first
      duped = topic.dup
      assert_nil duped.id
    end

    def test_dup_with_modified_attributes
      topic = Topic.first
      topic.author_name = "Aaron"
      duped = topic.dup
      assert_equal "Aaron", duped.author_name
    end

    def test_dup_with_changes
      dbtopic = Topic.first
      topic = Topic.new

      topic.attributes = dbtopic.attributes.except("id")

      # duped has no timestamp values
      duped = dbtopic.dup

      # clear topic timestamp values
      topic.send(:clear_timestamp_attributes)

      assert_equal topic.changes, duped.changes
    end

    def test_dup_topics_are_independent
      topic = Topic.first
      topic.author_name = "Aaron"
      duped = topic.dup

      duped.author_name = "meow"

      assert_not_equal topic.changes, duped.changes
    end

    def test_dup_attributes_are_independent
      topic = Topic.first
      duped = topic.dup

      duped.author_name = "meow"
      topic.author_name = "Aaron"

      assert_equal "Aaron", topic.author_name
      assert_equal "meow", duped.author_name
    end

    def test_dup_timestamps_are_cleared
      topic = Topic.first
      assert_not_nil topic.updated_at
      assert_not_nil topic.created_at

      # temporary change to the topic object
      topic.updated_at -= 3.days

      # dup should not preserve the timestamps if present
      new_topic = topic.dup
      assert_nil new_topic.updated_at
      assert_nil new_topic.created_at

      new_topic.save
      assert_not_nil new_topic.updated_at
      assert_not_nil new_topic.created_at
    end

    def test_dup_after_initialize_callbacks
      topic = Topic.new
      assert Topic.after_initialize_called
      Topic.after_initialize_called = false
      topic.dup
      assert Topic.after_initialize_called
    end

    def test_dup_validity_is_independent
      repair_validations(Topic) do
        Topic.validates_presence_of :title
        topic = Topic.new("title" => "Literature")
        topic.valid?

        duped = topic.dup
        duped.title = nil
        assert_predicate duped, :invalid?

        topic.title = nil
        duped.title = "Mathematics"
        assert_predicate topic, :invalid?
        assert_predicate duped, :valid?
      end
    end

    def test_dup_with_default_scope
      prev_default_scopes = Topic.default_scopes
      Topic.default_scopes = [proc { Topic.where(approved: true) }]
      topic = Topic.new(approved: false)
      assert_not topic.dup.approved?, "should not be overridden by default scopes"
    ensure
      Topic.default_scopes = prev_default_scopes
    end

    def test_dup_without_primary_key
      skip if current_adapter?(:OracleAdapter)

      klass = Class.new(ActiveRecord::Base) do
        self.table_name = "parrots_pirates"
      end

      record = klass.create!

      assert_nothing_raised do
        record.dup
      end
    end

    def test_dup_record_not_persisted_after_rollback_transaction
      movie = Movie.new(name: "test")

      assert_raises(ActiveRecord::RecordInvalid) do
        Movie.transaction do
          movie.save!
          duped = movie.dup
          duped.name = nil
          duped.save!
        end
      end

      assert_not movie.persisted?
    end
  end
end