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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
|
require_relative "spec_helper"
describe "Sequel::Plugins::Dirty" do
before do
@db = Sequel.mock(:fetch=>{:initial=>'i'.dup, :initial_changed=>'ic'.dup}, :numrows=>1)
@c = Class.new(Sequel::Model(@db[:c]))
@c.plugin :dirty
@c.columns :initial, :initial_changed, :missing, :missing_changed
end
dirty_plugin_specs = Module.new do
extend Minitest::Spec::DSL
it "initial_value should be the current value if value has not changed" do
@o.initial_value(:initial).must_equal 'i'
@o.initial_value(:missing).must_be_nil
end
it "initial_value should be the intial value if value has changed" do
@o.initial_value(:initial_changed).must_equal 'ic'
@o.initial_value(:missing_changed).must_be_nil
end
it "initial_value should handle case where initial value is reassigned later" do
@o.initial_changed = 'ic'
@o.initial_value(:initial_changed).must_equal 'ic'
@o.missing_changed = nil
@o.initial_value(:missing_changed).must_be_nil
end
it "changed_columns should handle case where initial value is reassigned later" do
@o.changed_columns.must_equal [:initial_changed, :missing_changed]
@o.initial_changed = 'ic'
@o.changed_columns.must_equal [:missing_changed]
@o.missing_changed = nil
@o.changed_columns.must_equal [:missing_changed]
end
it "column_change should give initial and current values if there has been a change made" do
@o.column_change(:initial_changed).must_equal ['ic', 'ic2']
@o.column_change(:missing_changed).must_equal [nil, 'mc2']
end
it "column_change should be nil if no change has been made" do
@o.column_change(:initial).must_be_nil
@o.column_change(:missing).must_be_nil
end
it "column_changed? should return whether the column has changed" do
@o.column_changed?(:initial).must_equal false
@o.column_changed?(:initial_changed).must_equal true
@o.column_changed?(:missing).must_equal false
@o.column_changed?(:missing_changed).must_equal true
end
it "column_changed? should handle case where initial value is reassigned later" do
@o.initial_changed = 'ic'
@o.column_changed?(:initial_changed).must_equal false
@o.missing_changed = nil
@o.column_changed?(:missing_changed).must_equal false
end
it "changed_columns should handle case where initial value is reassigned later" do
@o.changed_columns.must_equal [:initial_changed, :missing_changed]
@o.initial_changed = 'ic'
@o.changed_columns.must_equal [:missing_changed]
@o.missing_changed = nil
@o.changed_columns.must_equal [:missing_changed]
end
it "column_changes should give initial and current values" do
@o.column_changes.must_equal(:initial_changed=>['ic', 'ic2'], :missing_changed=>[nil, 'mc2'])
end
it "reset_column should reset the column to its initial value" do
@o.reset_column(:initial)
@o.initial.must_equal 'i'
@o.reset_column(:initial_changed)
@o.initial_changed.must_equal 'ic'
@o.reset_column(:missing)
@o.missing.must_be_nil
@o.reset_column(:missing_changed)
@o.missing_changed.must_be_nil
end
it "reset_column should remove missing values from the values" do
@o.reset_column(:missing)
@o.values.has_key?(:missing).must_equal false
@o.reset_column(:missing_changed)
@o.values.has_key?(:missing_changed).must_equal false
end
it "refresh should clear the cached initial values" do
@o.refresh
@o.column_changes.must_equal({})
end
it "will_change_column should be used to signal in-place modification to column" do
@o.will_change_column(:initial)
@o.initial << 'b'
@o.column_change(:initial).must_equal ['i', 'ib']
@o.will_change_column(:initial_changed)
@o.initial_changed << 'b'
@o.column_change(:initial_changed).must_equal ['ic', 'ic2b']
@o.will_change_column(:missing)
@o.values[:missing] = 'b'
@o.column_change(:missing).must_equal [nil, 'b']
@o.will_change_column(:missing_changed)
@o.missing_changed << 'b'
@o.column_change(:missing_changed).must_equal [nil, 'mc2b']
end
it "will_change_column should different types of existing objects" do
[nil, true, false, Class.new{undef_method :clone}.new, Class.new{def clone; raise TypeError; end}.new].each do |v|
o = @c.new(:initial=>v)
o.will_change_column(:initial)
o.initial = 'a'
o.column_change(:initial).must_equal [v, 'a']
end
end
it "should work when freezing objects" do
@o.freeze
@o.initial_value(:initial).must_equal 'i'
proc{@o.initial = 'b'}.must_raise
end
it "should have #dup duplicate structures" do
was_new = @o.new?
@o.update(:missing=>'m2')
@o.dup.initial_values.must_equal @o.initial_values
@o.dup.initial_values.wont_be_same_as(@o.initial_values)
@o.dup.instance_variable_get(:@missing_initial_values).must_equal @o.instance_variable_get(:@missing_initial_values)
@o.dup.instance_variable_get(:@missing_initial_values).wont_be_same_as(@o.instance_variable_get(:@missing_initial_values))
if was_new
@o.previous_changes.must_be_nil
@o.dup.previous_changes.must_be_nil
else
@o.dup.previous_changes.must_equal @o.previous_changes
end
@o.dup.previous_changes.wont_be_same_as(@o.previous_changes) if @o.previous_changes
end
end
describe "with new instance" do
before do
@o = @c.new(:initial=>'i'.dup, :initial_changed=>'ic'.dup)
@o.initial_changed = 'ic2'.dup
@o.missing_changed = 'mc2'.dup
end
include dirty_plugin_specs
it "save should clear the cached initial values" do
@o.save
@o.column_changes.must_equal({})
end
it "save_changes should clear the cached initial values" do
@c.dataset = @c.dataset.with_extend do
def supports_insert_select?; true end
def insert_select(*) {:id=>1} end
end
@o.save
@o.column_changes.must_equal({})
end
it "should work with the typecast_on_load plugin" do
@c.instance_variable_set(:@db_schema, :initial=>{:type=>:integer})
@c.plugin :typecast_on_load, :initial
@o = @c.call(:initial=>'1')
@o.column_changes.must_equal({})
@o.save
@o.previous_changes.must_equal({})
end
it "should have column_changes work with the typecast_on_load in after hooks" do
@c.instance_variable_set(:@db_schema, :initial=>{:type=>:integer})
@c.plugin :typecast_on_load, :initial
@o = @c.new
@o.initial = 1
@o.column_changes.must_equal({:initial=>[nil, 1]})
column_changes_in_after_save = nil
@o.define_singleton_method(:after_save) do
column_changes_in_after_save = column_changes
super()
end
@db.fetch = {:initial=>1}
@o.save
column_changes_in_after_save.must_equal({:initial=>[nil, 1]})
@o.initial = 2
@o.column_changes.must_equal({:initial=>[1, 2]})
@o.save
column_changes_in_after_save.must_equal({:initial=>[1, 2]})
@o.previous_changes.must_equal({:initial=>[1, 2]})
end
end
describe "with existing instance" do
before do
@o = @c[1]
@o.initial_changed = 'ic2'.dup
@o.missing_changed = 'mc2'.dup
end
include dirty_plugin_specs
it "previous_changes should be the previous changes after saving" do
@o.save
@o.previous_changes.must_equal(:initial_changed=>['ic', 'ic2'], :missing_changed=>[nil, 'mc2'])
end
it "column_previously_was should show the previous value of the column" do
@o.save
@o.column_previously_was(:initial_changed).must_equal 'ic'
@o.column_previously_was(:missing_changed).must_be_nil
end
it "column_previously_was should be nil if there were no previous changes" do
@o.save
@o.column_previously_was(:initial).must_be_nil
@o.column_previously_was(:missing).must_be_nil
end
it "column_previously_changed? should include whether the column previously changed" do
@o.save
@o.column_previously_changed?(:initial_changed).must_equal true
@o.column_previously_changed?(:missing_changed).must_equal true
@o.column_previously_changed?(:initial).must_equal false
@o.column_previously_changed?(:missing).must_equal false
end
it "column_previously_changed? should accept :from and :to options" do
@o.save
@o.column_previously_changed?(:initial_changed, :from=>'ic').must_equal true
@o.column_previously_changed?(:initial_changed, :from=>'ic2').must_equal false
@o.column_previously_changed?(:missing_changed, :from=>nil).must_equal true
@o.column_previously_changed?(:missing_changed, :from=>'mc2').must_equal false
@o.column_previously_changed?(:initial, :from=>nil).must_equal false
@o.column_previously_changed?(:missing, :from=>nil).must_equal false
@o.column_previously_changed?(:initial_changed, :to=>'ic').must_equal false
@o.column_previously_changed?(:initial_changed, :to=>'ic2').must_equal true
@o.column_previously_changed?(:missing_changed, :to=>nil).must_equal false
@o.column_previously_changed?(:missing_changed, :to=>'mc2').must_equal true
@o.column_previously_changed?(:initial, :to=>nil).must_equal false
@o.column_previously_changed?(:missing, :to=>nil).must_equal false
@o.column_previously_changed?(:initial_changed, :from=>'ic', :to=>'ic2').must_equal true
@o.column_previously_changed?(:initial_changed, :from=>'ic2', :to=>'ic2').must_equal false
@o.column_previously_changed?(:initial_changed, :from=>'ic', :to=>'ic').must_equal false
@o.column_previously_changed?(:initial_changed, :from=>'ic2', :to=>'ic').must_equal false
@o.column_previously_changed?(:missing_changed, :from=>nil, :to=>'mc2').must_equal true
@o.column_previously_changed?(:missing_changed, :from=>'mc2', :to=>'mc2').must_equal false
@o.column_previously_changed?(:missing_changed, :from=>'mc', :to=>'mc').must_equal false
@o.column_previously_changed?(:missing_changed, :from=>'mc2', :to=>nil).must_equal false
@o.column_previously_changed?(:initial, :from=>'', :to=>'').must_equal false
@o.column_previously_changed?(:missing, :from=>'', :to=>'').must_equal false
end
it "should work when freezing objects after saving" do
@o.initial = 'a'
@o.save
@o.freeze
@o.previous_changes[:initial].must_equal ['i', 'a']
proc{@o.initial = 'b'}.must_raise
end
end
end
|