rmx-firebase 0.0.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.
@@ -0,0 +1,202 @@
1
+ class RMXFirebaseModel
2
+
3
+ include RMXCommonMethods
4
+
5
+ attr_accessor :opts
6
+
7
+ attr_reader :api, :root
8
+
9
+ def self.new(opts=nil)
10
+ x = super
11
+ RMXFirebase::QUEUE.barrier_async do
12
+ x.internal_setup
13
+ end
14
+ x
15
+ end
16
+
17
+ def initialize(opts=nil)
18
+ @opts = opts
19
+ @dependencies_cancelled = {}
20
+ @dependencies_ready = {}
21
+ @dependencies = {}
22
+ end
23
+
24
+ def dealloc
25
+ if RMXFirebase::DEBUG_MODEL_DEALLOC
26
+ p " - dealloc!"
27
+ end
28
+ super
29
+ end
30
+
31
+ def ready?
32
+ !!@ready
33
+ end
34
+
35
+ def cancelled?
36
+ !!@cancelled
37
+ end
38
+
39
+ def finished?
40
+ ready? || cancelled?
41
+ end
42
+
43
+ def ready!
44
+ RMXFirebase::QUEUE.barrier_async do
45
+ # p "ready!"
46
+ @ready = true
47
+ RMX(self).trigger(:ready, self)
48
+ RMX(self).trigger(:finished, self)
49
+ end
50
+ end
51
+
52
+ def cancelled!
53
+ RMXFirebase::QUEUE.barrier_async do
54
+ @cancelled = true
55
+ RMX(self).trigger(:cancelled, self)
56
+ RMX(self).trigger(:finished, self)
57
+ end
58
+ end
59
+
60
+ # override
61
+ def setup
62
+ end
63
+
64
+ def internal_setup
65
+ RMX(self).require_queue!(RMXFirebase::QUEUE, __FILE__, __LINE__) if RMX::DEBUG_QUEUES
66
+ @api = RMXFirebaseCoordinator.new
67
+ RMX(@api).on(:finished, :queue => RMXFirebase::QUEUE) do
68
+ RMX(self).require_queue!(RMXFirebase::QUEUE, __FILE__, __LINE__) if RMX::DEBUG_QUEUES
69
+ check_ready
70
+ end
71
+ RMX(self).on(:cancelled, :exclusive => [ :ready, :finished ], :queue => :async)
72
+ setup
73
+ end
74
+
75
+ def check_ready
76
+ RMX(self).require_queue!(RMXFirebase::QUEUE, __FILE__, __LINE__) if RMX::DEBUG_QUEUES
77
+ # p "check_ready cancelled?", @api.cancelled?, dependencies_cancelled.size
78
+ # p "check_ready ready?", @api.ready?, dependencies_ready.size, dependencies.size
79
+ if @api.cancelled? || @dependencies_cancelled.size > 0
80
+ cancelled!
81
+ elsif @api.ready? && @dependencies_ready.size == @dependencies.size
82
+ ready!
83
+ end
84
+ end
85
+
86
+ def watch(name, ref, opts={}, &block)
87
+ RMX(self).require_queue!(RMXFirebase::QUEUE, __FILE__, __LINE__) if RMX::DEBUG_QUEUES
88
+ RMX(self).ivar(name, @api.watch(name, ref, opts, &block))
89
+ end
90
+
91
+ # add another model as a dependency and ivar,
92
+ # which will affect ready. should be done before ready has
93
+ # has a chance to be triggered. the user can add an
94
+ # attr_reader for easy access if desired.
95
+ #
96
+ # Book
97
+ # attr_reader :author
98
+ # model.watch(:root, ref) do |data|
99
+ # model.depend(:author, Author.get(data[:author_id]))
100
+ # end
101
+ # ...
102
+ # book = Book.get(1)
103
+ # book.attr("name") #=> "My Book"
104
+ # book.author.attr("name") #=> "Joe Noon"
105
+ def depend(name, model)
106
+ RMX(self).require_queue!(RMXFirebase::QUEUE, __FILE__, __LINE__) if RMX::DEBUG_QUEUES
107
+ @dependencies[name] = model
108
+ RMX(self).ivar(name, model)
109
+ track_dependency_state(model)
110
+ RMX(model).on(:finished, :queue => RMXFirebase::QUEUE) do |_model|
111
+ RMX(self).require_queue!(RMXFirebase::QUEUE, __FILE__, __LINE__) if RMX::DEBUG_QUEUES
112
+ track_dependency_state(_model)
113
+ check_ready
114
+ end
115
+ end
116
+
117
+ def track_dependency_state(model)
118
+ RMX(self).require_queue!(RMXFirebase::QUEUE, __FILE__, __LINE__) if RMX::DEBUG_QUEUES
119
+ if model.ready?
120
+ @dependencies_ready[model] = true
121
+ @dependencies_cancelled.delete(model)
122
+ elsif model.cancelled?
123
+ @dependencies_cancelled[model] = true
124
+ @dependencies_ready.delete(model)
125
+ end
126
+ end
127
+
128
+ def always_async(&block)
129
+ always(:async, &block)
130
+ end
131
+
132
+ def always(queue=nil, &block)
133
+ return false if cancelled?
134
+ if ready?
135
+ RMXFirebase.block_on_queue(queue, self, &block)
136
+ end
137
+ RMX(self).on(:ready, :queue => queue, &block)
138
+ end
139
+
140
+ def once(queue=nil, &block)
141
+ RMXFirebase::QUEUE.barrier_async do
142
+ if ready? || cancelled?
143
+ RMXFirebase.block_on_queue(queue, self, &block)
144
+ else
145
+ RMX(self).once(:ready, :strong => true, :queue => queue, &block)
146
+ end
147
+ end
148
+ self
149
+ end
150
+
151
+ def cancel_block(&block)
152
+ RMX(self).off(:ready, &block)
153
+ RMX(self).off(:cancelled, &block)
154
+ RMX(self).off(:finished, &block)
155
+ end
156
+
157
+ def attr(keypath)
158
+ root.attr(keypath)
159
+ end
160
+
161
+ def hasValue?
162
+ root.hasValue?
163
+ end
164
+
165
+ def toValue
166
+ root.toValue
167
+ end
168
+
169
+ def self.create(&block)
170
+ x = new
171
+ block.call(x)
172
+ x
173
+ end
174
+
175
+ # this is the method you should call
176
+ def self.get(opts=nil)
177
+ if opts && existing = identity_map[[ className, opts ]]
178
+ if RMXFirebase::DEBUG_IDENTITY_MAP
179
+ p "HIT!", className, opts, existing.retainCount
180
+ end
181
+ return existing
182
+ else
183
+ if RMXFirebase::DEBUG_IDENTITY_MAP
184
+ p "MISS!", className, opts
185
+ end
186
+ res = new(opts)
187
+ if opts
188
+ identity_map[[ className, opts ]] = res
189
+ end
190
+ res
191
+ end
192
+ end
193
+
194
+ Dispatch.once do
195
+ @@identity_map = RMXSynchronizedStrongToWeakHash.new
196
+ end
197
+
198
+ def self.identity_map
199
+ @@identity_map
200
+ end
201
+
202
+ end
@@ -0,0 +1,43 @@
1
+ class RMXFirebaseTableViewCell < RMXTableViewCell
2
+
3
+ extend RMXFirebaseHandleModel
4
+
5
+ def prepareForReuse
6
+ if @data
7
+ @data_unbinder.call if @data_unbinder
8
+ @data_unbinder = nil
9
+ end
10
+ @data = nil
11
+ reset
12
+ end
13
+
14
+ def reset
15
+ end
16
+
17
+ def changed
18
+ end
19
+
20
+ def data=(val)
21
+ return @data if val == @data
22
+ @data = val
23
+ if @data
24
+ unless @data.ready?
25
+ raise "#{className} tried to use a model that is not ready: #{@data.inspect}"
26
+ end
27
+ @data_unbinder = @data.always do |m|
28
+ next unless m == @data
29
+ changed
30
+ end
31
+ end
32
+ @data
33
+ end
34
+
35
+ def model
36
+ @data
37
+ end
38
+
39
+ def model=(val)
40
+ self.data = val
41
+ end
42
+
43
+ end
@@ -0,0 +1,38 @@
1
+ class RMXFirebaseView < RMXView
2
+
3
+ extend RMXFirebaseHandleModel
4
+
5
+ def reset
6
+ end
7
+
8
+ def changed
9
+ end
10
+
11
+ def model
12
+ @model
13
+ end
14
+
15
+ def model=(val)
16
+ return @model if @model == val
17
+ if @model
18
+ @model_unbinder.call if @model_unbinder
19
+ @model_unbinder = nil
20
+ end
21
+ @model = val
22
+ reset
23
+ if @model
24
+ unless @model.ready?
25
+ raise "#{className} tried to use a model that is not ready: #{@model.rmx_object_desc}"
26
+ end
27
+ @model_unbinder = @model.always do |m|
28
+ unless m == @model
29
+ p "model.always", "m", m, "@model", @model
30
+ end
31
+ next unless m == @model
32
+ changed
33
+ end
34
+ end
35
+ @model
36
+ end
37
+
38
+ end
@@ -0,0 +1,46 @@
1
+ class RMXFirebaseViewController < RMXViewController
2
+
3
+ extend RMXFirebaseHandleModel
4
+
5
+ def viewDidLoad
6
+ s = super
7
+ if @pending_changed
8
+ @pending_changed = nil
9
+ if @model
10
+ changed
11
+ end
12
+ end
13
+ s
14
+ end
15
+
16
+ def changed
17
+ end
18
+
19
+ def model
20
+ @model
21
+ end
22
+
23
+ def model=(val)
24
+ return @model if @model == val
25
+ if @model
26
+ @model_unbinder.call if @model_unbinder
27
+ @model_unbinder = nil
28
+ end
29
+ @model = val
30
+ if @model
31
+ unless @model.ready?
32
+ raise "#{className} tried to use a model that is not ready: #{@model.inspect}"
33
+ end
34
+ @model_unbinder = @model.always do |m|
35
+ next unless m == @model
36
+ if isViewLoaded
37
+ changed
38
+ else
39
+ @pending_changed = true
40
+ end
41
+ end
42
+ end
43
+ @model
44
+ end
45
+
46
+ end
@@ -0,0 +1,3 @@
1
+ class RMXFirebase
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,26 @@
1
+ require "rmx-firebase/version"
2
+
3
+ unless defined?(Motion::Project::Config)
4
+ raise "This file must be required within a RubyMotion project Rakefile."
5
+ end
6
+
7
+ Motion::Project::App.setup do |app|
8
+ index = app.files.rindex { |x| x.index("/RMX") }
9
+ %w(
10
+ Firebase+RMXFirebase
11
+ FQuery+RMXFirebase
12
+ RMXFirebase
13
+ RMXFirebaseDataSnapshot
14
+ RMXFirebaseListener
15
+ RMXFirebaseCoordinator
16
+ RMXFirebaseModel
17
+ RMXFirebaseBatch
18
+ RMXFirebaseCollection
19
+ RMXFirebaseHandleModel
20
+ RMXFirebaseTableViewCell
21
+ RMXFirebaseView
22
+ RMXFirebaseViewController
23
+ ).each_with_index do |x, i|
24
+ app.files.insert(index + 1 + i, File.join(File.dirname(__FILE__), "motion/#{x}.rb"))
25
+ end
26
+ end
Binary file
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rmx-firebase/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "rmx-firebase"
8
+ gem.version = RMXFirebase::VERSION
9
+ gem.authors = ["Joe Noon"]
10
+ gem.email = ["joenoon@gmail.com"]
11
+ gem.description = %q{Experimental rubymotion wrapper for firebase}
12
+ gem.summary = %q{Experimental rubymotion wrapper for firebase}
13
+ gem.homepage = "https://github.com/joenoon/rmx-firebase"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ gem.add_dependency "rmx", "~> 0.5.2"
20
+ end
@@ -0,0 +1,146 @@
1
+ class Bacon::Context
2
+ def after_modifications(collection, &block)
3
+ wait(0.5) do
4
+ collection.once do |snaps|
5
+ snap_names = snaps.map(&:name)
6
+ puts "snap_names: #{snap_names.inspect}\n\n"
7
+ RMX.block_on_main_q(block, snap_names)
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ describe "RMXFirebaseCollection" do
14
+
15
+ before do
16
+ Firebase.goOffline
17
+ $firebase = Firebase.alloc.initWithUrl("https://rmext.firebaseio.local/")
18
+ @ref = $firebase["collection_test"]
19
+ @letters = {
20
+ "a" => 10,
21
+ "b" => 20,
22
+ "c" => 30,
23
+ "d" => 40,
24
+ "e" => 50,
25
+ "f" => 60,
26
+ "g" => 70,
27
+ "h" => 80,
28
+ "i" => 90,
29
+ "j" => 100,
30
+ "k" => 110,
31
+ "l" => 120,
32
+ "m" => 130,
33
+ "n" => 140,
34
+ "o" => 150,
35
+ "p" => 160,
36
+ "q" => 170,
37
+ "r" => 180,
38
+ "s" => 190,
39
+ "t" => 200,
40
+ "u" => 210,
41
+ "v" => 220,
42
+ "w" => 230,
43
+ "x" => 240,
44
+ "y" => 250,
45
+ "z" => 260
46
+ }
47
+ end
48
+
49
+ describe "a collection" do
50
+
51
+ before do
52
+ @col = RMXFirebaseCollection.new(@ref)
53
+ @ref.setValue({})
54
+ @letters.each_pair do |k, pri|
55
+ p "SET", k, pri
56
+ @ref[k].setValue(pri, andPriority:pri)
57
+ end
58
+ end
59
+
60
+ it "can move c after v" do
61
+ @ref["c"].setPriority(@letters["v"] + 1)
62
+ after_modifications(@col) do |snap_names|
63
+ snap_names.index("c").should == snap_names.index("v") + 1
64
+ end
65
+ end
66
+
67
+ it "can move c after z" do
68
+ @ref["c"].setPriority(@letters["z"] + 1)
69
+ after_modifications(@col) do |snap_names|
70
+ snap_names.index("c").should == snap_names.index("z") + 1
71
+ end
72
+ end
73
+
74
+ it "can move c after everything" do
75
+ @ref["c"].setPriority(10000)
76
+ after_modifications(@col) do |snap_names|
77
+ snap_names.last.should == "c"
78
+ end
79
+ end
80
+
81
+ it "can move v before f" do
82
+ @ref["v"].setPriority(@letters["f"] - 1)
83
+ after_modifications(@col) do |snap_names|
84
+ snap_names.index("v").should == snap_names.index("f") - 1
85
+ end
86
+ end
87
+
88
+ it "can move c before everything" do
89
+ @ref["c"].setPriority(-10000)
90
+ after_modifications(@col) do |snap_names|
91
+ snap_names.first.should == "c"
92
+ end
93
+ end
94
+
95
+ it "add a new value before everything" do
96
+ @ref["new"].setValue(".", andPriority:-10000)
97
+ after_modifications(@col) do |snap_names|
98
+ snap_names.first.should == "new"
99
+ end
100
+ end
101
+
102
+ it "add a new value after everything" do
103
+ @ref["new"].setValue(".", andPriority:10000)
104
+ after_modifications(@col) do |snap_names|
105
+ snap_names.last.should == "new"
106
+ end
107
+ end
108
+
109
+ it "add a new value after j" do
110
+ @ref["new"].setValue(".", andPriority:(@letters["j"] + 1))
111
+ after_modifications(@col) do |snap_names|
112
+ snap_names.index("new").should == snap_names.index("j") + 1
113
+ end
114
+ end
115
+
116
+ it "add a new value before j" do
117
+ @ref["new"].setValue(".", andPriority:(@letters["j"] - 1))
118
+ after_modifications(@col) do |snap_names|
119
+ snap_names.index("new").should == snap_names.index("j") - 1
120
+ end
121
+ end
122
+
123
+ it "remove a" do
124
+ @ref["a"].removeValue
125
+ after_modifications(@col) do |snap_names|
126
+ snap_names.first.should == "b"
127
+ end
128
+ end
129
+
130
+ it "remove z" do
131
+ @ref["z"].removeValue
132
+ after_modifications(@col) do |snap_names|
133
+ snap_names.last.should == "y"
134
+ end
135
+ end
136
+
137
+ it "remove j" do
138
+ @ref["j"].removeValue
139
+ after_modifications(@col) do |snap_names|
140
+ snap_names[snap_names.index("i") + 1].should == "k"
141
+ end
142
+ end
143
+
144
+ end
145
+
146
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rmx-firebase
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Joe Noon
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rmx
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.5.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.5.2
27
+ description: Experimental rubymotion wrapper for firebase
28
+ email:
29
+ - joenoon@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - .gitignore
35
+ - Gemfile
36
+ - LICENSE.txt
37
+ - README.md
38
+ - Rakefile
39
+ - app/app_delegate.rb
40
+ - lib/motion/FQuery+RMXFirebase.rb
41
+ - lib/motion/Firebase+RMXFirebase.rb
42
+ - lib/motion/RMXFirebase.rb
43
+ - lib/motion/RMXFirebaseBatch.rb
44
+ - lib/motion/RMXFirebaseCollection.rb
45
+ - lib/motion/RMXFirebaseCoordinator.rb
46
+ - lib/motion/RMXFirebaseDataSnapshot.rb
47
+ - lib/motion/RMXFirebaseHandleModel.rb
48
+ - lib/motion/RMXFirebaseListener.rb
49
+ - lib/motion/RMXFirebaseModel.rb
50
+ - lib/motion/RMXFirebaseTableViewCell.rb
51
+ - lib/motion/RMXFirebaseView.rb
52
+ - lib/motion/RMXFirebaseViewController.rb
53
+ - lib/rmx-firebase.rb
54
+ - lib/rmx-firebase/version.rb
55
+ - resources/Default-568h@2x.png
56
+ - rmx-firebase.gemspec
57
+ - spec/collection_spec.rb
58
+ homepage: https://github.com/joenoon/rmx-firebase
59
+ licenses: []
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.0.14
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Experimental rubymotion wrapper for firebase
81
+ test_files:
82
+ - spec/collection_spec.rb