motion_bindable 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f463cb26ed789a3715bf0d6527bd87356dc7112f
4
- data.tar.gz: 97b54d01d66b4f65fc5debbda78e2ecfbe9d430f
3
+ metadata.gz: 22f69831469c0aae59f8af6aa599f586276bd23c
4
+ data.tar.gz: 61181ef1e9254eb8378bc229eacc396851480867
5
5
  SHA512:
6
- metadata.gz: 157772a475b474b87df0e0060f6ead78d9f98b3e13f53c457ffaf9c1cd7e8725d6be891dc196aa37d606b14a89f64922b28b729534863fe16f9dd6ec45911a7f
7
- data.tar.gz: 27f4376256b12d9ef4e2d6be2266c5bf4e2f426a210ec53a9e5ce81bd6371c06bbbb464e52cfffab285f98c6cde0797791bc97565e71659265135f89216d0e3f
6
+ metadata.gz: 9581949f1fe049307b10aeb65e26ac65976662c1e5ad51e18c741ebe46340774c5d6296ac41a417ee17a7f2ef1bb957c5075eb590c586b674b1978957aac5283
7
+ data.tar.gz: 1f28ee9528235b42e9e4282e116e5fa54a279fad178f32977a6e34ffec35e4c78ff590faff1a763d9532170c4fc04ac483190d438abb0fbd35a46c5a51dba772
data/Gemfile CHANGED
@@ -4,3 +4,4 @@ gem 'rake'
4
4
  # Add your dependencies here:
5
5
  gem 'webstub'
6
6
  gem 'motion-stump'
7
+ gem 'bubble-wrap', '~> 1.4.0'
data/Gemfile.lock CHANGED
@@ -1,6 +1,7 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
+ bubble-wrap (1.4.0)
4
5
  motion-stump (0.3.0)
5
6
  rake (10.1.0)
6
7
  webstub (1.0.1)
@@ -9,6 +10,7 @@ PLATFORMS
9
10
  ruby
10
11
 
11
12
  DEPENDENCIES
13
+ bubble-wrap (~> 1.4.0)
12
14
  motion-stump
13
15
  rake
14
16
  webstub
@@ -15,7 +15,9 @@ module MotionBindable
15
15
 
16
16
  def bind_attributes(attrs, object = self)
17
17
  attrs.each_pair do |k, v|
18
- if v.is_a?(Hash) then bind_attributes(v, object.send(k))
18
+ case v
19
+ when Hash then bind_attributes(v, object.send(k))
20
+ when Array then v.each { |v| bind strategy_for(v).new(object, k).bind(v) }
19
21
  else bind strategy_for(v).new(object, k).bind(v)
20
22
  end
21
23
  end
@@ -27,25 +29,20 @@ module MotionBindable
27
29
  self
28
30
  end
29
31
 
32
+ def unbind_all
33
+ @bindings.each { |b| b.unbind }
34
+ @bindings = []
35
+ end
36
+
30
37
  def refresh
31
38
  @bindings.each { |b| b.refresh }
32
39
  self
33
40
  end
34
41
 
35
- private
36
-
37
42
  def strategy_for(reference)
38
43
  Strategy.find_by_reference(reference)
39
44
  end
40
45
 
41
- def underscore(str)
42
- str.gsub(/::/, '/')
43
- .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
44
- .gsub(/([a-z\d])([A-Z])/,'\1_\2')
45
- .tr("-", "_")
46
- .downcase
47
- end
48
-
49
46
  end
50
47
 
51
48
  end
@@ -20,9 +20,9 @@ module MotionBindable
20
20
  attr_accessor :object
21
21
  attr_accessor :bound
22
22
 
23
- def initialize(object, attribute)
24
- @attribute = attribute.to_sym
25
- self.object = WeakRef.new(object)
23
+ def initialize(object, attr_name)
24
+ @attr_name = attr_name.to_sym
25
+ self.object = object
26
26
  end
27
27
 
28
28
  def bind(bound)
@@ -32,6 +32,9 @@ module MotionBindable
32
32
  self
33
33
  end
34
34
 
35
+ def unbind
36
+ end
37
+
35
38
  # You can either choose to just override `#refresh` for objects that can't
36
39
  # be bound with callbacks. Or override `#on_bind` for objects that can be
