Skip to content

Commit

Permalink
Make serialization_modification_detection plugin work correctly with …
Browse files Browse the repository at this point in the history
…new objects and after saving existing objects (Fixes jeremyevans#432)

Previously, the plugin only really worked correctly on existing objects
loaded from the database before saving.  That's generally the main use
case, but other cases should be handled as well.  Unfortunately, to
handle the other cases, on new object creation and after saving, you
need to serialize and deserialize all of the deserialized columns to
get clean copies.
  • Loading branch information
jeremyevans committed Feb 1, 2012
1 parent 9bb7ef8 commit e16f1d3
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
=== HEAD

* Make serialization_modification_detection plugin work correctly with new objects and after saving existing objects (jeremyevans) (#432)

* Make refreshes after model creation clear the deserialized values in the serialization plugin (jeremyevans)

* Add Dataset#update_ignore on MySQL, for using UPDATE IGNORE in queries (danielb2) (#429)
Expand Down
20 changes: 16 additions & 4 deletions lib/sequel/plugins/serialization_modification_detection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ def self.apply(model)
end

module InstanceMethods
# Clear the cache of original deserialized values after saving so that it doesn't
# show the column is modified after saving.
def after_save
super
copy_deserialized_values
end

# Detect which serialized columns have changed.
def changed_columns
cc = super
Expand All @@ -34,11 +41,16 @@ def changed_columns

private

# Clear the cache of original deserialized values after saving so that it doesn't
# show the column is modified after saving.
def after_save
# For new objects, populate the original deserialized value so that we know it hasn't
# changed since initialization.
def initialize_set(values)
super
@original_deserialized_values.clear if @original_deserialized_values
copy_deserialized_values
end

def copy_deserialized_values
@original_deserialized_values = h = {}
@deserialized_values.each{|k, v| h[k] = deserialize_value(k, serialize_value(k, v))}
end

# Return the original deserialized value of the column, caching it to improve performance.
Expand Down
37 changes: 36 additions & 1 deletion spec/extensions/serialization_modification_detection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,20 @@
plugin :serialization, :yaml, :h
plugin :serialization_modification_detection
end
@o1 = @c.new
@o1 = @c.new(:h=>{})
@o2 = @c.load(:id=>1, :h=>"--- {}\n\n")
@o3 = @c.new
@o4 = @c.load(:id=>1, :h=>nil)
MODEL_DB.reset
end

it "should not detect columns that haven't been changed" do
@o1.changed_columns.should == []
@o1.h.should == {}
@o1.h[1] = 2
@o1.h.clear
@o1.changed_columns.should == []

@o2.changed_columns.should == []
@o2.h.should == {}
@o2.h[1] = 2
Expand All @@ -23,15 +31,42 @@
end

it "should detect columns that have been changed" do
@o1.changed_columns.should == []
@o1.h.should == {}
@o1.h[1] = 2
@o1.changed_columns.should == [:h]

@o2.changed_columns.should == []
@o2.h.should == {}
@o2.h[1] = 2
@o2.changed_columns.should == [:h]

@o3.changed_columns.should == []
@o3.h.should == nil
@o3.h = {}
@o3.changed_columns.should == [:h]

@o4.changed_columns.should == []
@o4.h.should == nil
@o4.h = {}
@o4.changed_columns.should == [:h]
end

it "should report correct changed_columns after saving" do
@o1.h[1] = 2
@o1.save
@o1.changed_columns.should == []

@o2.h[1] = 2
@o2.save_changes
@o2.changed_columns.should == []

@o3.h = {1=>2}
@o3.save
@o3.changed_columns.should == []

@o4.h = {1=>2}
@o4.save
@o4.changed_columns.should == []
end
end

0 comments on commit e16f1d3

Please sign in to comment.