Skip to content
This repository was archived by the owner on Oct 19, 2018. It is now read-only.

Commit fee718d

Browse files
committed
added synced scopes
1 parent 2094d35 commit fee718d

File tree

13 files changed

+260
-16
lines changed

13 files changed

+260
-16
lines changed

lib/reactive-record.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
require "reactive_record/active_record/associations"
1010
require "reactive_record/active_record/reactive_record/base"
1111
require "reactive_record/active_record/reactive_record/collection"
12+
require "reactive_record/reactive_scope"
1213
require "reactive_record/active_record/class_methods"
1314
require "reactive_record/active_record/instance_methods"
1415
require "reactive_record/active_record/base"
@@ -22,6 +23,7 @@
2223
require "reactive_record/engine"
2324
require "reactive_record/server_data_cache"
2425
require "reactive_record/active_record/reactive_record/isomorphic_base"
26+
require "reactive_record/reactive_scope"
2527
require "reactive_record/serializers"
2628
require "reactive_record/pry"
2729

lib/reactive_record/active_record/reactive_record/base.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,28 @@ def self.class_scopes(model)
6565
@class_scopes[model.base_class]
6666
end
6767

68+
def self.sync_blocks
69+
# @sync_blocks[watch_model][sync_model][scope_name][...array of blocks...]
70+
@sync_blocks ||= Hash.new { |hash, key| hash[key] = Hash.new { |hash, key| hash[key] = Hash.new { |hash, key| hash[key] = [] } } }
71+
end
72+
73+
def sync_scopes
74+
self.class.sync_blocks[self.model].each do |watching_class, scopes|
75+
scopes.each do |scope_name, blocks|
76+
blocks.each do |block|
77+
if block.arity > 0
78+
block.call watching_class.send(scope_name), @ar_instance
79+
elsif @ar_instance.instance_eval &block
80+
watching_class.send(scope_name) << @ar_instance
81+
else
82+
watching_class.send(scope_name).delete(@ar_instance)
83+
end
84+
end
85+
end
86+
end
87+
model.all << @ar_instance
88+
end
89+
6890
def self.find(model, attribute, value)
6991
# will return the unique record with this attribute-value pair
7092
# value cannot be an association or aggregation

lib/reactive_record/active_record/reactive_record/collection.rb

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def dup_for_sync
2727
end
2828

2929
def all
30+
observed
3031
@dummy_collection.notify if @dummy_collection
3132
unless @collection
3233
@collection = []
@@ -43,7 +44,7 @@ def all
4344
end
4445

4546
def [](index)
46-
47+
observed
4748
if (@collection || all).length <= index and @dummy_collection
4849
(@collection.length..index).each do |i|
4950
new_dummy_record = ReactiveRecord::Base.new_from_vector(@target_klass, nil, *@vector, "*#{i}")
@@ -55,6 +56,9 @@ def [](index)
5556
end
5657

5758
def ==(other_collection)
59+
observed
60+
return nil unless other_collection.is_a? Collection
61+
other_collection.observed
5862
my_collection = (@collection || []).select { |target| target != @dummy_record }
5963
other_collection = (other_collection ? (other_collection.collection || []) : []).select { |target| target != other_collection.dummy_record }
6064
my_collection == other_collection
@@ -68,6 +72,7 @@ def apply_scope(scope, *args)
6872
end
6973

7074
def count
75+
observed
7176
if @collection
7277
@collection.count
7378
elsif @count ||= ReactiveRecord::Base.fetch_from_db([*@vector, "*count"])
@@ -89,6 +94,7 @@ def klass
8994
end
9095

9196
def <<(item)
97+
return delete(item) if item.destroyed? # pushing a destroyed item is the same as removing it
9298
backing_record = item.backing_record
9399
all << item unless all.include? item # does this use == if so we are okay...
94100
if backing_record and @owner and @association and inverse_of = @association.inverse_of and item.attributes[inverse_of] != @owner
@@ -104,7 +110,7 @@ def <<(item)
104110
@dummy_record = @collection.detect { |r| r.backing_record.vector.last =~ /^\*[0-9]+$/ }
105111
@dummy_collection = nil
106112
end
107-
self
113+
notify_of_change
108114
end
109115

110116
[:first, :last].each do |method|
@@ -141,19 +147,19 @@ def replace(new_array)
141147
@dummy_collection = @dummy_record = nil
142148
new_array.each { |item| self << item }
143149
end
144-
new_array
150+
notify_of_change new_array
145151
end
146152

147153
def delete(item)
148-
if @owner and @association and inverse_of = @association.inverse_of
154+
notify_of_change(if @owner and @association and inverse_of = @association.inverse_of
149155
if backing_record = item.backing_record and backing_record.attributes[inverse_of] == @owner
150156
# the if prevents double update if delete is being called from << (see << above)
151157
backing_record.update_attribute(inverse_of, nil)
152158
end
153159
all.delete(item).tap { @owner.backing_record.update_attribute(@association.attribute) } # forces a check if association contents have changed from synced values
154160
else
155161
all.delete(item)
156-
end
162+
end)
157163
end
158164

159165
def loading?
@@ -185,6 +191,19 @@ def dummy_collection
185191
@dummy_collection
186192
end
187193