37
40
  # bound with a callback.
@@ -41,11 +44,11 @@ module MotionBindable
41
44
  end
42
45
 
43
46
  def attribute
44
- object.send(@attribute)
47
+ object.send(@attr_name)
45
48
  end
46
49
 
47
50
  def attribute=(value)
48
- object.send(:"#{@attribute.to_s}=", value)
51
+ object.send(:"#{@attr_name.to_s}=", value)
49
52
  end
50
53
 
51
54
  end
@@ -1,3 +1,3 @@
1
1
  module MotionBindable
2
- VERSION = "0.0.6"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -2,28 +2,37 @@ module MotionBindable::Strategies
2
2
 
3
3
  class UITextField < ::MotionBindable::Strategy
4
4
 
5
+ include BW::KVO
6
+
5
7
  def on_bind
6
- update_attribute
8
+ refresh
9
+
10
+ # Observe the bound object
7
11
  NSNotificationCenter.defaultCenter.addObserver(
8
- self,
9
- selector: :on_change,
10
- name: UITextFieldTextDidChangeNotification,
11
- object: bound
12
+ self, selector: :on_bound_change,
13
+ name: UITextFieldTextDidChangeNotification, object: bound
12
14
  )
13
- end
14
15
 
15
- def on_change
16
- update_attribute
16
+ # Observe the attribute
17
+ observe(object, @attr_name) { |_, _| on_object_change }
17
18
  end
18
19
 
19
- alias_method :refresh, :on_change
20
+ def on_bound_change
21
+ self.attribute = bound.text
22
+ end
20
23
 
21
- private
24
+ def on_object_change
25
+ @bound.text = attribute
26
+ end
22
27
 
23
- def update_attribute
24
- self.attribute = bound.text
28
+ def unbind
29
+ App.notification_center.unobserve(@bound_observer)
30
+ unobserve(object, @attr_name)
25
31
  end
26
32
 
33
+ # Text field takes precedence
34
+ alias_method :refresh, :on_bound_change
35
+
27
36
  end
28
37
 
29
38
  end
@@ -17,4 +17,6 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'bubble-wrap', '~> 1.4.0'
20
22
  end
@@ -11,50 +11,77 @@ describe 'MotionBindable::Bindable' do
11
11
 
12
12
  before do
13
13
  @object = FakeBindable.new
14
- @bound = Object.new
14
+ @object.nested = FakeBindable.new
15
15
  @object.stub!(:strategy_for) { |_| FakeStrategy }
16
- @strategy = FakeStrategy.new(@object, :attribute)
16
+ @bound = Object.new
17
+ FakeStrategy.stub!(:new) { |_, _| @strategy }
17
18
  end
18
19
 
19
20
  describe '#bind_attributes' do
20
- before do
21
- @object.nested = FakeBindable.new
22
- end
23
21
 
24
- it 'accepts nested attributes' do
25
- FakeStrategy.stub!(:bind) do |attribute|
26
- @attribute = attribute
22
+ context 'un-nested' do
23
+ before do
24
+ @strategy = FakeStrategy.new(@object, :attribute)
27
25
  end
28
26
 
29
- @object.bind_attributes({
30
- attribute: @bound,
31
- nested: {
32
- attribute: @bound
33
- }
34
- })
27
+ it 'accepts an array of objects' do
28
+ @attributes = []
29
+ @strategy.stub!(:bind) { |attribute| @attributes << attribute }
30
+ @bound2 = Object.new
31
+ @object.bind_attributes(attribute: [@bound, @bound2])
32
+ @attributes.length.should.equal 2
33
+ end
35
34
 
36
- @attribute.should.equal @object.nested.attribute
35
+ it 'passes the strategy to bind' do
36
+ @called = false
37
+ @object.stub!(:bind) { |_| @called = true }
38
+ @object.bind_attributes({ attribute: @bound })
39
+ @called.should.equal true
40
+ end
37
41
  end
38
42
 
39
- it 'passes the strategy to bind' do
40
- @called = false
41
- @object.stub!(:bind) { |_| @called = true }
42
- @object.bind_attributes({ attribute: @bound })
43
- @called.should.equal true
43
+ context 'nested' do
44
+ before do
45
+ @strategy = FakeStrategy.new(@object.nested, :attribute)
46
+ end
47
+
48
+ it 'accepts nested attributes' do
49
+ @strategy.stub!(:bind) { |bound| @bounded = bound }
50
+ @object.bind_attributes nested: { attribute: @bound }
51
+ @bounded.should.equal @bound
52
+ end
44
53
  end
