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,97 @@
|
|
1
|
+
module RenderSync
|
2
|
+
module ModelChangeTracking
|
3
|
+
private
|
4
|
+
# Set up callback to store record and sync scope states prior
|
5
|
+
# the update action
|
6
|
+
def self.included(base)
|
7
|
+
base.class_eval do
|
8
|
+
before_update :store_state_before_update, if: -> { RenderSync::Model.enabled? }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Stores the current state of the record with its attributes
|
13
|
+
# and all sync relations in an instance variable BEFORE the update
|
14
|
+
# command to later be able to check if the record has been
|
15
|
+
# added/removed from sync scopes.
|
16
|
+
#
|
17
|
+
# Uses ActiveModel::Dirty to track attribute changes
|
18
|
+
# (triggered by AR Callback before_update)
|
19
|
+
#
|
20
|
+
def store_state_before_update
|
21
|
+
record = self.dup
|
22
|
+
changed_attributes.each do |key, value|
|
23
|
+
record.send("#{key}=", value)
|
24
|
+
end
|
25
|
+
record.send("#{self.class.primary_key}=", self.send(self.class.primary_key))
|
26
|
+
|
27
|
+
@record_before_update = record
|
28
|
+
|
29
|
+
@scopes_before_update = {}
|
30
|
+
sync_scope_definitions.each do |definition|
|
31
|
+
scope = RenderSync::Scope.new_from_model(definition, record)
|
32
|
+
@scopes_before_update[definition.name] = {
|
33
|
+
scope: scope,
|
34
|
+
contains_record: scope.contains?(record)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Checks if this record has left the old scope defined by the passed scope
|
40
|
+
# definition throughout the update process
|
41
|
+
#
|
42
|
+
def left_old_scope?(definition)
|
43
|
+
scope_before_update(definition).valid? \
|
44
|
+
&& old_record_in_old_scope?(definition) \
|
45
|
+
&& !new_record_in_old_scope?(definition)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Checks if this record has entered the new (possibly changed) scope
|
49
|
+
# defined by the passed scope definition throughout the update process
|
50
|
+
#
|
51
|
+
def entered_new_scope?(definition)
|
52
|
+
scope_after_update(definition).valid? \
|
53
|
+
&& new_record_in_new_scope?(definition) \
|
54
|
+
&& !remained_in_old_scope?(definition)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Return the instance (state) of this record from before the update
|
58
|
+
# (which was previously stored by #store_state_before_update)
|
59
|
+
#
|
60
|
+
def record_before_update
|
61
|
+
@record_before_update
|
62
|
+
end
|
63
|
+
|
64
|
+
def record_after_update
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def remained_in_old_scope?(definition)
|
69
|
+
old_record_in_old_scope?(definition) && new_record_in_old_scope?(definition)
|
70
|
+
end
|
71
|
+
|
72
|
+
def scope_before_update(definition)
|
73
|
+
@scopes_before_update[definition.name][:scope]
|
74
|
+
end
|
75
|
+
|
76
|
+
def scope_after_update(definition)
|
77
|
+
RenderSync::Scope.new_from_model(definition, record_after_update)
|
78
|
+
end
|
79
|
+
|
80
|
+
def old_record_in_old_scope?(definition)
|
81
|
+
@scopes_before_update[definition.name][:contains_record]
|
82
|
+
end
|
83
|
+
|
84
|
+
def old_record_in_new_scope?(definition)
|
85
|
+
scope_after_update(definition).contains?(record_before_update)
|
86
|
+
end
|
87
|
+
|
88
|
+
def new_record_in_new_scope?(definition)
|
89
|
+
scope_after_update(definition).contains?(record_after_update)
|
90
|
+
end
|
91
|
+
|
92
|
+
def new_record_in_old_scope?(defintion)
|
93
|
+
scope_before_update(defintion).contains?(record_after_update)
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module RenderSync
|
2
|
+
module ModelRenderSyncing
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def prepare_sync_create
|
7
|
+
add_sync_action(:new, self, default_scope: sync_default_scope)
|
8
|
+
|
9
|
+
sync_scope_definitions.each do |definition|
|
10
|
+
scope = RenderSync::Scope.new_from_model(definition, self)
|
11
|
+
if scope.contains?(self)
|
12
|
+
add_sync_action :new, self, scope: scope, default_scope: sync_default_scope
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def prepare_sync_update
|
18
|
+
add_sync_action :update, self
|
19
|
+
|
20
|
+
sync_scope_definitions.each do |definition|
|
21
|
+
prepare_sync_update_scope(definition)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def prepare_sync_destroy
|
26
|
+
add_sync_action :destroy, self, default_scope: sync_default_scope
|
27
|
+
|
28
|
+
sync_scope_definitions.each do |definition|
|
29
|
+
scope = RenderSync::Scope.new_from_model(definition, self)
|
30
|
+
if scope.valid?
|
31
|
+
add_sync_action :destroy, self,
|
32
|
+
scope: scope,
|
33
|
+
default_scope: sync_default_scope
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Creates update actions for subscribers on the sync scope defined by
|
39
|
+
# the passed sync scope definition.
|
40
|
+
#
|
41
|
+
# It compares the state of the record in context of the sync scope before
|
42
|
+
# and after the update. If the record has been added to a scope, it
|
43
|
+
# publishes a new partial to the subscribers of that scope. It also sends
|
44
|
+
# a destroy action to subscribers of the scope, if the record has been
|
45
|
+
# removed from it.
|
46
|
+
#
|
47
|
+
def prepare_sync_update_scope(scope_definition)
|
48
|
+
# Add destroy action for the old scope (scope_before_update)
|
49
|
+
# if this record has left it
|
50
|
+
if left_old_scope?(scope_definition)
|
51
|
+
add_sync_action :destroy, record_before_update,
|
52
|
+
scope: scope_before_update(scope_definition),
|
53
|
+
default_scope: sync_default_scope
|
54
|
+
end
|
55
|
+
|
56
|
+
# Add new action for the new scope (scope_after_update) if this record has entered it
|
57
|
+
if entered_new_scope?(scope_definition)
|
58
|
+
add_sync_action :new, record_after_update,
|
59
|
+
scope: scope_after_update(scope_definition),
|
60
|
+
default_scope: sync_default_scope
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module RenderSync
|
2
|
+
module ModelTouching
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def prepare_sync_touches
|
7
|
+
sync_touches.each do |touch_association|
|
8
|
+
add_sync_action :update, touch_association
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Return the associations to be touched after a record change
|
13
|
+
# Takes into account that an association itself may have changed during
|
14
|
+
# an update call (e.g. project_id has changed). To accomplish this, it
|
15
|
+
# uses the stored record from before the update (@record_before_update)
|
16
|
+
# and touches that as well as the current association
|
17
|
+
#
|
18
|
+
def sync_touches
|
19
|
+
sync_associations = []
|
20
|
+
|
21
|
+
self.class.sync_touches.each do |touch|
|
22
|
+
current = send(touch)
|
23
|
+
sync_associations.push(current.reload) if current.present?
|
24
|
+
|
25
|
+
if @record_before_update.present?
|
26
|
+
previous = @record_before_update.send(touch)
|
27
|
+
sync_associations.push(previous.reload) if previous.present?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
sync_associations.uniq.compact
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module RenderSync
|
2
|
+
class Partial
|
3
|
+
attr_accessor :name, :resource, :context
|
4
|
+
|
5
|
+
def self.all(model, context, scope = nil)
|
6
|
+
resource = Resource.new(model, scope)
|
7
|
+
|
8
|
+
Dir["#{RenderSync.views_root}/#{resource.plural_name}/_*.*"].map do |partial|
|
9
|
+
partial_name = File.basename(partial)
|
10
|
+
Partial.new(partial_name[1...partial_name.index('.')], resource.model, scope, context)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.find(model, partial_name, context)
|
15
|
+
resource = Resource.new(model)
|
16
|
+
plural_name = resource.plural_name
|
17
|
+
partial = Dir["app/views/sync/#{plural_name}/_#{partial_name}.*"].first
|
18
|
+
return unless partial
|
19
|
+
Partial.new(partial_name, resource.model, nil, context)
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(name, resource, scope, context)
|
23
|
+
self.name = name
|
24
|
+
self.resource = Resource.new(resource, scope)
|
25
|
+
self.context = context
|
26
|
+
end
|
27
|
+
|
28
|
+
def render_to_string
|
29
|
+
context.render_to_string(partial: path, locals: locals, formats: [:html])
|
30
|
+
end
|
31
|
+
|
32
|
+
def render
|
33
|
+
context.render(partial: path, locals: locals, formats: [:html])
|
34
|
+
end
|
35
|
+
|
36
|
+
def sync(action)
|
37
|
+
message(action).publish
|
38
|
+
end
|
39
|
+
|
40
|
+
def message(action)
|
41
|
+
RenderSync.client.build_message channel_for_action(action),
|
42
|
+
html: (render_to_string unless action.to_s == "destroy")
|
43
|
+
end
|
44
|
+
|
45
|
+
def authorized?(auth_token)
|
46
|
+
self.auth_token == auth_token
|
47
|
+
end
|
48
|
+
|
49
|
+
def auth_token
|
50
|
+
@auth_token ||= Channel.new("#{polymorphic_path}-_#{name}").to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
# For the refetch feature we need an auth_token that wasn't created
|
54
|
+
# with scopes, because the scope information is not available on the
|
55
|
+
# refetch-request. So we create a refetch_auth_token which is based
|
56
|
+
# only on model_name and id plus the name of this partial
|
57
|
+
#
|
58
|
+
def refetch_auth_token
|
59
|
+
@refetch_auth_token ||= Channel.new("#{model_path}-_#{name}").to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
def channel_prefix
|
63
|
+
@channel_prefix ||= auth_token
|
64
|
+
end
|
65
|
+
|
66
|
+
def update_channel_prefix
|
67
|
+
@update_channel_prefix ||= refetch_auth_token
|
68
|
+
end
|
69
|
+
|
70
|
+
def channel_for_action(action)
|
71
|
+
case action
|
72
|
+
when :update
|
73
|
+
"#{update_channel_prefix}-#{action}"
|
74
|
+
else
|
75
|
+
"#{channel_prefix}-#{action}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def selector_start
|
80
|
+
"#{channel_prefix}-start"
|
81
|
+
end
|
82
|
+
|
83
|
+
def selector_end
|
84
|
+
"#{channel_prefix}-end"
|
85
|
+
end
|
86
|
+
|
87
|
+
def creator_for_scope(scope)
|
88
|
+
PartialCreator.new(name, resource.model, scope, context)
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def path
|
95
|
+
"sync/#{resource.plural_name}/#{name}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def locals
|
99
|
+
locals_hash = {}
|
100
|
+
locals_hash[resource.base_name.to_sym] = resource.model
|
101
|
+
locals_hash
|
102
|
+
end
|
103
|
+
|
104
|
+
def model_path
|
105
|
+
resource.model_path
|
106
|
+
end
|
107
|
+
|
108
|
+
def polymorphic_path
|
109
|
+
resource.polymorphic_path
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module RenderSync
|
2
|
+
class PartialCreator
|
3
|
+
attr_accessor :name, :resource, :context, :partial
|
4
|
+
|
5
|
+
def initialize(name, resource, scopes, context)
|
6
|
+
self.name = name
|
7
|
+
self.resource = Resource.new(resource, scopes)
|
8
|
+
self.context = context
|
9
|
+
self.partial = Partial.new(name, self.resource.model, scopes, context)
|
10
|
+
end
|
11
|
+
|
12
|
+
def auth_token
|
13
|
+
@auth_token ||= Channel.new("#{polymorphic_path}-_#{name}").to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def channel
|
17
|
+
@channel ||= auth_token
|
18
|
+
end
|
19
|
+
|
20
|
+
def selector
|
21
|
+
"#{channel}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def sync_new
|
25
|
+
message.publish
|
26
|
+
end
|
27
|
+
|
28
|
+
def message
|
29
|
+
RenderSync.client.build_message(channel,
|
30
|
+
html: partial.render_to_string,
|
31
|
+
resourceId: resource.id,
|
32
|
+
authToken: partial.auth_token,
|
33
|
+
channelUpdate: partial.channel_for_action(:update),
|
34
|
+
channelDestroy: partial.channel_for_action(:destroy),
|
35
|
+
selectorStart: partial.selector_start,
|
36
|
+
selectorEnd: partial.selector_end
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def polymorphic_path
|
44
|
+
resource.polymorphic_new_path
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module RenderSync
|
2
|
+
class Reactor
|
3
|
+
include MonitorMixin
|
4
|
+
|
5
|
+
# Execute EventMachine bound code block, waiting for reactor to start if
|
6
|
+
# not yet started or reactor thread has gone away
|
7
|
+
def perform
|
8
|
+
return EM.next_tick{ yield } if running?
|
9
|
+
cleanly_shutdown_reactor
|
10
|
+
condition = new_cond
|
11
|
+
Thread.new do
|
12
|
+
EM.run do
|
13
|
+
EM.next_tick do
|
14
|
+
synchronize do
|
15
|
+
condition.signal
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
synchronize do
|
21
|
+
condition.wait_until { EM.reactor_running? }
|
22
|
+
EM.next_tick { yield }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def stop
|
27
|
+
EM.stop if running?
|
28
|
+
end
|
29
|
+
|
30
|
+
def running?
|
31
|
+
EM.reactor_running? && EM.reactor_thread.alive?
|
32
|
+
end
|
33
|
+
|
34
|
+
# If the reactor's thread died, EM still thinks it's running but it isn't.
|
35
|
+
# This will happen if we forked from a process that had the reator running.
|
36
|
+
# Tell EM it's dead. Stolen from the EM internals
|
37
|
+
#
|
38
|
+
# https://groups.google.com/forum/#!msg/ruby-amqp/zchM4QzbZRE/I43wIjbgIv4J
|
39
|
+
#
|
40
|
+
def cleanly_shutdown_reactor
|
41
|
+
if EM.reactor_running?
|
42
|
+
EM.stop_event_loop
|
43
|
+
EM.release_machine
|
44
|
+
EM.instance_variable_set '@reactor_running', false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RenderSync
|
2
|
+
class RefetchModel
|
3
|
+
|
4
|
+
def self.find_by_class_name_and_id(resource_name, id)
|
5
|
+
class_name = resource_name.to_s.classify
|
6
|
+
class_name.safe_constantize.find(id) if supported_classes.include?(class_name)
|
7
|
+
rescue
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.supported_classes
|
12
|
+
Thread.current["sync_refetch_classes"] = nil if Rails.env.development?
|
13
|
+
|
14
|
+
Thread.current["sync_refetch_classes"] ||= begin
|
15
|
+
Dir["app/views/sync/*/refetch"].collect{|path|
|
16
|
+
File.basename(path.gsub(/\/refetch$/, '')).classify
|
17
|
+
}.reject{|clazz| clazz.nil? }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module RenderSync
|
2
|
+
class RefetchPartial < Partial
|
3
|
+
|
4
|
+
def self.all(model, context, scope = nil)
|
5
|
+
resource = Resource.new(model)
|
6
|
+
|
7
|
+
Dir["#{RenderSync.views_root}/#{resource.plural_name}/refetch/_*.*"].map do |partial|
|
8
|
+
partial_name = File.basename(partial)
|
9
|
+
RefetchPartial.new(partial_name[1...partial_name.index('.')], resource.model, scope, context)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.find(model, partial_name, context)
|
14
|
+
resource = Resource.new(model)
|
15
|
+
plural_name = resource.plural_name
|
16
|
+
partial = Dir["#{RenderSync.views_root}/#{plural_name}/refetch/_#{partial_name}.*"].first
|
17
|
+
return unless partial
|
18
|
+
RefetchPartial.new(partial_name, resource.model, nil, context)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.find_by_authorized_resource(model, partial_name, context, auth_token)
|
22
|
+
partial = find(model, partial_name, context)
|
23
|
+
return unless partial && partial.authorized?(auth_token)
|
24
|
+
|
25
|
+
partial
|
26
|
+
end
|
27
|
+
|
28
|
+
def message(action)
|
29
|
+
RenderSync.client.build_message channel_for_action(action), refetch: true
|
30
|
+
end
|
31
|
+
|
32
|
+
def creator_for_scope(scope)
|
33
|
+
RefetchPartialCreator.new(name, resource.model, scope, context)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def path
|
40
|
+
"sync/#{resource.plural_name}/refetch/#{name}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|