194+
def notify_of_change(value = nil)
195+
begin
196+
React::State.set_state(self, "collection", collection) unless ReactiveRecord::Base.data_loading?
197+
rescue Exception => e
198+
`debugger`
199+
end
200+
value
201+
end
202+
203+
def observed
204+
React::State.get_state(self, "collection") unless ReactiveRecord::Base.data_loading?
205+
end
206+
188207
end
189208

190209
end

lib/reactive_record/active_record/reactive_record/isomorphic_base.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,10 @@ def save(validate, force, &block)
316316
end
317317
end
318318

319-
response.json[:saved_models].each { | item | backing_records[item[0]].errors! item[3] }
319+
response.json[:saved_models].each do | item |
320+
backing_records[item[0]].sync_scopes
321+
backing_records[item[0]].errors! item[3]
322+
end
320323

321324
yield response.json[:success], response.json[:message], response.json[:models] if block
322325
promise.resolve response.json
@@ -546,6 +549,7 @@ def destroy(&block)
546549

547550
if !data_loading? and (id or vector)
548551
HTTP.post(`window.ReactiveRecordEnginePath`+"/destroy", payload: {model: ar_instance.model_name, id: id, vector: vector}).then do |response|
552+
sync_scopes
549553
yield response.json[:success], response.json[:message] if block
550554
promise.resolve response.json
551555
end

lib/reactive_record/reactive_scope.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class ActiveRecord::Base
2+
3+
def self.to_sync(scope_name, opts={}, &block)
4+
watch_list = if opts[:watch]
5+
[*opts.delete[:watch]]
6+
else
7+
[self]
8+
end
9+
if RUBY_ENGINE=='opal'
10+
watch_list.each do |klass_to_watch|
11+
ReactiveRecord::Base.sync_blocks[klass_to_watch][self][scope_name] << block
12+
end
13+
else
14+
# this is where we put server side watchers in place to sync all clients!
15+
end
16+
end
17+
18+
end

lib/reactive_record/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module ReactiveRecord
2-
VERSION = "0.7.39"
2+
VERSION = "0.7.40"
33
end

spec/test_app/Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ gem "rails"
33
gem 'sqlite3'
44
gem 'opal', "~> 0.8"
55
gem 'react-rails', "1.3.2"#, File.exist?("../../../react-rails") ? {path: "../../../react-rails"} : {git: "https://github.com/catprintlabs/react-rails.git", :branch => 'isomorphic-methods-support'}
6-
gem 'reactive-ruby', "0.7.32" #File.exist?("../../../reactive-ruby") ? {path: "../../../reactive-ruby"} : {}
6+
gem 'reactive-ruby' #File.exist?("../../../reactive-ruby") ? {path: "../../../reactive-ruby"} : {}
77
gem 'opal-rails'
88
gem 'rspec-rails'
99
gem 'reactive-record', path: "../.."

spec/test_app/Gemfile.lock

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ../..
33
specs:
4-
reactive-record (0.7.38)
4+
reactive-record (0.7.39)
55
opal-browser
66
opal-rails
77
rails (>= 3.2.13)
@@ -84,12 +84,12 @@ GEM
8484
minitest (5.8.1)
8585
nokogiri (1.6.6.2)
8686
mini_portile (~> 0.6.0)
87-
opal (0.8.1)
87+
opal (0.8.0)
8888
hike (~> 1.2)
8989
sourcemap (~> 0.1.0)
9090
sprockets (~> 3.1)
9191
tilt (>= 1.4)
92-
opal-activesupport (0.2.0)
92+
opal-activesupport (0.3.0)
9393
opal (>= 0.5.0, < 1.0.0)
9494
opal-browser (0.2.0)
9595
opal
@@ -150,10 +150,10 @@ GEM
150150
execjs
151151
rails (>= 3.2)
152152
tilt
153-
reactive-ruby (0.7.32)
154-
opal
153+
reactive-ruby (0.7.38)
154+
opal (= 0.8.0)
155155
opal-activesupport (>= 0.2.0)
156-
opal-browser
156+
opal-browser (= 0.2.0)
157157
ref (2.0.0)
158158
rspec-core (3.3.2)
159159
rspec-support (~> 3.3.0)
@@ -187,7 +187,7 @@ GEM
187187
ref
188188
thor (0.19.1)
189189
thread_safe (0.3.5)
190-
tilt (2.0.1)
190+
tilt (2.0.2)
191191
tzinfo (1.2.2)
192192
thread_safe (~> 0.1)
193193

@@ -204,7 +204,7 @@ DEPENDENCIES
204204
rails
205205
react-rails (= 1.3.2)
206206
reactive-record!
207-
reactive-ruby (= 0.7.32)
207+
reactive-ruby
208208
rspec-rails
209209
sqlite3
210210

spec/test_app/app/views/models/todo_item.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,16 @@ def update_permitted?
1818
scope :find_string, ->(s) { where("title LIKE ? OR description LIKE ?", "%#{s}%", "%#{s}%") }
1919

2020
scope :active, -> { where("title LIKE '%mitch%' OR description LIKE '%mitch%'")}
21+
to_sync :active do |scope, record|
22+
if record.title =~ /mitch/ || record.description =~ /mitch/
23+
scope << record
24+
else
25+
scope.delete(record)
26+
end
27+
end
28+
2129
scope :important, -> { where("title LIKE '%another%' OR description LIKE '%another%'")}
30+
to_sync(:important) {title =~ /another/ || description =~ /another/ }
2231

2332
def virtual_user_first_name
2433
user.first_name

spec/test_app/db/development.sqlite3

0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)