45
54
 
46
55
  end
47
56
 
48
57
  describe '#bind' do
58
+ before do
59
+ @strategy = FakeStrategy.new(@object, :attribute)
60
+ @strategy.bind(@bound)
61
+ end
62
+
49
63
  it 'should be chainable' do
50
64
  @object.bind(@strategy).should.equal @object
51
65
  end
52
66
  end
53
67
 
54
- describe '#refresh' do
55
- it 'should be chainable' do
56
- @object.bind(@strategy)
57
- @object.refresh.should.equal @object
68
+ describe '#unbind_all' do
69
+ before do
70
+ @strategy1 = FakeStrategy.new(@object, :attribute)
71
+ @strategy1.bind(@bound)
72
+ @object.bind(@strategy1)
73
+
74
+ @strategy2 = FakeStrategy.new(@object.nested, :attribute)
75
+ @strategy2.bind(@bound)
76
+ @object.bind(@strategy2)
77
+ end
78
+
79
+ it 'should send unbind to all strategies' do
80
+ @called = 0
81
+ @strategy1.stub!(:unbind) { @called += 1 }
82
+ @strategy2.stub!(:unbind) { @called += 1 }
83
+ @object.unbind_all
84
+ @called.should.equal 2
58
85
  end
59
86
  end
60
87
 
@@ -62,6 +62,12 @@ describe 'MotionBindable::Strategy' do
62
62
  end
63
63
  end
64
64
 
65
+ describe '#unbind' do
66
+ it 'should respond' do
67
+ @strategy.respond_to?(:unbind).should.equal true
68
+ end
69
+ end
70
+
65
71
  end
66
72
 
67
73
  end
@@ -1,7 +1,10 @@
1
1
  class FakeModel
2
2
  include MotionBindable::Bindable
3
- attr_accessor :attribute
4
3
  attr_accessor :nested
4
+ attr_accessor :attribute
5
+ def attribute
6
+ @attribute
7
+ end
5
8
  end
6
9
 
7
10
  describe 'MotionBindable::Strategies::UITextField' do
@@ -24,14 +27,11 @@ describe 'MotionBindable::Strategies::UITextField' do
24
27
  end
25
28
 
26
29
  context 'text set and then bound' do
27
-
28
30
  before do
29
31
  @text_field.text = 'Just testing.'
30
32
  @object.bind_attributes({
31
33
  attribute: @text_field,
32
- nested: {
33
- attribute: @text_field
34
- }
34
+ nested: { attribute: @text_field }
35
35
  })
36
36
  end
37
37
 
@@ -48,9 +48,10 @@ describe 'MotionBindable::Strategies::UITextField' do
48
48
  before do
49
49
  @text_field.text = 'Updated.'
50
50
  NSNotificationCenter.defaultCenter.postNotificationName(
51
- UITextFieldTextDidChangeNotification,
52
- object: @text_field
51
+ UITextFieldTextDidChangeNotification, object: @text_field
53
52
  )
53
+ # BW puts observer cb's into this queue
54
+ NSOperationQueue.mainQueue.waitUntilAllOperationsAreFinished
54
55
  end
55
56
 
56
57
  it 'should update the root attribute' do
@@ -60,12 +61,20 @@ describe 'MotionBindable::Strategies::UITextField' do
60
61
  it 'should update the nested attribute' do
61
62
  @object.nested.attribute.should.equal 'Updated.'
62
63
  end
64
+ end
65
+
66
+ context 'bound attribute is updated' do
67
+ before do
68
+ @object.attribute = 'Reverse'
69
+ end
63
70
 
71
+ it 'should update the text field' do
72
+ @text_field.text.should.equal 'Reverse'
73
+ end
64
74
  end
65
75
 
66
76
  end
67
77
 
68
78
  end
69
79
 
70
-
71
80
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion_bindable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Kot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-19 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2013-12-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bubble-wrap
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 1.4.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 1.4.0
13
27
  description: A simple data binding library for RubyMotion.
14
28
  email:
15
29
  - nk@nathankot.com