live_record 0.1.2 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -2
- data/{lib/live_record/.rspec → .rspec} +0 -0
- data/.travis.yml +0 -1
- data/Gemfile +3 -1
- data/README.md +363 -202
- data/Rakefile +5 -0
- data/app/assets/javascripts/live_record.coffee +4 -0
- data/app/assets/javascripts/live_record/helpers.coffee +4 -0
- data/app/assets/javascripts/live_record/helpers/load_records.coffee +13 -7
- data/app/assets/javascripts/live_record/helpers/spaceship.coffee +13 -0
- data/app/assets/javascripts/live_record/model.coffee +4 -0
- data/app/assets/javascripts/live_record/model/create.coffee +96 -27
- data/app/assets/javascripts/live_record/plugins.coffee +3 -0
- data/app/assets/javascripts/live_record/plugins/live_dom.coffee +5 -19
- data/app/assets/javascripts/live_record/plugins/live_dom/apply_to_model.coffee +17 -0
- data/app/channels/live_record/base_channel.rb +41 -0
- data/app/channels/live_record/changes_channel.rb +59 -0
- data/app/channels/live_record/publications_channel.rb +134 -0
- data/{lib/live_record/config.ru → config.ru} +0 -0
- data/lib/live_record.rb +2 -0
- data/lib/live_record/action_view_extensions/view_helper.rb +22 -0
- data/lib/live_record/configure.rb +19 -0
- data/lib/live_record/generators/install_generator.rb +9 -4
- data/lib/live_record/generators/templates/create_live_record_updates.rb +1 -1
- data/lib/live_record/generators/templates/index.html.erb +1 -0
- data/lib/live_record/generators/templates/model.rb.rb +4 -4
- data/lib/live_record/model/callbacks.rb +8 -2
- data/lib/live_record/version.rb +1 -1
- data/live_record.gemspec +2 -2
- data/{lib/live_record/spec → spec}/factories/posts.rb +0 -0
- data/spec/features/live_record_syncing_spec.rb +184 -0
- data/spec/helpers/wait.rb +19 -0
- data/{lib/live_record/spec → spec}/internal/app/assets/config/manifest.js +0 -0
- data/{lib/live_record/spec → spec}/internal/app/assets/javascripts/application.js +0 -0
- data/{lib/live_record/spec → spec}/internal/app/assets/javascripts/cable.js +0 -0
- data/spec/internal/app/assets/javascripts/posts.coffee +8 -0
- data/{lib/live_record/spec → spec}/internal/app/channels/application_cable/channel.rb +0 -0
- data/{lib/live_record/spec → spec}/internal/app/channels/application_cable/connection.rb +4 -4
- data/{lib/live_record/spec → spec}/internal/app/controllers/application_controller.rb +0 -0
- data/{lib/live_record/spec → spec}/internal/app/controllers/posts_controller.rb +1 -0
- data/{lib/live_record/spec → spec}/internal/app/models/application_record.rb +0 -0
- data/{lib/live_record/spec → spec}/internal/app/models/live_record_update.rb +0 -0
- data/spec/internal/app/models/post.rb +11 -0
- data/{lib/live_record/spec → spec}/internal/app/views/layouts/application.html.erb +0 -0
- data/{lib/live_record/spec → spec}/internal/app/views/posts/_form.html.erb +0 -0
- data/{lib/live_record/spec → spec}/internal/app/views/posts/_post.json.jbuilder +0 -0
- data/{lib/live_record/spec → spec}/internal/app/views/posts/edit.html.erb +0 -0
- data/{lib/live_record/spec → spec}/internal/app/views/posts/index.html.erb +6 -5
- data/{lib/live_record/spec → spec}/internal/app/views/posts/index.json.jbuilder +0 -0
- data/{lib/live_record/spec → spec}/internal/app/views/posts/new.html.erb +0 -0
- data/{lib/live_record/spec → spec}/internal/app/views/posts/show.html.erb +0 -0
- data/{lib/live_record/spec → spec}/internal/app/views/posts/show.json.jbuilder +0 -0
- data/{lib/live_record/spec → spec}/internal/config/cable.yml +0 -0
- data/{lib/live_record/spec → spec}/internal/config/database.yml +0 -0
- data/{lib/live_record/spec → spec}/internal/config/routes.rb +0 -0
- data/{lib/live_record/spec → spec}/internal/db/schema.rb +2 -0
- data/{lib/live_record/spec → spec}/internal/public/favicon.ico +0 -0
- data/{lib/live_record/spec → spec}/rails_helper.rb +4 -2
- data/{lib/live_record/spec → spec}/spec_helper.rb +0 -0
- metadata +64 -56
- data/app/assets/javascripts/live_record.js +0 -4
- data/app/assets/javascripts/live_record/helpers.js +0 -4
- data/app/assets/javascripts/live_record/model.js +0 -4
- data/app/assets/javascripts/live_record/plugins.js +0 -3
- data/lib/live_record/channel/implement.rb +0 -100
- data/lib/live_record/spec/features/live_record_syncing_spec.rb +0 -60
- data/lib/live_record/spec/internal/app/assets/javascripts/posts.coffee +0 -14
- data/lib/live_record/spec/internal/app/channels/live_record_channel.rb +0 -4
- data/lib/live_record/spec/internal/app/models/post.rb +0 -11
File without changes
|
data/lib/live_record.rb
CHANGED
@@ -6,6 +6,8 @@ Dir[__dir__ + '/live_record/*.rb'].each {|file| require file }
|
|
6
6
|
Dir[__dir__ + '/live_record/model/*.rb'].each {|file| require file }
|
7
7
|
Dir[__dir__ + '/live_record/channel/*.rb'].each {|file| require file }
|
8
8
|
Dir[__dir__ + '/live_record/generators/*.rb'].each {|file| require file }
|
9
|
+
Dir[__dir__ + '/live_record/overrides/*.rb'].each {|file| require file }
|
10
|
+
Dir[__dir__ + '/live_record/action_view_extensions/*.rb'].each {|file| require file }
|
9
11
|
|
10
12
|
module LiveRecord
|
11
13
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module LiveRecord
|
2
|
+
module ActionViewExtensions
|
3
|
+
module ViewHelper
|
4
|
+
def live_record_element(record)
|
5
|
+
raw " data-live-record-element='#{record.class.name}-#{record.id}' "
|
6
|
+
end
|
7
|
+
|
8
|
+
def live_record_updatable(record, attribute)
|
9
|
+
raise ArgumentError, "[#{record.class}] does not have an attribute named [#{attribute}]" unless record.attribute_names.include? attribute.to_s
|
10
|
+
raw " data-live-record-update-from='#{record.class.name}-#{record.id}-#{attribute}' "
|
11
|
+
end
|
12
|
+
|
13
|
+
def live_record_destroyable(record)
|
14
|
+
raw " data-live-record-destroy-from='#{record.class.name}-#{record.id}' "
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
ActiveSupport.on_load(:action_view) do
|
21
|
+
include LiveRecord::ActionViewExtensions::ViewHelper
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module LiveRecord
|
4
|
+
|
5
|
+
class Configuration < OpenStruct
|
6
|
+
end
|
7
|
+
|
8
|
+
@configuration = Configuration.new(
|
9
|
+
sync_record_buffer_time: 1.minute
|
10
|
+
)
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :configuration
|
14
|
+
|
15
|
+
def configure(&block)
|
16
|
+
block.call(@configuration)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -32,10 +32,15 @@ module LiveRecord
|
|
32
32
|
migration_template 'create_live_record_updates.rb', 'db/migrate/create_live_record_updates.rb'
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
end
|
35
|
+
# def copy_live_record_changes_channel_template
|
36
|
+
# class_collisions 'LiveRecordChangesChannel'
|
37
|
+
# template 'live_record_changes_channel.rb', File.join('app/channels', 'live_record_changes_channel.rb')
|
38
|
+
# end
|
39
|
+
|
40
|
+
# def copy_live_record_publication_channel_template
|
41
|
+
# class_collisions 'LiveRecordPublicationChannel'
|
42
|
+
# template 'live_record_publication_channel.rb', File.join('app/channels', 'live_record_publication_channel.rb')
|
43
|
+
# end
|
39
44
|
|
40
45
|
def update_application_javascript
|
41
46
|
in_root do
|
@@ -11,12 +11,12 @@ class <%= class_name %> < <%= parent_class_name.classify %>
|
|
11
11
|
<% end -%>
|
12
12
|
|
13
13
|
include LiveRecord::Model::Callbacks
|
14
|
-
has_many :live_record_updates, as: :recordable
|
14
|
+
has_many :live_record_updates, as: :recordable, dependent: :destroy
|
15
15
|
|
16
16
|
def self.live_record_whitelisted_attributes(<%= class_name.underscore %>, current_user)
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
# Add attributes to this array that you would like current_user to have access to.
|
18
|
+
# Defaults to empty array, thereby blocking everything by default, only unless explicitly stated here so.
|
19
|
+
[]
|
20
20
|
end
|
21
21
|
end
|
22
22
|
<% end -%>
|
@@ -7,6 +7,7 @@ module LiveRecord
|
|
7
7
|
before_update :__live_record_reference_changed_attributes__
|
8
8
|
after_update_commit :__live_record_broadcast_record_update__
|
9
9
|
after_destroy_commit :__live_record_broadcast_record_destroy__
|
10
|
+
after_create_commit :__live_record_broadcast_record_create__
|
10
11
|
|
11
12
|
def self.live_record_whitelisted_attributes(record, current_user)
|
12
13
|
[]
|
@@ -22,13 +23,18 @@ module LiveRecord
|
|
22
23
|
included_attributes = attributes.slice(*@_live_record_changed_attributes)
|
23
24
|
@_live_record_changed_attributes = nil
|
24
25
|
message_data = { 'action' => 'update', 'attributes' => included_attributes }
|
25
|
-
|
26
|
+
LiveRecord::ChangesChannel.broadcast_to(self, message_data)
|
26
27
|
LiveRecordUpdate.create!(recordable_type: self.class, recordable_id: self.id, created_at: DateTime.now)
|
27
28
|
end
|
28
29
|
|
29
30
|
def __live_record_broadcast_record_destroy__
|
30
31
|
message_data = { 'action' => 'destroy' }
|
31
|
-
|
32
|
+
LiveRecord::ChangesChannel.broadcast_to(self, message_data)
|
33
|
+
end
|
34
|
+
|
35
|
+
def __live_record_broadcast_record_create__
|
36
|
+
message_data = { 'action' => 'create', 'attributes' => attributes }
|
37
|
+
ActionCable.server.broadcast "live_record:publications:#{self.class.name.underscore}", message_data
|
32
38
|
end
|
33
39
|
end
|
34
40
|
end
|
data/lib/live_record/version.rb
CHANGED
data/live_record.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = 'live_record'
|
7
7
|
s.version = LiveRecord::VERSION
|
8
8
|
s.summary = 'Rails 5 ActionCable Live JS Objects and DOM Elements'
|
9
|
-
s.description = "Auto-syncs records in client-side JS (through a Model DSL) from changes in the backend Rails server through ActionCable.\
|
9
|
+
s.description = "Auto-syncs records in client-side JS (through a Model DSL) from changes (updates/destroy) in the backend Rails server through ActionCable.\n Also supports streaming newly created records to client-side JS.\n Supports lost connection restreaming for both new records (create), and record-changes (updates/destroy).\n Auto-updates DOM elements mapped to a record attribute, from changes (updates/destroy)."
|
10
10
|
s.authors = ['Jules Roman B. Polidario']
|
11
11
|
s.email = 'jrpolidario@gmail.com'
|
12
12
|
s.files = `git ls-files`.split("\n")
|
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
|
17
17
|
s.add_dependency 'rails', '>= 5.0.0', '< 5.2'
|
18
18
|
|
19
|
+
s.add_development_dependency 'rails', '~> 5.1'
|
19
20
|
s.add_development_dependency 'bundler', '~> 1.3'
|
20
21
|
s.add_development_dependency 'rspec-rails', '~> 3.6'
|
21
22
|
s.add_development_dependency 'combustion', '~> 0.7'
|
@@ -27,7 +28,6 @@ Gem::Specification.new do |s|
|
|
27
28
|
s.add_development_dependency 'sprockets-rails', '~> 3.2'
|
28
29
|
s.add_development_dependency 'coffee-rails', '~> 4.2'
|
29
30
|
s.add_development_dependency 'jbuilder', '~> 2.7'
|
30
|
-
s.add_development_dependency 'capybara', '~> 2.15'
|
31
31
|
s.add_development_dependency 'chromedriver-helper', '~> 1.1'
|
32
32
|
s.add_development_dependency 'selenium-webdriver', '~> 3.5'
|
33
33
|
s.add_development_dependency 'faker', '~> 1.8'
|
File without changes
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.feature 'LiveRecord Syncing', type: :feature do
|
4
|
+
let(:post1) { create(:post) }
|
5
|
+
let(:post2) { create(:post) }
|
6
|
+
let(:post3) { create(:post) }
|
7
|
+
let!(:posts) { [post1, post2, post3] }
|
8
|
+
|
9
|
+
scenario 'User sees live changes (updates) of post records', js: true do
|
10
|
+
visit '/posts'
|
11
|
+
|
12
|
+
post1_title_td = find('td', text: post1.title, wait: 10)
|
13
|
+
post2_title_td = find('td', text: post2.title, wait: 10)
|
14
|
+
post3_title_td = find('td', text: post3.title, wait: 10)
|
15
|
+
|
16
|
+
post1.update!(title: 'post1newtitle')
|
17
|
+
post2.update!(title: 'post2newtitle')
|
18
|
+
|
19
|
+
expect(post1_title_td).to have_content('post1newtitle', wait: 10)
|
20
|
+
expect(post2_title_td).to have_content('post2newtitle', wait: 10)
|
21
|
+
expect(post3_title_td).to have_content(post3.title, wait: 10)
|
22
|
+
end
|
23
|
+
|
24
|
+
scenario 'User sees live changes (destroy) of post records', js: true do
|
25
|
+
visit '/posts'
|
26
|
+
|
27
|
+
expect{find('td', text: post1.title, wait: 10)}.to_not raise_error
|
28
|
+
expect{find('td', text: post2.title, wait: 10)}.to_not raise_error
|
29
|
+
expect{find('td', text: post3.title, wait: 10)}.to_not raise_error
|
30
|
+
|
31
|
+
post1.destroy
|
32
|
+
post2.destroy
|
33
|
+
|
34
|
+
expect{find('td', text: post1.title)}.to raise_error Capybara::ElementNotFound
|
35
|
+
expect{find('td', text: post2.title)}.to raise_error Capybara::ElementNotFound
|
36
|
+
expect{find('td', text: post3.title)}.to_not raise_error
|
37
|
+
end
|
38
|
+
|
39
|
+
# see spec/internal/app/models/post.rb to view specified whitelisted attributes
|
40
|
+
scenario 'User sees live changes (updates) of post records, but only changes from whitelisted authorised attributes', js: true do
|
41
|
+
visit '/posts'
|
42
|
+
|
43
|
+
post1_title_td = find('td', text: post1.title, wait: 10)
|
44
|
+
post1_content_td = find('td', text: post1.content, wait: 10)
|
45
|
+
post2_title_td = find('td', text: post2.title, wait: 10)
|
46
|
+
post2_content_td = find('td', text: post2.content, wait: 10)
|
47
|
+
post3_title_td = find('td', text: post3.title, wait: 10)
|
48
|
+
post3_content_td = find('td', text: post3.content, wait: 10)
|
49
|
+
|
50
|
+
post1.update!(title: 'post1newtitle', content: 'post1newcontent')
|
51
|
+
post2.update!(title: 'post2newtitle', content: 'post2newcontent')
|
52
|
+
post3.update!(title: 'post3newtitle', content: 'post3newcontent')
|
53
|
+
|
54
|
+
expect(post1_title_td).to have_content('post1newtitle', wait: 10)
|
55
|
+
expect(post1_content_td).to_not have_content('post1newcontent')
|
56
|
+
expect(post2_title_td).to have_content('post2newtitle', wait: 10)
|
57
|
+
expect(post2_content_td).to_not have_content('post2newcontent')
|
58
|
+
expect(post3_title_td).to have_content('post3newtitle', wait: 10)
|
59
|
+
expect(post3_content_td).to_not have_content('post3newcontent')
|
60
|
+
end
|
61
|
+
|
62
|
+
# see spec/internal/app/views/posts/index.html.erb to see the subscribe "conditions"
|
63
|
+
scenario 'JS-Client receives live new (create) post records where specified "conditions" matched', js: true do
|
64
|
+
visit '/posts'
|
65
|
+
|
66
|
+
sleep(5)
|
67
|
+
|
68
|
+
post4 = create(:post, id: 98, is_enabled: true)
|
69
|
+
post5 = create(:post, id: 99, is_enabled: false)
|
70
|
+
|
71
|
+
wait before: -> { evaluate_script("LiveRecord.Model.all.Post.all[#{post4.id}] == undefined") }, becomes: -> (value) { value == false }
|
72
|
+
expect(evaluate_script("LiveRecord.Model.all.Post.all[#{post4.id}] == undefined")).to be false
|
73
|
+
|
74
|
+
wait before: -> { evaluate_script("LiveRecord.Model.all.Post.all[#{post5.id}] == undefined") }, becomes: -> (value) { value == true }
|
75
|
+
expect(evaluate_script("LiveRecord.Model.all.Post.all[#{post5.id}] == undefined")).to be true
|
76
|
+
end
|
77
|
+
|
78
|
+
# see spec/internal/app/views/posts/index.html.erb to see the subscribe "conditions"
|
79
|
+
scenario 'JS-Client receives live new (create) post records where only considered "conditions" are the whitelisted authorised attributes', js: true do
|
80
|
+
visit '/posts'
|
81
|
+
|
82
|
+
sleep(5)
|
83
|
+
|
84
|
+
# in index.html.erb:
|
85
|
+
# LiveRecord.Model.all.Post.subscribe({ where: { is_enabled: true, content: 'somecontent' }});
|
86
|
+
# because `content` is not whitelisted, therefore the `content` condition above is disregarded
|
87
|
+
post4 = create(:post, is_enabled: true, content: 'somecontent')
|
88
|
+
post5 = create(:post, is_enabled: true, content: 'contentisnotwhitelistedthereforewontbeconsidered')
|
89
|
+
|
90
|
+
wait before: -> { evaluate_script("LiveRecord.Model.all.Post.all[#{post4.id}] == undefined") }, becomes: -> (value) { value == false }
|
91
|
+
expect(evaluate_script("LiveRecord.Model.all.Post.all[#{post4.id}] == undefined")).to be false
|
92
|
+
|
93
|
+
wait before: -> { evaluate_script("LiveRecord.Model.all.Post.all[#{post5.id}] == undefined") }, becomes: -> (value) { value == false }
|
94
|
+
expect(evaluate_script("LiveRecord.Model.all.Post.all[#{post5.id}] == undefined")).to be false
|
95
|
+
end
|
96
|
+
|
97
|
+
# see spec/internal/app/models/post.rb to view specified whitelisted attributes
|
98
|
+
scenario 'JS-Client receives live new (create) post records having only the whitelisted authorised attributes', js: true do
|
99
|
+
visit '/posts'
|
100
|
+
|
101
|
+
sleep(5)
|
102
|
+
|
103
|
+
post4 = create(:post, is_enabled: true, title: 'sometitle', content: 'somecontent')
|
104
|
+
|
105
|
+
wait before: -> { evaluate_script("LiveRecord.Model.all.Post.all[#{post4.id}] == undefined") }, becomes: -> (value) { value == false }
|
106
|
+
expect(evaluate_script("LiveRecord.Model.all.Post.all[#{post4.id}].title()")).to eq post4.title
|
107
|
+
expect(evaluate_script("LiveRecord.Model.all.Post.all[#{post4.id}].content()")).to eq nil
|
108
|
+
end
|
109
|
+
|
110
|
+
# see spec/internal/app/models/post.rb to view specified whitelisted attributes
|
111
|
+
context 'when client got disconnected, and then reconnected' do
|
112
|
+
scenario 'JS-Client resyncs stale records', js: true do
|
113
|
+
post_that_will_be_updated_while_disconnected_1 = create(:post, is_enabled: true)
|
114
|
+
post_that_will_be_updated_while_disconnected_2 = create(:post, is_enabled: true)
|
115
|
+
|
116
|
+
visit '/posts'
|
117
|
+
|
118
|
+
sleep(5)
|
119
|
+
|
120
|
+
disconnection_time = 20 # seconds
|
121
|
+
|
122
|
+
Thread.new do
|
123
|
+
sleep(2)
|
124
|
+
|
125
|
+
# temporarily stop all current publication_channel connections
|
126
|
+
ObjectSpace.each_object(LiveRecord::ChangesChannel) do |changes_channel|
|
127
|
+
changes_channel.connection.close
|
128
|
+
end
|
129
|
+
|
130
|
+
# then we update records while disconnected
|
131
|
+
post_that_will_be_updated_while_disconnected_1.update!(title: 'newtitle')
|
132
|
+
post_that_will_be_updated_while_disconnected_2.update!(title: 'newtitle')
|
133
|
+
end
|
134
|
+
|
135
|
+
# LiveRecord.stop_all_streams
|
136
|
+
sleep(disconnection_time)
|
137
|
+
|
138
|
+
wait before: -> { evaluate_script("LiveRecord.Model.all.Post.all[#{post_that_will_be_updated_while_disconnected_1.id}] == undefined") }, becomes: -> (value) { value == false }, duration: 10.seconds
|
139
|
+
expect(evaluate_script("LiveRecord.Model.all.Post.all[#{post_that_will_be_updated_while_disconnected_1.id}].title()")).to eq 'newtitle'
|
140
|
+
|
141
|
+
wait before: -> { evaluate_script("LiveRecord.Model.all.Post.all[#{post_that_will_be_updated_while_disconnected_2.id}] == undefined") }, becomes: -> (value) { value == false }
|
142
|
+
expect(evaluate_script("LiveRecord.Model.all.Post.all[#{post_that_will_be_updated_while_disconnected_2.id}].title()")).to eq 'newtitle'
|
143
|
+
end
|
144
|
+
|
145
|
+
scenario 'JS-Client receives all post records created during the time it got disconnected', js: true do
|
146
|
+
visit '/posts'
|
147
|
+
|
148
|
+
sleep(5)
|
149
|
+
|
150
|
+
disconnection_time = 20 # seconds
|
151
|
+
|
152
|
+
post_created_before_disconnection = nil
|
153
|
+
post_created_while_disconnected_1 = nil
|
154
|
+
post_created_while_disconnected_2 = nil
|
155
|
+
|
156
|
+
Thread.new do
|
157
|
+
sleep(2)
|
158
|
+
|
159
|
+
# temporarily stop all current publication_channel connections
|
160
|
+
ObjectSpace.each_object(LiveRecord::PublicationsChannel) do |publication_channel|
|
161
|
+
publication_channel.connection.close
|
162
|
+
end
|
163
|
+
|
164
|
+
# then we create records while disconnected
|
165
|
+
post_created_while_disconnected_1 = create(:post, is_enabled: true, created_at: (DateTime.now - LiveRecord.configuration.sync_record_buffer_time) + 30.seconds)
|
166
|
+
post_created_while_disconnected_2 = create(:post, is_enabled: true, created_at: (DateTime.now - LiveRecord.configuration.sync_record_buffer_time) + 99.hours)
|
167
|
+
# we need to create this here, otherwise it will be loaded on the Page immediately by the .loadRecords() in JS
|
168
|
+
post_created_before_disconnection = create(:post, is_enabled: true, created_at: (DateTime.now - LiveRecord.configuration.sync_record_buffer_time) - 30.seconds)
|
169
|
+
end
|
170
|
+
|
171
|
+
# LiveRecord.stop_all_streams
|
172
|
+
sleep(disconnection_time)
|
173
|
+
|
174
|
+
wait before: -> { evaluate_script("LiveRecord.Model.all.Post.all[#{post_created_while_disconnected_1.id}] == undefined") }, becomes: -> (value) { value == false }, duration: 10.seconds
|
175
|
+
expect(evaluate_script("LiveRecord.Model.all.Post.all[#{post_created_while_disconnected_1.id}] == undefined")).to be false
|
176
|
+
|
177
|
+
wait before: -> { evaluate_script("LiveRecord.Model.all.Post.all[#{post_created_while_disconnected_2.id}] == undefined") }, becomes: -> (value) { value == false }
|
178
|
+
expect(evaluate_script("LiveRecord.Model.all.Post.all[#{post_created_while_disconnected_2.id}] == undefined")).to be false
|
179
|
+
|
180
|
+
wait before: -> { evaluate_script("LiveRecord.Model.all.Post.all[#{post_created_before_disconnection.id}] == undefined") }, becomes: -> (value) { value == false }
|
181
|
+
expect(evaluate_script("LiveRecord.Model.all.Post.all[#{post_created_before_disconnection.id}] == undefined")).to be true
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SpecHelpers
|
2
|
+
module Wait
|
3
|
+
# Wait before the value of the "before" Proc becomes "becomes",
|
4
|
+
# but only wait until "duration" number of seconds,
|
5
|
+
# while checking the value each "interval" seconds interval.
|
6
|
+
def wait(duration: 5.seconds, interval: (0.5).second, before:, becomes:)
|
7
|
+
# use a different thread to prevent blocking the main thread due to sleep()
|
8
|
+
Thread.new do
|
9
|
+
start = Time.now
|
10
|
+
|
11
|
+
loop do
|
12
|
+
break if becomes.call(before.call)
|
13
|
+
sleep interval.seconds
|
14
|
+
break if (Time.now - start).seconds > duration
|
15
|
+
end
|
16
|
+
end.join
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Post < ApplicationRecord
|
2
|
+
include LiveRecord::Model::Callbacks
|
3
|
+
|
4
|
+
has_many :live_record_updates, as: :recordable, dependent: :destroy
|
5
|
+
|
6
|
+
def self.live_record_whitelisted_attributes(post, current_user)
|
7
|
+
# Add attributes to this array that you would like current_user to have access to.
|
8
|
+
# Defaults to empty array, thereby blocking everything by default, only unless explicitly stated here so.
|
9
|
+
[:title, :is_enabled, :created_at, :updated_at]
|
10
|
+
end
|
11
|
+
end
|
File without changes
|