Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 23 additions & 25 deletions lib/disposable/twin/changed.rb
Original file line number Diff line number Diff line change
@@ -1,41 +1,32 @@
module Disposable::Twin::Changed
class Changes < Hash
def changed?(name=nil)
return true if name.nil? and values.find { |val| val == true } # TODO: this could be speed-improved, of course.
def changes(name=nil)
_find_changed_twins!(_changes)

!! self[name.to_s]
end
end


def changed?(*args) # not recommended for external use?
changed.changed?(*args)
return _changes unless name
_changes[name.to_s]
end

# FIXME: can we make #changed the only public concept? so we don't need to find twice?
def changed?(name=nil)
_find_changed_twins!(_changes)

# this is usually called only once in Sync::SkipUnchanged, per twin.
def changed
_find_changed_twins!(@_changes)

@_changes
(name.nil? && _changes.values.any?) || _changes.has_key?(name.to_s)
end

private
def initialize(model, *args)
super # Setup#initialize.
@_changes = Changes.new # override changed from initialize.
end

def _changed
@_changes ||= Changes.new # FIXME: why do we need to re-initialize here?
attr_reader :_changes
def initialize(model, *args)
super # Setup#initialize.
@_changes = {} # override changed from initialize.
end

def write_property(name, value, dfn)
old_value = field_read(name)
return if old_value == value

super.tap do
_changed[name.to_s] = old_value != value
@_changes ||= {}
_changes[name.to_s] = [old_value, value]
end
end

Expand All @@ -44,7 +35,14 @@ def _find_changed_twins!(changes) # FIXME: this will change soon. don't touch.
next unless twin = send(dfn.getter)
next unless twin.changed?

changes[dfn[:name]] = true
if twin.is_a?(Disposable::Twin::Collection)
changes[dfn[:name]] = []
twin.each do |item|
changes[dfn[:name]] << item.changes
end
else
changes[dfn[:name]] = twin.changes
end
end
end
end
end
36 changes: 36 additions & 0 deletions test/twin/changed_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,53 @@ class Album < Disposable::Twin
twin.artist.name = "No Fun At All"

expect(twin.changed?(:name)).must_equal true
expect(twin.changes(:name)).must_equal ["The Rest Is Silence", "Out Of Bounds"]
expect(twin.changes).must_equal({
"name" => ["The Rest Is Silence", "Out Of Bounds"],
"artist" => { "name" => ["Randy", "No Fun At All"] },
"songs" => [
{"title" => ["Broken", "I Have Seen"]},
{
"title" => ["Broken", "In A Rhyme"],
"composer" => {
"name" => [2, "Ingemar Jansson & Mikael Danielsson"]
}
}
]
})
expect(twin.changed?).must_equal true

expect(twin.songs[0].changed?).must_equal true
expect(twin.songs[0].changed?(:title)).must_equal true
expect(twin.songs[0].changes(:title)).must_equal ["Broken", "I Have Seen"]
expect(twin.songs[0].changes).must_equal({
"title" => ["Broken", "I Have Seen"]
})

expect(twin.songs[1].changed?).must_equal true
expect(twin.songs[1].changed?(:title)).must_equal true
expect(twin.songs[1].changes(:title)).must_equal ["Broken", "In A Rhyme"]
expect(twin.songs[1].changes).must_equal({
"title" => ["Broken", "In A Rhyme"],
"composer" => {
"name" => [2, "Ingemar Jansson & Mikael Danielsson"]
}
})

expect(twin.songs[1].composer.changed?(:name)).must_equal true
expect(twin.songs[1].composer.changes(:name)).must_equal(
[2, "Ingemar Jansson & Mikael Danielsson"]
)
expect(twin.songs[1].composer.changes).must_equal({
"name" => [2, "Ingemar Jansson & Mikael Danielsson"]
})
expect(twin.songs[1].composer.changed?).must_equal true

expect(twin.artist.changed?(:name)).must_equal true
expect(twin.artist.changes(:name)).must_equal ["Randy", "No Fun At All"]
expect(twin.artist.changes).must_equal({
"name" => ["Randy", "No Fun At All"]
})
expect(twin.artist.changed?).must_equal true

# you can also ask for nested twins by name.
Expand Down
2 changes: 1 addition & 1 deletion test/twin/struct_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Song < Disposable::Twin
it { expect(Song.new({number: 3}, {cool?: true}).number).must_equal 3 }

# with string key and false value
it { Song.new('number' => 3, 'cool?' => false).cool?.must_equal false }
it { expect(Song.new('number' => 3, 'cool?' => false).cool?).must_equal false }


describe "writing" do
Expand Down
Loading