observables 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -20
- data/README.rdoc +117 -117
- data/lib/observables.rb +14 -14
- data/lib/observables/array_watcher.rb +50 -50
- data/lib/observables/base.rb +97 -94
- data/lib/observables/collections.rb +14 -14
- data/lib/observables/extensions/array.rb +4 -4
- data/lib/observables/extensions/hash.rb +4 -4
- data/lib/observables/extensions/object.rb +9 -9
- data/lib/observables/hash_watcher.rb +39 -39
- data/lib/observables/version.rb +4 -4
- data/test/extensions/test_extensions.rb +20 -20
- data/test/{test_observables.rb → test_Observables.rb} +9 -9
- data/test/test_array_watcher.rb +136 -136
- data/test/test_base.rb +126 -126
- data/test/test_hash_watcher.rb +88 -88
- data/test/test_helper.rb +13 -13
- data/test/test_observable_array.rb +12 -12
- metadata +41 -28
@@ -1,15 +1,15 @@
|
|
1
|
-
module Observables
|
2
|
-
class Array < ::Array
|
3
|
-
include ArrayWatcher
|
4
|
-
def initialize(*args)
|
5
|
-
super(*args)
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
class Hash < ::Hash
|
10
|
-
include HashWatcher
|
11
|
-
def initialize(*args)
|
12
|
-
super(*args)
|
13
|
-
end
|
14
|
-
end
|
1
|
+
module Observables
|
2
|
+
class Array < ::Array
|
3
|
+
include ArrayWatcher
|
4
|
+
def initialize(*args)
|
5
|
+
super(*args)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Hash < ::Hash
|
10
|
+
include HashWatcher
|
11
|
+
def initialize(*args)
|
12
|
+
super(*args)
|
13
|
+
end
|
14
|
+
end
|
15
15
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
class ::Array
|
2
|
-
def make_observable
|
3
|
-
class << self; include Observables::ArrayWatcher; end unless observable?
|
4
|
-
end
|
1
|
+
class ::Array
|
2
|
+
def make_observable
|
3
|
+
class << self; include Observables::ArrayWatcher; end unless observable?
|
4
|
+
end
|
5
5
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
class ::Hash
|
2
|
-
def make_observable
|
3
|
-
class << self; include Observables::HashWatcher; end unless observable?
|
4
|
-
end
|
1
|
+
class ::Hash
|
2
|
+
def make_observable
|
3
|
+
class << self; include Observables::HashWatcher; end unless observable?
|
4
|
+
end
|
5
5
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
class ::Object
|
2
|
-
def can_be_observable?
|
3
|
-
respond_to?(:make_observable)
|
4
|
-
end
|
5
|
-
|
6
|
-
def observable?
|
7
|
-
kind_of?(Observables::Base)
|
8
|
-
end
|
9
|
-
|
1
|
+
class ::Object
|
2
|
+
def can_be_observable?
|
3
|
+
respond_to?(:make_observable)
|
4
|
+
end
|
5
|
+
|
6
|
+
def observable?
|
7
|
+
kind_of?(Observables::Base)
|
8
|
+
end
|
9
|
+
|
10
10
|
end
|
@@ -1,40 +1,40 @@
|
|
1
|
-
module Observables
|
2
|
-
module HashWatcher
|
3
|
-
include Observables::Base
|
4
|
-
|
5
|
-
MODIFIER_METHODS = :replace, :merge!, :update
|
6
|
-
REMOVE_METHODS = :clear, :delete, :delete_if, :reject!, :shift
|
7
|
-
|
8
|
-
#[]= can either be an add method or a modifier method depending on
|
9
|
-
#if the previous key exists
|
10
|
-
def []=(key,val)
|
11
|
-
change_type = keys.include?(key) ? :modified : :added
|
12
|
-
changes = changes_for(change_type,:[]=,key,val)
|
13
|
-
changing(change_type,:trigger=>:[]=, :changes=>changes) {super}
|
14
|
-
end
|
15
|
-
alias :store :[]=
|
16
|
-
|
17
|
-
override_mutators :modified=>MODIFIER_METHODS,
|
18
|
-
:removed=>REMOVE_METHODS
|
19
|
-
|
20
|
-
def changes_for(change_type, trigger_method, *args, &block)
|
21
|
-
prev = self.dup
|
22
|
-
if change_type == :added
|
23
|
-
lambda {{:added=>[args]}}
|
24
|
-
elsif change_type == :removed
|
25
|
-
case trigger_method
|
26
|
-
when :clear then lambda{{:removed=>prev.to_a}}
|
27
|
-
when :delete then lambda{{:removed=>[[args[0],prev[args[0]]]]}}
|
28
|
-
when :delete_if, :reject! then lambda{{:removed=>prev.select(&block)}}
|
29
|
-
when :shift then lambda { {:removed=>[prev.keys[0],prev.values[0]]}}
|
30
|
-
end
|
31
|
-
else
|
32
|
-
case trigger_method
|
33
|
-
when :[]= then lambda{{:removed=>[[args[0],prev[args[0]]]],:added=>[args]}}
|
34
|
-
when :replace then lambda{{:removed=>prev.to_a, :added=>args[0].to_a}}
|
35
|
-
when :merge!, :update then lambda{{:removed=>prev.select{|k,_|args[0].keys.include?(k)},:added=>args[0].to_a}}
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
1
|
+
module Observables
|
2
|
+
module HashWatcher
|
3
|
+
include Observables::Base
|
4
|
+
|
5
|
+
MODIFIER_METHODS = :replace, :merge!, :update
|
6
|
+
REMOVE_METHODS = :clear, :delete, :delete_if, :reject!, :shift
|
7
|
+
|
8
|
+
#[]= can either be an add method or a modifier method depending on
|
9
|
+
#if the previous key exists
|
10
|
+
def []=(key,val)
|
11
|
+
change_type = keys.include?(key) ? :modified : :added
|
12
|
+
changes = changes_for(change_type,:[]=,key,val)
|
13
|
+
changing(change_type,:trigger=>:[]=, :changes=>changes) {super}
|
14
|
+
end
|
15
|
+
alias :store :[]=
|
16
|
+
|
17
|
+
override_mutators :modified=>MODIFIER_METHODS,
|
18
|
+
:removed=>REMOVE_METHODS
|
19
|
+
|
20
|
+
def changes_for(change_type, trigger_method, *args, &block)
|
21
|
+
prev = self.dup
|
22
|
+
if change_type == :added
|
23
|
+
lambda {{:added=>[args]}}
|
24
|
+
elsif change_type == :removed
|
25
|
+
case trigger_method
|
26
|
+
when :clear then lambda{{:removed=>prev.to_a}}
|
27
|
+
when :delete then lambda{{:removed=>[[args[0],prev[args[0]]]]}}
|
28
|
+
when :delete_if, :reject! then lambda{{:removed=>prev.select(&block)}}
|
29
|
+
when :shift then lambda { {:removed=>[prev.keys[0],prev.values[0]]}}
|
30
|
+
end
|
31
|
+
else
|
32
|
+
case trigger_method
|
33
|
+
when :[]= then lambda{{:removed=>[[args[0],prev[args[0]]]],:added=>[args]}}
|
34
|
+
when :replace then lambda{{:removed=>prev.to_a, :added=>args[0].to_a}}
|
35
|
+
when :merge!, :update then lambda{{:removed=>prev.select{|k,_|args[0].keys.include?(k)},:added=>args[0].to_a}}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
40
|
end
|
data/lib/observables/version.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
module Observables
|
3
|
-
Version = '0.1.
|
4
|
-
end
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Observables
|
3
|
+
Version = '0.1.2'
|
4
|
+
end
|
@@ -1,21 +1,21 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class TestExtensions < Test::Unit::TestCase
|
4
|
-
context "Array" do
|
5
|
-
context "#make_observable" do
|
6
|
-
|
7
|
-
should "detect an observable array" do
|
8
|
-
x, y = [], [].tap{|a|a.make_observable}
|
9
|
-
assert_equal false, x.observable?
|
10
|
-
assert y.observable?
|
11
|
-
end
|
12
|
-
|
13
|
-
should "make an instance of an array observable" do
|
14
|
-
x = []
|
15
|
-
assert_equal false, x.observable?
|
16
|
-
x.make_observable
|
17
|
-
assert x.observable?
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TestExtensions < Test::Unit::TestCase
|
4
|
+
context "Array" do
|
5
|
+
context "#make_observable" do
|
6
|
+
|
7
|
+
should "detect an observable array" do
|
8
|
+
x, y = [], [].tap{|a|a.make_observable}
|
9
|
+
assert_equal false, x.observable?
|
10
|
+
assert y.observable?
|
11
|
+
end
|
12
|
+
|
13
|
+
should "make an instance of an array observable" do
|
14
|
+
x = []
|
15
|
+
assert_equal false, x.observable?
|
16
|
+
x.make_observable
|
17
|
+
assert x.observable?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
21
|
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class TestObservables < Test::Unit::TestCase
|
4
|
-
context "including observables" do
|
5
|
-
should "include something or other" do
|
6
|
-
assert_equal defined?(Observables), "constant"
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestObservables < Test::Unit::TestCase
|
4
|
+
context "including observables" do
|
5
|
+
should "include something or other" do
|
6
|
+
assert_equal defined?(Observables), "constant"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
data/test/test_array_watcher.rb
CHANGED
@@ -1,137 +1,137 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class TestArrayWatcher < Test::Unit::TestCase
|
4
|
-
context "An array which has included Observables::ArrayWatcher" do
|
5
|
-
setup do
|
6
|
-
@ary = Array.new([1,2,3]).tap do |a|
|
7
|
-
a.make_observable
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
should "notify observers of any change that adds elements to itself" do
|
12
|
-
before_methods, after_methods = [],[]
|
13
|
-
method_list = Observables::ArrayWatcher::ADD_METHODS
|
14
|
-
@ary.subscribe(/before_added/){|_,args|before_methods<<args[:trigger]}
|
15
|
-
@ary.subscribe(/after_added/) {|_,args|after_methods<<args[:trigger]}
|
16
|
-
method_list.each do |method|
|
17
|
-
@ary.send(method,*args_for(method))
|
18
|
-
end
|
19
|
-
|
20
|
-
assert_equal method_list, before_methods
|
21
|
-
assert_equal method_list, after_methods
|
22
|
-
end
|
23
|
-
|
24
|
-
should "notify observers of any change that modifies elements" do
|
25
|
-
before_methods, after_methods = [],[]
|
26
|
-
method_list = Observables::ArrayWatcher::MODIFIER_METHODS
|
27
|
-
@ary.subscribe(/before_modified/){|_,args|before_methods<<args[:trigger]}
|
28
|
-
@ary.subscribe(/after_modified/) {|_,args|after_methods<<args[:trigger]}
|
29
|
-
method_list.each do |method|
|
30
|
-
args = args_for(method)
|
31
|
-
args ? @ary.send(method,*args) : @ary.send(method)
|
32
|
-
end
|
33
|
-
assert_equal method_list, before_methods
|
34
|
-
assert_equal method_list, after_methods
|
35
|
-
end
|
36
|
-
|
37
|
-
should "notify observers of any change that removes elements" do
|
38
|
-
before_methods, after_methods = [],[]
|
39
|
-
method_list = Observables::ArrayWatcher::REMOVE_METHODS
|
40
|
-
@ary.subscribe(/before_removed/){|_,args|before_methods<<args[:trigger]}
|
41
|
-
@ary.subscribe(/after_removed/) {|_,args|after_methods<<args[:trigger]}
|
42
|
-
method_list.each do |method|
|
43
|
-
args = args_for(method)
|
44
|
-
args ? @ary.send(method,*args) : @ary.send(method)
|
45
|
-
end
|
46
|
-
assert_equal method_list, before_methods
|
47
|
-
assert_equal method_list, after_methods
|
48
|
-
end
|
49
|
-
|
50
|
-
context "Calling #changes on the event args" do
|
51
|
-
should "calculate changes for #<<" do
|
52
|
-
assert_equal [9],get_changes(@ary){ @ary << 9}[:added]
|
53
|
-
end
|
54
|
-
should "calculate changes for #push, #unshift" do
|
55
|
-
[:push,:unshift].each do|method|
|
56
|
-
ary = @ary.dup
|
57
|
-
assert_equal [1,2,3],get_changes(ary){ary.send(method,1,2,3)}[:added]
|
58
|
-
end
|
59
|
-
end
|
60
|
-
should "calculate changes for #concat" do
|
61
|
-
assert_equal [1,2,3],get_changes(@ary){@ary.concat([1,2,3])}[:added]
|
62
|
-
end
|
63
|
-
should "calculate changes for insert" do
|
64
|
-
assert_equal [3,4,5],get_changes(@ary){@ary.insert(2,3,4,5)}[:added]
|
65
|
-
end
|
66
|
-
should "calculate changes for delete" do
|
67
|
-
assert_equal [2],get_changes(@ary){@ary.delete(2)}[:removed]
|
68
|
-
end
|
69
|
-
should "calculate changes for delete_at" do
|
70
|
-
assert_equal [2],get_changes(@ary){@ary.delete_at(1)}[:removed]
|
71
|
-
end
|
72
|
-
should "calculate changes for delete_if, reject!" do
|
73
|
-
[:delete_if, :reject!].each do |method|
|
74
|
-
ary = @ary.dup
|
75
|
-
assert_equal [2], get_changes(ary){ary.send(method){|i|i%2==0}}[:removed]
|
76
|
-
end
|
77
|
-
end
|
78
|
-
should "calculate changes for pop" do
|
79
|
-
assert_equal [3], get_changes(@ary){@ary.pop}[:removed]
|
80
|
-
end
|
81
|
-
should "calculate changes for shift" do
|
82
|
-
assert_equal [1], get_changes(@ary){@ary.shift}[:removed]
|
83
|
-
end
|
84
|
-
should "calculate changes for clear" do
|
85
|
-
assert_equal [1,2,3], get_changes(@ary){@ary.clear}[:removed]
|
86
|
-
end
|
87
|
-
should "calculate changes for compact!" do
|
88
|
-
@ary = [1,2,nil,3,nil,4].tap{|a|a.make_observable}
|
89
|
-
assert_equal [nil], get_changes(@ary){@ary.compact!}[:removed]
|
90
|
-
end
|
91
|
-
should "calculate changes for slice!" do
|
92
|
-
assert_equal [2,3], get_changes(@ary){@ary.slice!(1,2)}[:removed]
|
93
|
-
end
|
94
|
-
should "calculate changes for uniq!" do
|
95
|
-
@ary = [1,2,2,3,3,4,4,5].tap{|a|a.make_observable}
|
96
|
-
assert_equal [], get_changes(@ary){@ary.uniq!}[:removed]
|
97
|
-
end
|
98
|
-
should "calculate changes for replace" do
|
99
|
-
assert_equal({:removed=>@ary.dup,:added=>[4,5,6,7]}, get_changes(@ary){@ary.replace([4,5,6,7])})
|
100
|
-
end
|
101
|
-
should "calculate changes for []=" do
|
102
|
-
assert_equal [6,7,8,9], get_changes(@ary){@ary[3,4]=[6,7,8,9]}[:added]
|
103
|
-
end
|
104
|
-
should "calculated changes for []= when []= is a modification method" do
|
105
|
-
assert_equal({:removed=>[1],:added=>[9]},get_changes(@ary){@ary[0]=9})
|
106
|
-
end
|
107
|
-
should "return the original array as changes for other modification methods of array" do
|
108
|
-
[:collect!, :map!, :flatten!, :reverse!, :sort!].each do |method|
|
109
|
-
ary = @ary.dup
|
110
|
-
assert_equal({:removed=>ary.dup, :added=>ary.dup.tap{|a|a.send(method)}}, get_changes(ary){ary.send(method)})
|
111
|
-
end
|
112
|
-
end
|
113
|
-
should "return the original array as changes for fill" do
|
114
|
-
assert_equal({:removed=>@ary.dup, :added=>@ary.dup.fill("*")}, get_changes(@ary){@ary.fill("*")})
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def args_for(method)
|
120
|
-
case method
|
121
|
-
when :<<, :push, :unshift, :delete, :delete_at then [1]
|
122
|
-
when :concat, :replace then [[1,2]]
|
123
|
-
when :fill then ["*"]
|
124
|
-
when :insert, :"[]=", :slice! then [1,1]
|
125
|
-
when :flatten!, :collect!, :map!, :reverse!, :sort!,
|
126
|
-
:clear, :compact!, :pop, :reject!, :uniq!, :delete_if, :shift then nil
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def get_changes(ary)
|
131
|
-
changes = []
|
132
|
-
sub = ary.subscribe(/after/){|_,args|changes << args.changes}
|
133
|
-
yield
|
134
|
-
ary.unsubscribe(sub)
|
135
|
-
changes.pop
|
136
|
-
end
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TestArrayWatcher < Test::Unit::TestCase
|
4
|
+
context "An array which has included Observables::ArrayWatcher" do
|
5
|
+
setup do
|
6
|
+
@ary = Array.new([1,2,3]).tap do |a|
|
7
|
+
a.make_observable
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
should "notify observers of any change that adds elements to itself" do
|
12
|
+
before_methods, after_methods = [],[]
|
13
|
+
method_list = Observables::ArrayWatcher::ADD_METHODS
|
14
|
+
@ary.subscribe(/before_added/){|_,args|before_methods<<args[:trigger]}
|
15
|
+
@ary.subscribe(/after_added/) {|_,args|after_methods<<args[:trigger]}
|
16
|
+
method_list.each do |method|
|
17
|
+
@ary.send(method,*args_for(method))
|
18
|
+
end
|
19
|
+
|
20
|
+
assert_equal method_list, before_methods
|
21
|
+
assert_equal method_list, after_methods
|
22
|
+
end
|
23
|
+
|
24
|
+
should "notify observers of any change that modifies elements" do
|
25
|
+
before_methods, after_methods = [],[]
|
26
|
+
method_list = Observables::ArrayWatcher::MODIFIER_METHODS
|
27
|
+
@ary.subscribe(/before_modified/){|_,args|before_methods<<args[:trigger]}
|
28
|
+
@ary.subscribe(/after_modified/) {|_,args|after_methods<<args[:trigger]}
|
29
|
+
method_list.each do |method|
|
30
|
+
args = args_for(method)
|
31
|
+
args ? @ary.send(method,*args) : @ary.send(method)
|
32
|
+
end
|
33
|
+
assert_equal method_list, before_methods
|
34
|
+
assert_equal method_list, after_methods
|
35
|
+
end
|
36
|
+
|
37
|
+
should "notify observers of any change that removes elements" do
|
38
|
+
before_methods, after_methods = [],[]
|
39
|
+
method_list = Observables::ArrayWatcher::REMOVE_METHODS
|
40
|
+
@ary.subscribe(/before_removed/){|_,args|before_methods<<args[:trigger]}
|
41
|
+
@ary.subscribe(/after_removed/) {|_,args|after_methods<<args[:trigger]}
|
42
|
+
method_list.each do |method|
|
43
|
+
args = args_for(method)
|
44
|
+
args ? @ary.send(method,*args) : @ary.send(method)
|
45
|
+
end
|
46
|
+
assert_equal method_list, before_methods
|
47
|
+
assert_equal method_list, after_methods
|
48
|
+
end
|
49
|
+
|
50
|
+
context "Calling #changes on the event args" do
|
51
|
+
should "calculate changes for #<<" do
|
52
|
+
assert_equal [9],get_changes(@ary){ @ary << 9}[:added]
|
53
|
+
end
|
54
|
+
should "calculate changes for #push, #unshift" do
|
55
|
+
[:push,:unshift].each do|method|
|
56
|
+
ary = @ary.dup
|
57
|
+
assert_equal [1,2,3],get_changes(ary){ary.send(method,1,2,3)}[:added]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
should "calculate changes for #concat" do
|
61
|
+
assert_equal [1,2,3],get_changes(@ary){@ary.concat([1,2,3])}[:added]
|
62
|
+
end
|
63
|
+
should "calculate changes for insert" do
|
64
|
+
assert_equal [3,4,5],get_changes(@ary){@ary.insert(2,3,4,5)}[:added]
|
65
|
+
end
|
66
|
+
should "calculate changes for delete" do
|
67
|
+
assert_equal [2],get_changes(@ary){@ary.delete(2)}[:removed]
|
68
|
+
end
|
69
|
+
should "calculate changes for delete_at" do
|
70
|
+
assert_equal [2],get_changes(@ary){@ary.delete_at(1)}[:removed]
|
71
|
+
end
|
72
|
+
should "calculate changes for delete_if, reject!" do
|
73
|
+
[:delete_if, :reject!].each do |method|
|
74
|
+
ary = @ary.dup
|
75
|
+
assert_equal [2], get_changes(ary){ary.send(method){|i|i%2==0}}[:removed]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
should "calculate changes for pop" do
|
79
|
+
assert_equal [3], get_changes(@ary){@ary.pop}[:removed]
|
80
|
+
end
|
81
|
+
should "calculate changes for shift" do
|
82
|
+
assert_equal [1], get_changes(@ary){@ary.shift}[:removed]
|
83
|
+
end
|
84
|
+
should "calculate changes for clear" do
|
85
|
+
assert_equal [1,2,3], get_changes(@ary){@ary.clear}[:removed]
|
86
|
+
end
|
87
|
+
should "calculate changes for compact!" do
|
88
|
+
@ary = [1,2,nil,3,nil,4].tap{|a|a.make_observable}
|
89
|
+
assert_equal [nil], get_changes(@ary){@ary.compact!}[:removed]
|
90
|
+
end
|
91
|
+
should "calculate changes for slice!" do
|
92
|
+
assert_equal [2,3], get_changes(@ary){@ary.slice!(1,2)}[:removed]
|
93
|
+
end
|
94
|
+
should "calculate changes for uniq!" do
|
95
|
+
@ary = [1,2,2,3,3,4,4,5].tap{|a|a.make_observable}
|
96
|
+
assert_equal [], get_changes(@ary){@ary.uniq!}[:removed]
|
97
|
+
end
|
98
|
+
should "calculate changes for replace" do
|
99
|
+
assert_equal({:removed=>@ary.dup,:added=>[4,5,6,7]}, get_changes(@ary){@ary.replace([4,5,6,7])})
|
100
|
+
end
|
101
|
+
should "calculate changes for []=" do
|
102
|
+
assert_equal [6,7,8,9], get_changes(@ary){@ary[3,4]=[6,7,8,9]}[:added]
|
103
|
+
end
|
104
|
+
should "calculated changes for []= when []= is a modification method" do
|
105
|
+
assert_equal({:removed=>[1],:added=>[9]},get_changes(@ary){@ary[0]=9})
|
106
|
+
end
|
107
|
+
should "return the original array as changes for other modification methods of array" do
|
108
|
+
[:collect!, :map!, :flatten!, :reverse!, :sort!].each do |method|
|
109
|
+
ary = @ary.dup
|
110
|
+
assert_equal({:removed=>ary.dup, :added=>ary.dup.tap{|a|a.send(method)}}, get_changes(ary){ary.send(method)})
|
111
|
+
end
|
112
|
+
end
|
113
|
+
should "return the original array as changes for fill" do
|
114
|
+
assert_equal({:removed=>@ary.dup, :added=>@ary.dup.fill("*")}, get_changes(@ary){@ary.fill("*")})
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def args_for(method)
|
120
|
+
case method
|
121
|
+
when :<<, :push, :unshift, :delete, :delete_at then [1]
|
122
|
+
when :concat, :replace then [[1,2]]
|
123
|
+
when :fill then ["*"]
|
124
|
+
when :insert, :"[]=", :slice! then [1,1]
|
125
|
+
when :flatten!, :collect!, :map!, :reverse!, :sort!,
|
126
|
+
:clear, :compact!, :pop, :reject!, :uniq!, :delete_if, :shift then nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def get_changes(ary)
|
131
|
+
changes = []
|
132
|
+
sub = ary.subscribe(/after/){|_,args|changes << args.changes}
|
133
|
+
yield
|
134
|
+
ary.unsubscribe(sub)
|
135
|
+
changes.pop
|
136
|
+
end
|
137
137
|
end
|