render_sync 0.5.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 +7 -0
- data/CHANGELOG.md +153 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +521 -0
- data/Rakefile +9 -0
- data/app/assets/javascripts/sync.coffee +355 -0
- data/app/controllers/sync/refetches_controller.rb +56 -0
- data/app/helpers/render_sync/config_helper.rb +15 -0
- data/config/routes.rb +3 -0
- data/config/sync.yml +21 -0
- data/lib/generators/render_sync/install_generator.rb +14 -0
- data/lib/generators/render_sync/templates/sync.ru +14 -0
- data/lib/generators/render_sync/templates/sync.yml +34 -0
- data/lib/render_sync.rb +174 -0
- data/lib/render_sync/action.rb +39 -0
- data/lib/render_sync/actions.rb +114 -0
- data/lib/render_sync/channel.rb +23 -0
- data/lib/render_sync/clients/dummy.rb +22 -0
- data/lib/render_sync/clients/faye.rb +104 -0
- data/lib/render_sync/clients/pusher.rb +77 -0
- data/lib/render_sync/controller_helpers.rb +33 -0
- data/lib/render_sync/engine.rb +24 -0
- data/lib/render_sync/erb_tracker.rb +49 -0
- data/lib/render_sync/faye_extension.rb +45 -0
- data/lib/render_sync/model.rb +174 -0
- data/lib/render_sync/model_actions.rb +60 -0
- data/lib/render_sync/model_change_tracking.rb +97 -0
- data/lib/render_sync/model_syncing.rb +65 -0
- data/lib/render_sync/model_touching.rb +35 -0
- data/lib/render_sync/partial.rb +112 -0
- data/lib/render_sync/partial_creator.rb +47 -0
- data/lib/render_sync/reactor.rb +48 -0
- data/lib/render_sync/refetch_model.rb +21 -0
- data/lib/render_sync/refetch_partial.rb +43 -0
- data/lib/render_sync/refetch_partial_creator.rb +21 -0
- data/lib/render_sync/renderer.rb +19 -0
- data/lib/render_sync/resource.rb +115 -0
- data/lib/render_sync/scope.rb +113 -0
- data/lib/render_sync/scope_definition.rb +30 -0
- data/lib/render_sync/view_helpers.rb +106 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/sync/users/_show.html.erb +1 -0
- data/test/dummy/app/views/sync/users/refetch/_show.html.erb +1 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +22 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +8 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/log/test.log +626 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/em_minitest_spec.rb +100 -0
- data/test/fixtures/sync_auth_token_missing.yml +6 -0
- data/test/fixtures/sync_erb.yml +7 -0
- data/test/fixtures/sync_faye.yml +7 -0
- data/test/fixtures/sync_pusher.yml +8 -0
- data/test/models/group.rb +3 -0
- data/test/models/project.rb +2 -0
- data/test/models/todo.rb +8 -0
- data/test/models/user.rb +82 -0
- data/test/sync/abstract_controller.rb +3 -0
- data/test/sync/action_test.rb +82 -0
- data/test/sync/channel_test.rb +15 -0
- data/test/sync/config_test.rb +25 -0
- data/test/sync/erb_tracker_test.rb +72 -0
- data/test/sync/faye_extension_test.rb +87 -0
- data/test/sync/message_test.rb +159 -0
- data/test/sync/model_test.rb +315 -0
- data/test/sync/partial_creator_test.rb +35 -0
- data/test/sync/partial_test.rb +107 -0
- data/test/sync/protected_attributes_test.rb +39 -0
- data/test/sync/reactor_test.rb +18 -0
- data/test/sync/refetch_model_test.rb +26 -0
- data/test/sync/refetch_partial_creator_test.rb +16 -0
- data/test/sync/refetch_partial_test.rb +74 -0
- data/test/sync/renderer_test.rb +19 -0
- data/test/sync/resource_test.rb +181 -0
- data/test/sync/scope_definition_test.rb +39 -0
- data/test/sync/scope_test.rb +113 -0
- data/test/test_helper.rb +66 -0
- data/test/travis/sync.ru +14 -0
- data/test/travis/sync.yml +21 -0
- metadata +317 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe RenderSync::Channel do
|
4
|
+
include TestHelper
|
5
|
+
|
6
|
+
describe '#signature' do
|
7
|
+
before do
|
8
|
+
@channel = RenderSync::Channel.new("testing")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "Creates uniqe HMAC signature" do
|
12
|
+
assert_equal 40, @channel.signature.length
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe RenderSync.config do
|
4
|
+
before do
|
5
|
+
RenderSync.load_config(
|
6
|
+
File.expand_path("../../fixtures/sync_erb.yml", __FILE__),
|
7
|
+
"test"
|
8
|
+
)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#load_config" do
|
12
|
+
it "Evaluates ERB from the config file" do
|
13
|
+
assert_equal("erb secret", RenderSync.config[:auth_token])
|
14
|
+
end
|
15
|
+
|
16
|
+
it "raises an exception if auth_token is missing" do
|
17
|
+
assert_raises ArgumentError do
|
18
|
+
RenderSync.load_config(
|
19
|
+
File.expand_path("../../fixtures/sync_auth_token_missing.yml", __FILE__),
|
20
|
+
"test"
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
require 'rails/all'
|
3
|
+
require 'active_support/core_ext/array/access'
|
4
|
+
require 'render_sync/erb_tracker'
|
5
|
+
|
6
|
+
describe RenderSync::ERBTracker do
|
7
|
+
Template = Struct.new(:source)
|
8
|
+
it 'tracks collection partials' do
|
9
|
+
dependencies = RenderSync::ERBTracker.call "name", Template.new(<<-TEMPLATE)
|
10
|
+
<%= sync partial: 'item', collection: something.things %>
|
11
|
+
TEMPLATE
|
12
|
+
|
13
|
+
assert_equal ['sync/things/item'], dependencies
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'tracks collection instance variable partials' do
|
17
|
+
dependencies = RenderSync::ERBTracker.call "name", Template.new(<<-TEMPLATE)
|
18
|
+
<%= sync partial: 'item', collection: @something.things %>
|
19
|
+
TEMPLATE
|
20
|
+
|
21
|
+
assert_equal ['sync/things/item'], dependencies
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'tracks resource partials' do
|
25
|
+
dependencies = RenderSync::ERBTracker.call "name", Template.new(<<-TEMPLATE)
|
26
|
+
<%= sync partial: 'item', resource: thing %>
|
27
|
+
TEMPLATE
|
28
|
+
|
29
|
+
assert_equal ['sync/things/item'], dependencies
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'tracks sync_new partials' do
|
33
|
+
dependencies = RenderSync::ERBTracker.call "name", Template.new(<<-TEMPLATE)
|
34
|
+
<%= sync_new partial: 'item', resource: thing %>
|
35
|
+
TEMPLATE
|
36
|
+
|
37
|
+
assert_equal ['sync/things/item'], dependencies
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'tracks multiple sync partials' do
|
41
|
+
dependencies = RenderSync::ERBTracker.call "name", Template.new(<<-TEMPLATE)
|
42
|
+
<%= sync partial: 'item', resource: thing %>
|
43
|
+
<%= sync partial: 'other_item', resource: rock %>
|
44
|
+
TEMPLATE
|
45
|
+
|
46
|
+
assert_equal ['sync/things/item', 'sync/rocks/other_item'], dependencies
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'tracks resource instance variable partials' do
|
50
|
+
dependencies = RenderSync::ERBTracker.call "name", Template.new(<<-TEMPLATE)
|
51
|
+
<%= sync partial: 'item', resource: @thing %>
|
52
|
+
TEMPLATE
|
53
|
+
|
54
|
+
assert_equal ['sync/things/item'], dependencies
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'tracks haml resource partials' do
|
58
|
+
dependencies = RenderSync::ERBTracker.call "name", Template.new(<<-TEMPLATE)
|
59
|
+
=sync partial: 'item', resource: thing
|
60
|
+
TEMPLATE
|
61
|
+
|
62
|
+
assert_equal ['sync/things/item'], dependencies
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'tracks regular renders too' do
|
66
|
+
dependencies = RenderSync::ERBTracker.call "name", Template.new(<<-TEMPLATE)
|
67
|
+
<%= render partial: 'things/item', collection: things %>
|
68
|
+
TEMPLATE
|
69
|
+
|
70
|
+
assert_equal ['things/item'], dependencies
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe RenderSync::FayeExtension do
|
4
|
+
include TestHelper
|
5
|
+
|
6
|
+
before do
|
7
|
+
@server = RenderSync::FayeExtension.new
|
8
|
+
@message = {
|
9
|
+
"channel" => "/channel",
|
10
|
+
"message" => "HTML",
|
11
|
+
"ext" => {"auth_token" => "secret"}
|
12
|
+
}
|
13
|
+
@unauthed_message = {
|
14
|
+
"channel" => "/channel",
|
15
|
+
"message" => "HTML",
|
16
|
+
"ext" => {"auth_token" => "WRONG"}
|
17
|
+
}
|
18
|
+
@batched_message = {
|
19
|
+
"data" => [{
|
20
|
+
"channel" => "/channel",
|
21
|
+
"message" => "HTML",
|
22
|
+
"ext" => {"auth_token" => "secret"}
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"channel" => "/channel",
|
26
|
+
"message" => "HTML",
|
27
|
+
"ext" => {"auth_token" => "secret"}
|
28
|
+
}]
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'incoming messages' do
|
33
|
+
describe 'message authentication' do
|
34
|
+
describe 'with valid auth_token' do
|
35
|
+
it 'should be valid' do
|
36
|
+
assert @server.message_authenticated?(@message)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'with invalid auth_token' do
|
41
|
+
it 'should be invalid' do
|
42
|
+
refute @server.message_authenticated?(@unauthed_message)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should add error to message before callback' do
|
46
|
+
assert @server.incoming(@unauthed_message, Proc.new{|msg| msg["error"]})
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'outgoing messages' do
|
53
|
+
it 'should strip out message auth_token to prevent auth_token leak' do
|
54
|
+
assert_equal nil, @server.outgoing(
|
55
|
+
{"ext" => {"auth_token" => "secret"}},
|
56
|
+
Proc.new{|message| message["ext"]["auth_token"] }
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'batch_incoming' do
|
62
|
+
it 'proccesses all batched messages as single message' do
|
63
|
+
assert @server.batch_incoming(@batched_message, Proc.new{})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'single_incoming(message, callback)' do
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'batch_publish?' do
|
71
|
+
describe 'with batched messages' do
|
72
|
+
it 'should be true' do
|
73
|
+
assert @server.batch_publish?({
|
74
|
+
'channel' => '/batch_publish'
|
75
|
+
})
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'with single message' do
|
80
|
+
it 'should be false' do
|
81
|
+
refute @server.batch_publish?({
|
82
|
+
'channel' => '/some-channel'
|
83
|
+
})
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
require 'mocha/setup'
|
3
|
+
|
4
|
+
|
5
|
+
describe "Faye" do
|
6
|
+
include TestHelperFaye
|
7
|
+
|
8
|
+
before do
|
9
|
+
@message = RenderSync.client.build_message("/my-channel", html: "<p>Some Data</p>")
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "normalize_channel" do
|
13
|
+
it 'converts channel to faye server friendly format with leading forward-slash' do
|
14
|
+
assert_equal "/", RenderSync.client.normalize_channel("alfjalkjfkfjaslkfj2342424")[0]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#to_hash' do
|
19
|
+
before do
|
20
|
+
@message_hash = @message.to_hash
|
21
|
+
end
|
22
|
+
|
23
|
+
it "Converts message to hash for Faye publish" do
|
24
|
+
assert @message_hash.keys.include?(:channel)
|
25
|
+
assert @message_hash.keys.include?(:data)
|
26
|
+
assert @message_hash.keys.include?(:ext)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "Includes auth_token for Faye password security" do
|
30
|
+
assert @message_hash[:ext][:auth_token]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#to_json' do
|
35
|
+
it "Converts message to json for Faye publish" do
|
36
|
+
assert @message.to_json
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "asynchronous publishing" do
|
41
|
+
include EM::MiniTest::Spec
|
42
|
+
|
43
|
+
before do
|
44
|
+
RenderSync.stubs(:async?).returns true
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "batched message publishing" do
|
48
|
+
before do
|
49
|
+
@messages = 10.times.collect{|i| RenderSync.client.build_message("/ch#{i}", {html: ""})}
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should publish array of messages with single post to faye' do
|
53
|
+
EM.expects(:next_tick).once.returns true
|
54
|
+
assert RenderSync.client.batch_publish(@messages)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#publish' do
|
59
|
+
it 'Publishes a message to Faye' do
|
60
|
+
RenderSync.reactor.expects(:perform).once
|
61
|
+
@message.publish
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "synchronous publishing" do
|
67
|
+
before do
|
68
|
+
Net::HTTP.stubs(:post_form).returns true
|
69
|
+
RenderSync.stubs(:async?).returns false
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "batched message publishing" do
|
73
|
+
before do
|
74
|
+
@messages = 10.times.collect{|i| RenderSync.client.build_message("/ch#{i}", {html: ""})}
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should publish array of messages with single post to faye' do
|
78
|
+
assert RenderSync.client.batch_publish(@messages)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
describe '#publish' do
|
82
|
+
it 'Publishes a message to Faye' do
|
83
|
+
assert @message.publish
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
describe "Pusher" do
|
94
|
+
include TestHelperPusher
|
95
|
+
|
96
|
+
before do
|
97
|
+
@message = RenderSync.client.build_message("/my-channel", html: "<p>Some Data</p>")
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "normalize_channel" do
|
101
|
+
it 'converts channel to pusher server friendly format without leading forward-slash' do
|
102
|
+
refute RenderSync.client.normalize_channel("alfjalkjfkfjaslkfj2342424")[0] == "/"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '#to_json' do
|
107
|
+
it "Converts message to json for Faye publish" do
|
108
|
+
assert @message.to_json
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "asynchronous publishing" do
|
113
|
+
include EM::MiniTest::Spec
|
114
|
+
|
115
|
+
before do
|
116
|
+
RenderSync.stubs(:async?).returns true
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "batched message publishing" do
|
120
|
+
before do
|
121
|
+
@messages = 10.times.collect{|i| RenderSync.client.build_message("/ch#{i}", {html: ""})}
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should publish array of messages with single post to faye' do
|
125
|
+
assert RenderSync.client.batch_publish(@messages)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe '#publish' do
|
130
|
+
it 'Publishes a message to Pusher' do
|
131
|
+
RenderSync.reactor.expects(:perform).once
|
132
|
+
@message.publish
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "synchronous publishing" do
|
138
|
+
before do
|
139
|
+
Pusher.stubs(:trigger).returns(true)
|
140
|
+
RenderSync.stubs(:async?).returns false
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "batched message publishing" do
|
144
|
+
before do
|
145
|
+
@messages = 10.times.collect{|i| RenderSync.client.build_message("/ch#{i}", {html: ""})}
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should publish array of messages with single post to faye' do
|
149
|
+
assert RenderSync.client.batch_publish(@messages)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
describe '#publish' do
|
153
|
+
it 'Publishes a message to Pusher' do
|
154
|
+
assert @message.publish
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
@@ -0,0 +1,315 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
require 'mocha/setup'
|
3
|
+
require 'rails/all'
|
4
|
+
|
5
|
+
setup_database
|
6
|
+
|
7
|
+
describe RenderSync::Model do
|
8
|
+
|
9
|
+
it 'can is disabled by default' do
|
10
|
+
refute RenderSync::Model.enabled?
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'can be enabled and disabled' do
|
14
|
+
RenderSync::Model.enable!
|
15
|
+
assert RenderSync::Model.enabled?
|
16
|
+
|
17
|
+
RenderSync::Model.disable!
|
18
|
+
refute RenderSync::Model.enabled?
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'can be given a block to have things enabled in' do
|
22
|
+
RenderSync::Model.enable do
|
23
|
+
assert RenderSync::Model.enabled?
|
24
|
+
end
|
25
|
+
|
26
|
+
refute RenderSync::Model.enabled?
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'syncing of model changes to all listening channels' do
|
30
|
+
it 'publishes record (create/update/destroy) to main new channel' do
|
31
|
+
RenderSync::Model.enable do
|
32
|
+
user = UserWithoutScopes.new
|
33
|
+
|
34
|
+
# Create
|
35
|
+
user.save!
|
36
|
+
assert user.persisted?
|
37
|
+
assert_equal 1, user.sync_actions.size
|
38
|
+
|
39
|
+
assert_equal :new, user.sync_actions[0].name
|
40
|
+
assert_equal "/user_without_scopes/#{user.id}", user.sync_actions[0].test_path
|
41
|
+
|
42
|
+
# Update
|
43
|
+
user.update_attributes!(name: "Foo")
|
44
|
+
assert user.persisted?
|
45
|
+
assert_equal 1, user.sync_actions.size
|
46
|
+
|
47
|
+
assert_equal :update, user.sync_actions[0].name
|
48
|
+
assert_equal "/user_without_scopes/#{user.id}", user.sync_actions[0].test_path
|
49
|
+
|
50
|
+
# Destroy
|
51
|
+
user.destroy
|
52
|
+
assert user.destroyed?
|
53
|
+
assert_equal 1, user.sync_actions.size
|
54
|
+
|
55
|
+
assert_equal :destroy, user.sync_actions[0].name
|
56
|
+
assert_equal "/user_without_scopes/#{user.id}", user.sync_actions[0].test_path
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'publishes record with default scope to scope channel and parent channel' do
|
61
|
+
RenderSync::Model.enable do
|
62
|
+
|
63
|
+
# Create
|
64
|
+
group = Group.create!
|
65
|
+
user = UserWithDefaultScope.new(group: group)
|
66
|
+
user.save!
|
67
|
+
|
68
|
+
assert user.persisted?
|
69
|
+
assert_equal 1, user.sync_actions.size
|
70
|
+
|
71
|
+
assert_equal :new, user.sync_actions[0].name
|
72
|
+
assert_equal "/groups/#{group.id}/user_with_default_scopes/#{user.id}", user.sync_actions[0].test_path
|
73
|
+
|
74
|
+
# Update
|
75
|
+
user.update_attributes!(name: "Foo")
|
76
|
+
|
77
|
+
assert user.persisted?
|
78
|
+
assert_equal 1, user.sync_actions.size
|
79
|
+
|
80
|
+
assert_equal :update, user.sync_actions[0].name
|
81
|
+
assert_equal "/user_with_default_scopes/#{user.id}", user.sync_actions[0].test_path
|
82
|
+
|
83
|
+
# Destroy
|
84
|
+
user.destroy
|
85
|
+
|
86
|
+
assert user.destroyed?
|
87
|
+
assert_equal 1, user.sync_actions.size
|
88
|
+
|
89
|
+
assert_equal :destroy, user.sync_actions[0].name
|
90
|
+
assert_equal "/groups/#{group.id}/user_with_default_scopes/#{user.id}", user.sync_actions[0].test_path
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'publishes record with simple named sync scope' do
|
96
|
+
RenderSync::Model.enable do
|
97
|
+
|
98
|
+
# Create user not in scope 'old' (age > 90)
|
99
|
+
user = UserWithSimpleScope.create!(age: 85)
|
100
|
+
|
101
|
+
assert_equal 1, user.sync_actions.size
|
102
|
+
|
103
|
+
assert_equal :new, user.sync_actions[0].name
|
104
|
+
assert_equal "/user_with_simple_scopes/#{user.id}", user.sync_actions[0].test_path
|
105
|
+
|
106
|
+
# Create user in scope 'old' (age >= 90)
|
107
|
+
user = UserWithSimpleScope.new(age: 95)
|
108
|
+
user.save!
|
109
|
+
assert_equal 2, user.sync_actions.size
|
110
|
+
|
111
|
+
assert_equal :new, user.sync_actions[0].name
|
112
|
+
assert_equal "/user_with_simple_scopes/#{user.id}", user.sync_actions[0].test_path
|
113
|
+
|
114
|
+
assert_equal :new, user.sync_actions[1].name
|
115
|
+
assert_equal "/old/user_with_simple_scopes/#{user.id}", user.sync_actions[1].test_path
|
116
|
+
|
117
|
+
# Update of independent attribute name (user still in scope 'old')
|
118
|
+
user.update_attributes!(name: "Foo")
|
119
|
+
assert !user.changed?
|
120
|
+
assert_equal 1, user.sync_actions.size
|
121
|
+
|
122
|
+
assert_equal :update, user.sync_actions[0].name
|
123
|
+
assert_equal "/user_with_simple_scopes/#{user.id}", user.sync_actions[0].test_path
|
124
|
+
|
125
|
+
# Update of dependent attribute age, so that the user no longer falls into scope 'old'
|
126
|
+
# and has to be destroyed on the scoped channel
|
127
|
+
user.update_attributes!(age: 80)
|
128
|
+
assert !user.changed?
|
129
|
+
assert_equal 2, user.sync_actions.size
|
130
|
+
|
131
|
+
assert_equal :update, user.sync_actions[0].name
|
132
|
+
assert_equal "/user_with_simple_scopes/#{user.id}", user.sync_actions[0].test_path
|
133
|
+
|
134
|
+
assert_equal :destroy, user.sync_actions[1].name
|
135
|
+
assert_equal "/old/user_with_simple_scopes/#{user.id}", user.sync_actions[1].test_path
|
136
|
+
|
137
|
+
# Update of dependent attribute age, so that the record will fall into scope 'old'
|
138
|
+
# and has to be published as new on that scoped channel
|
139
|
+
user.update_attributes(age: 100)
|
140
|
+
|
141
|
+
assert !user.changed?
|
142
|
+
assert_equal 2, user.sync_actions.size
|
143
|
+
|
144
|
+
assert_equal :update, user.sync_actions[0].name
|
145
|
+
assert_equal "/user_with_simple_scopes/#{user.id}", user.sync_actions[0].test_path
|
146
|
+
|
147
|
+
assert_equal :new, user.sync_actions[1].name
|
148
|
+
assert_equal "/old/user_with_simple_scopes/#{user.id}", user.sync_actions[1].test_path
|
149
|
+
|
150
|
+
# Destroy user currently in scoped by 'old'
|
151
|
+
user.destroy
|
152
|
+
|
153
|
+
assert user.destroyed?
|
154
|
+
assert_equal 2, user.sync_actions.size
|
155
|
+
|
156
|
+
assert_equal :destroy, user.sync_actions[0].name
|
157
|
+
assert_equal "/user_with_simple_scopes/#{user.id}", user.sync_actions[0].test_path
|
158
|
+
|
159
|
+
assert_equal :destroy, user.sync_actions[1].name
|
160
|
+
assert_equal "/old/user_with_simple_scopes/#{user.id}", user.sync_actions[1].test_path
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'publishes record with a named sync scope that takes arguments' do
|
166
|
+
RenderSync::Model.enable do
|
167
|
+
|
168
|
+
# Create user not in scope 'in_group'
|
169
|
+
group1 = Group.create
|
170
|
+
group2 = Group.create
|
171
|
+
user = UserWithAdvancedScope.create!
|
172
|
+
|
173
|
+
assert user.persisted?
|
174
|
+
assert_equal 1, user.sync_actions.size
|
175
|
+
|
176
|
+
assert_equal :new, user.sync_actions[0].name
|
177
|
+
assert_equal "/user_with_advanced_scopes/#{user.id}", user.sync_actions[0].test_path
|
178
|
+
|
179
|
+
# Create user in scope 'in_group'
|
180
|
+
user = UserWithAdvancedScope.create!(group: group1)
|
181
|
+
|
182
|
+
assert user.persisted?
|
183
|
+
assert_equal 2, user.sync_actions.size
|
184
|
+
|
185
|
+
assert_equal :new, user.sync_actions[0].name
|
186
|
+
assert_equal "/user_with_advanced_scopes/#{user.id}", user.sync_actions[0].test_path
|
187
|
+
|
188
|
+
assert_equal :new, user.sync_actions[1].name
|
189
|
+
assert_equal "/in_group/group/#{group1.id}/user_with_advanced_scopes/#{user.id}", user.sync_actions[1].test_path
|
190
|
+
|
191
|
+
# Change group
|
192
|
+
user.update_attributes(group: group2)
|
193
|
+
|
194
|
+
assert user.persisted?
|
195
|
+
assert_equal 3, user.sync_actions.size
|
196
|
+
|
197
|
+
assert_equal :update, user.sync_actions[0].name
|
198
|
+
assert_equal "/user_with_advanced_scopes/#{user.id}", user.sync_actions[0].test_path
|
199
|
+
|
200
|
+
assert_equal :destroy, user.sync_actions[1].name
|
201
|
+
assert_equal "/in_group/group/#{group1.id}/user_with_advanced_scopes/#{user.id}", user.sync_actions[1].test_path
|
202
|
+
|
203
|
+
assert_equal :new, user.sync_actions[2].name
|
204
|
+
assert_equal "/in_group/group/#{group2.id}/user_with_advanced_scopes/#{user.id}", user.sync_actions[2].test_path
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
describe "touching associated records explicitly" do
|
212
|
+
it 'unsyncd user touches single association if configured' do
|
213
|
+
RenderSync::Model.enable do
|
214
|
+
group1 = Group.create
|
215
|
+
group2 = Group.create
|
216
|
+
user = UserJustTouchingGroup.create!(group: group1)
|
217
|
+
|
218
|
+
assert user.persisted?
|
219
|
+
assert_equal 1, user.sync_actions.size
|
220
|
+
|
221
|
+
assert_equal :update, user.sync_actions[0].name
|
222
|
+
assert_equal "/groups/#{group1.id}", user.sync_actions[0].test_path
|
223
|
+
|
224
|
+
user.group = group2
|
225
|
+
user.save!
|
226
|
+
|
227
|
+
assert !user.changed?
|
228
|
+
assert_equal 2, user.sync_actions.size
|
229
|
+
|
230
|
+
assert_equal :update, user.sync_actions[0].name
|
231
|
+
assert_equal "/groups/#{group2.id}", user.sync_actions[0].test_path
|
232
|
+
|
233
|
+
assert_equal :update, user.sync_actions[1].name
|
234
|
+
assert_equal "/groups/#{group1.id}", user.sync_actions[1].test_path
|
235
|
+
|
236
|
+
user.group = nil
|
237
|
+
user.save!
|
238
|
+
|
239
|
+
assert !user.changed?
|
240
|
+
assert_equal 1, user.sync_actions.size
|
241
|
+
|
242
|
+
assert_equal :update, user.sync_actions[0].name
|
243
|
+
assert_equal "/groups/#{group2.id}", user.sync_actions[0].test_path
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'syncd user touches single association if configured' do
|
248
|
+
RenderSync::Model.enable do
|
249
|
+
group1 = Group.create
|
250
|
+
group2 = Group.create
|
251
|
+
user = UserTouchingGroup.create!(group: group1)
|
252
|
+
|
253
|
+
assert user.persisted?
|
254
|
+
assert_equal 2, user.sync_actions.size
|
255
|
+
|
256
|
+
assert_equal :update, user.sync_actions[1].name
|
257
|
+
assert_equal "/groups/#{group1.id}", user.sync_actions[1].test_path
|
258
|
+
|
259
|
+
user.group = group2
|
260
|
+
user.save!
|
261
|
+
|
262
|
+
assert !user.changed?
|
263
|
+
assert_equal 3, user.sync_actions.size
|
264
|
+
|
265
|
+
assert_equal :update, user.sync_actions[1].name
|
266
|
+
assert_equal "/groups/#{group2.id}", user.sync_actions[1].test_path
|
267
|
+
|
268
|
+
assert_equal :update, user.sync_actions[2].name
|
269
|
+
assert_equal "/groups/#{group1.id}", user.sync_actions[2].test_path
|
270
|
+
|
271
|
+
user.group = nil
|
272
|
+
user.save!
|
273
|
+
|
274
|
+
assert !user.changed?
|
275
|
+
assert_equal 2, user.sync_actions.size
|
276
|
+
|
277
|
+
assert_equal :update, user.sync_actions[1].name
|
278
|
+
assert_equal "/groups/#{group2.id}", user.sync_actions[1].test_path
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
it 'touches multiple associations if configured' do
|
283
|
+
RenderSync::Model.enable do
|
284
|
+
group = Group.create
|
285
|
+
project = Project.create
|
286
|
+
user = UserTouchingGroupAndProject.create!(group: group, project: project)
|
287
|
+
|
288
|
+
assert user.persisted?
|
289
|
+
assert_equal 3, user.sync_actions.size
|
290
|
+
|
291
|
+
assert_equal :update, user.sync_actions[1].name
|
292
|
+
assert_equal "/groups/#{group.id}", user.sync_actions[1].test_path
|
293
|
+
|
294
|
+
assert_equal :update, user.sync_actions[2].name
|
295
|
+
assert_equal "/projects/#{project.id}", user.sync_actions[2].test_path
|
296
|
+
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
|
302
|
+
it 'does not have a sync default scope if it is not specified' do
|
303
|
+
user = User.new name: "Foo"
|
304
|
+
assert user.sync_default_scope.nil?
|
305
|
+
end
|
306
|
+
|
307
|
+
it 'does not sync if sync is not enabled' do
|
308
|
+
user = UserWithSimpleScope.new name: "Foo"
|
309
|
+
user.stubs(:publish_actions)
|
310
|
+
|
311
|
+
user.expects(:publish_actions).never
|
312
|
+
user.save!
|
313
|
+
end
|
314
|
+
|
315
|
+
end
|