kvo 0.0.2 → 0.0.3
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/.gitignore +1 -0
- data/README.md +20 -2
- data/lib/kvo.rb +24 -3
- data/lib/kvo/version.rb +1 -1
- data/spec/kvo_spec.rb +77 -1
- metadata +24 -9
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Description
|
2
2
|
===========
|
3
3
|
|
4
|
-
Key-Value Observing in ruby
|
4
|
+
Key-Value Observing and Binding in ruby
|
5
5
|
|
6
6
|
### Synopsis
|
7
7
|
|
@@ -9,16 +9,34 @@ Fires a [Publisher](http://atomicobject.github.com/publisher/) event whenever th
|
|
9
9
|
|
10
10
|
### How do I use it?
|
11
11
|
|
12
|
+
```ruby
|
13
|
+
# kvo example
|
12
14
|
class Foo
|
13
15
|
include Kvo
|
14
16
|
kvo_attr_accessor :bar, :baz
|
15
17
|
end
|
16
|
-
|
18
|
+
|
17
19
|
f = Foo.new
|
18
20
|
f.when :bar_changed do |oldVal, newVal|
|
19
21
|
puts "bar was changed from #{oldVal} to #{newVal}"
|
20
22
|
end
|
21
23
|
|
24
|
+
|
25
|
+
# kvb example
|
26
|
+
class Baz
|
27
|
+
attr_accessor :bar
|
28
|
+
end
|
29
|
+
|
30
|
+
b = Bar.new
|
31
|
+
# b's bar will be updated whenever f's is
|
32
|
+
f.kvo_bind_attr :bar, b
|
33
|
+
|
34
|
+
# optional transforms
|
35
|
+
f.kvo_bind_attr :bar, b do |val|
|
36
|
+
val + 5
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
22
40
|
Authors
|
23
41
|
=======
|
24
42
|
* Shawn Anderson (shawn.anderson@atomicobject.com)
|
data/lib/kvo.rb
CHANGED
@@ -3,21 +3,42 @@ module Kvo
|
|
3
3
|
module ClassMethods
|
4
4
|
def kvo_attr_accessor(*kvo_symbols)
|
5
5
|
kvo_symbols.each do |kvo|
|
6
|
+
|
7
|
+
raise "the method #{kvo} already exists" if self.instance_methods.include? kvo
|
8
|
+
raise "the method #{kvo}= already exists" if self.instance_methods.include? "#{kvo}=".to_sym
|
9
|
+
|
6
10
|
class_eval <<-METHODS
|
7
11
|
can_fire :#{kvo}_changed unless published_events == :any_event_is_ok
|
8
12
|
def #{kvo}
|
9
13
|
@kvo_#{kvo}
|
10
14
|
end
|
11
|
-
def #{kvo}=(
|
15
|
+
def #{kvo}=(new_val)
|
12
16
|
old = @kvo_#{kvo}
|
13
|
-
@kvo_#{kvo}=
|
14
|
-
fire :#{kvo}_changed, old,
|
17
|
+
@kvo_#{kvo}=new_val
|
18
|
+
fire :#{kvo}_changed, old, new_val
|
15
19
|
end
|
16
20
|
METHODS
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
25
|
+
def kvo_bind_attr(attr_sym, target, opts={})
|
26
|
+
target_attr = opts[:to] || attr_sym
|
27
|
+
change_event = "#{attr_sym}_changed".to_sym
|
28
|
+
|
29
|
+
unless self.class.published_events.include? change_event
|
30
|
+
raise "#{attr_sym} is not a kvo attr; use #{self.class}.kvo_attr_accessor #{attr_sym}"
|
31
|
+
end
|
32
|
+
|
33
|
+
self.when change_event do |old, new_val|
|
34
|
+
val = new_val
|
35
|
+
# transform
|
36
|
+
val = yield(new_val) if block_given?
|
37
|
+
|
38
|
+
target.send "#{target_attr}=", val
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
21
42
|
def self.included(receiver)
|
22
43
|
receiver.extend Publisher
|
23
44
|
receiver.extend ClassMethods
|
data/lib/kvo/version.rb
CHANGED
data/spec/kvo_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__),'helper')
|
2
2
|
|
3
|
-
describe '
|
3
|
+
describe '.kvo_attr_accessor' do
|
4
4
|
before do
|
5
5
|
@target = Foo.new
|
6
6
|
@target.bar = :old
|
@@ -32,6 +32,21 @@ describe 'kvo' do
|
|
32
32
|
@target.instance_variable_get("@bar").should be_nil
|
33
33
|
end
|
34
34
|
|
35
|
+
it 'can call back a block of arity 0' do
|
36
|
+
@baz_fired = nil
|
37
|
+
@target.when :baz_changed do @baz_fired = true end
|
38
|
+
@target.baz = :something
|
39
|
+
@baz_fired.should be
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'raises an error if attr setter is already defined' do
|
43
|
+
lambda{ ThingOne.kvo_attr_accessor :one }.should raise_exception(RuntimeError, /one= already exists/)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'raises an error if attr getter is already defined' do
|
47
|
+
lambda{ ThingTwo.kvo_attr_accessor :two }.should raise_exception(RuntimeError, /two already exists/)
|
48
|
+
end
|
49
|
+
|
35
50
|
describe "inheritance" do
|
36
51
|
before do
|
37
52
|
@target = SubFoo.new
|
@@ -66,6 +81,44 @@ describe 'kvo' do
|
|
66
81
|
end
|
67
82
|
end
|
68
83
|
|
84
|
+
describe '#kvo_bind_attr' do
|
85
|
+
let(:peter_pan) {
|
86
|
+
peter = PeterPan.new
|
87
|
+
peter.location = "OVER THERE"
|
88
|
+
peter.flying = false
|
89
|
+
peter
|
90
|
+
}
|
91
|
+
let(:shadow) { Shadow.new }
|
92
|
+
|
93
|
+
it 'modifies attr when bound objects attr changes' do
|
94
|
+
peter_pan.kvo_bind_attr :location, shadow
|
95
|
+
peter_pan.location = "NEVERLAND"
|
96
|
+
|
97
|
+
shadow.location.should == "NEVERLAND"
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'can use a different method name on target' do
|
101
|
+
peter_pan.kvo_bind_attr :location, shadow, to: :place
|
102
|
+
|
103
|
+
peter_pan.location = "NEVERLAND"
|
104
|
+
|
105
|
+
shadow.location.should be_nil
|
106
|
+
shadow.place.should == "NEVERLAND"
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'can transform new value with a block' do
|
110
|
+
peter_pan.kvo_bind_attr :location, shadow do |new_value|
|
111
|
+
new_value.downcase
|
112
|
+
end
|
113
|
+
peter_pan.location = "NEVERLAND"
|
114
|
+
shadow.location.should == "neverland"
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'can bind to non-kvo attrs (by making them kvo)' do
|
118
|
+
lambda{ peter_pan.kvo_bind_attr :flying, shadow}.should raise_exception(RuntimeError, /flying is not a kvo attr/)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
69
122
|
class Foo
|
70
123
|
include Kvo
|
71
124
|
kvo_attr_accessor :bar, :baz
|
@@ -74,3 +127,26 @@ end
|
|
74
127
|
class SubFoo < Foo
|
75
128
|
kvo_attr_accessor :qux
|
76
129
|
end
|
130
|
+
|
131
|
+
class PeterPan
|
132
|
+
include Kvo
|
133
|
+
kvo_attr_accessor :location
|
134
|
+
attr_accessor :flying
|
135
|
+
end
|
136
|
+
|
137
|
+
class Shadow
|
138
|
+
attr_accessor :location, :place, :flying
|
139
|
+
end
|
140
|
+
|
141
|
+
class ThingOne
|
142
|
+
include Kvo
|
143
|
+
attr_writer :one
|
144
|
+
end
|
145
|
+
|
146
|
+
class ThingTwo
|
147
|
+
include Kvo
|
148
|
+
attr_reader :two
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kvo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: publisher
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rspec
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: '0'
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: mocha
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,7 +53,12 @@ dependencies:
|
|
43
53
|
version: '0'
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
47
62
|
description: KVO in ruby.
|
48
63
|
email:
|
49
64
|
- shawn42@gmail.com
|
@@ -80,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
95
|
version: '0'
|
81
96
|
requirements: []
|
82
97
|
rubyforge_project: kvo
|
83
|
-
rubygems_version: 1.8.
|
98
|
+
rubygems_version: 1.8.24
|
84
99
|
signing_key:
|
85
100
|
specification_version: 3
|
86
101
|
summary: KVO in ruby
|