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,77 @@
|
|
1
|
+
module RenderSync
|
2
|
+
module Clients
|
3
|
+
class Pusher
|
4
|
+
|
5
|
+
def setup
|
6
|
+
require 'pusher'
|
7
|
+
::Pusher.app_id = RenderSync.app_id
|
8
|
+
::Pusher.key = RenderSync.api_key
|
9
|
+
::Pusher.secret = RenderSync.auth_token
|
10
|
+
|
11
|
+
if RenderSync.pusher_api_scheme
|
12
|
+
::Pusher.scheme = RenderSync.pusher_api_scheme
|
13
|
+
end
|
14
|
+
|
15
|
+
if RenderSync.pusher_api_host
|
16
|
+
::Pusher.host = RenderSync.pusher_api_host
|
17
|
+
end
|
18
|
+
|
19
|
+
if RenderSync.pusher_api_port
|
20
|
+
::Pusher.port = RenderSync.pusher_api_port
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def batch_publish(*args)
|
25
|
+
Message.batch_publish(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_message(*args)
|
29
|
+
Message.new(*args)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Public: Normalize channel to adapter supported format
|
33
|
+
#
|
34
|
+
# channel - The string channel name
|
35
|
+
#
|
36
|
+
# Returns The normalized channel prefixed with supported format for Pusher
|
37
|
+
def normalize_channel(channel)
|
38
|
+
channel
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
class Message
|
43
|
+
|
44
|
+
attr_accessor :channel, :data
|
45
|
+
|
46
|
+
def self.batch_publish(messages)
|
47
|
+
messages.each do |message|
|
48
|
+
message.publish
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def initialize(channel, data)
|
53
|
+
self.channel = channel
|
54
|
+
self.data = data
|
55
|
+
end
|
56
|
+
|
57
|
+
def publish
|
58
|
+
if RenderSync.async?
|
59
|
+
publish_asynchronous
|
60
|
+
else
|
61
|
+
publish_synchronous
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def publish_synchronous
|
66
|
+
::Pusher.trigger([channel], 'sync', data)
|
67
|
+
end
|
68
|
+
|
69
|
+
def publish_asynchronous
|
70
|
+
RenderSync.reactor.perform do
|
71
|
+
::Pusher.trigger_async([channel], 'sync', data)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RenderSync
|
2
|
+
|
3
|
+
module ControllerHelpers
|
4
|
+
|
5
|
+
include Actions
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def enable_sync(options = {})
|
13
|
+
around_filter :enable_sync, options
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def enable_sync
|
21
|
+
RenderSync::Model.enable(sync_render_context) do
|
22
|
+
yield
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# ControllerHelpers overrides Action#sync_render_context to use self as
|
27
|
+
# context to allow full access to request/response cycle
|
28
|
+
# over default abstract Renderer class
|
29
|
+
def sync_render_context
|
30
|
+
self
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module RenderSync
|
2
|
+
|
3
|
+
class Engine < Rails::Engine
|
4
|
+
# Loads the sync.yml file if it exists.
|
5
|
+
initializer "sync.config", group: :all do
|
6
|
+
path = Rails.root.join("config/sync.yml")
|
7
|
+
RenderSync.load_config(path, Rails.env) if path.exist?
|
8
|
+
end
|
9
|
+
|
10
|
+
initializer "sync.activerecord" do
|
11
|
+
ActiveRecord::Base.send :extend, Model::ClassMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
# Adds the ViewHelpers into ActionView::Base
|
15
|
+
initializer "sync.view_helpers" do
|
16
|
+
ActionView::Base.send :include, ViewHelpers
|
17
|
+
end
|
18
|
+
|
19
|
+
# Adds the ControllerHelpers into ActionConroller::Base
|
20
|
+
initializer "sync.controller_helpers" do
|
21
|
+
ActionController::Base.send :include, RenderSync::ControllerHelpers
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RenderSync
|
2
|
+
tracker_class = nil
|
3
|
+
begin
|
4
|
+
require 'action_view/dependency_tracker'
|
5
|
+
tracker_class = ActionView::DependencyTracker::ERBTracker
|
6
|
+
rescue LoadError
|
7
|
+
begin
|
8
|
+
require 'cache_digests/dependency_tracker'
|
9
|
+
tracker_class = CacheDigests::DependencyTracker::ERBTracker
|
10
|
+
rescue LoadError
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if tracker_class
|
15
|
+
class ERBTracker < tracker_class
|
16
|
+
# Matches:
|
17
|
+
# sync partial: "comment", collection: commentable.comments
|
18
|
+
# sync partial: "comment", resource: comment
|
19
|
+
SYNC_DEPENDENCY = /
|
20
|
+
sync(?:_new)?\s* # sync or sync_new, followed by optional whitespace
|
21
|
+
\(?\s* # start an optional parenthesis for the sync call
|
22
|
+
(?:partial:|:partial\s+=>)\s* # naming the partial, used with collection
|
23
|
+
["']([a-z][a-z_\/]+)["']\s* # the template name itself -- 1st capture
|
24
|
+
,\s* # comma separating parameters
|
25
|
+
:?(?:resource|collection)(?::|\s+=>)\s* # resource or collection identifier
|
26
|
+
@?(?:[a-z]+\.)*([a-z]+) # the resource or collection itself -- 2nd capture
|
27
|
+
/x
|
28
|
+
|
29
|
+
def self.call(name, template)
|
30
|
+
new(name, template).dependencies
|
31
|
+
end
|
32
|
+
|
33
|
+
def dependencies
|
34
|
+
(sync_dependencies + super).uniq
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def source
|
40
|
+
template.source
|
41
|
+
end
|
42
|
+
|
43
|
+
def sync_dependencies
|
44
|
+
source.scan(SYNC_DEPENDENCY).
|
45
|
+
collect { |template, resource| "sync/#{resource.pluralize}/#{template}" }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module RenderSync
|
2
|
+
class FayeExtension
|
3
|
+
|
4
|
+
def incoming(message, callback)
|
5
|
+
return handle_eror(message, callback) unless message_authenticated?(message)
|
6
|
+
if batch_publish?(message)
|
7
|
+
batch_incoming(message, callback)
|
8
|
+
else
|
9
|
+
single_incoming(message, callback)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def batch_incoming(message, callback)
|
14
|
+
message["data"].each do |message|
|
15
|
+
incoming(message, callback)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def single_incoming(message, callback)
|
20
|
+
callback.call(message)
|
21
|
+
end
|
22
|
+
|
23
|
+
def batch_publish?(message)
|
24
|
+
message['channel'] == "/batch_publish"
|
25
|
+
end
|
26
|
+
|
27
|
+
# IMPORTANT: clear out the auth token so it is not leaked to the client
|
28
|
+
def outgoing(message, callback)
|
29
|
+
if message['ext'] && message['ext']['auth_token']
|
30
|
+
message['ext'] = {}
|
31
|
+
end
|
32
|
+
callback.call(message)
|
33
|
+
end
|
34
|
+
|
35
|
+
def handle_eror(message, callback)
|
36
|
+
message['error'] = 'Invalid authentication token'
|
37
|
+
callback.call(message)
|
38
|
+
end
|
39
|
+
|
40
|
+
def message_authenticated?(message)
|
41
|
+
!(message['channel'] !~ %r{^/meta/} &&
|
42
|
+
message['ext']['auth_token'] != RenderSync.auth_token)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
module RenderSync
|
2
|
+
module Model
|
3
|
+
|
4
|
+
def self.enabled?
|
5
|
+
Thread.current["model_sync_enabled"]
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.context
|
9
|
+
Thread.current["model_sync_context"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.enable!(context = nil)
|
13
|
+
Thread.current["model_sync_enabled"] = true
|
14
|
+
Thread.current["model_sync_context"] = context
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.disable!
|
18
|
+
Thread.current["model_sync_enabled"] = false
|
19
|
+
Thread.current["model_sync_context"] = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.enable(context = nil)
|
23
|
+
enable!(context)
|
24
|
+
yield
|
25
|
+
ensure
|
26
|
+
disable!
|
27
|
+
end
|
28
|
+
|
29
|
+
module ClassMethods
|
30
|
+
attr_accessor :sync_default_scope, :sync_scope_definitions, :sync_touches
|
31
|
+
|
32
|
+
# Set up automatic syncing of partials when a record of this class is
|
33
|
+
# created, updated or deleted. Be sure to wrap your model actions inside
|
34
|
+
# a sync_enable block for sync to do its magic.
|
35
|
+
#
|
36
|
+
def sync(*actions)
|
37
|
+
include ModelActions unless include?(ModelActions)
|
38
|
+
include ModelChangeTracking unless include?(ModelChangeTracking)
|
39
|
+
include ModelRenderSyncing
|
40
|
+
|
41
|
+
if actions.last.is_a? Hash
|
42
|
+
@sync_default_scope = actions.last.fetch :default_scope
|
43
|
+
end
|
44
|
+
|
45
|
+
actions = [:create, :update, :destroy] if actions.include? :all
|
46
|
+
actions.flatten!
|
47
|
+
|
48
|
+
if actions.include? :create
|
49
|
+
after_create :prepare_sync_create, if: -> { RenderSync::Model.enabled? }
|
50
|
+
end
|
51
|
+
|
52
|
+
if actions.include? :update
|
53
|
+
after_update :prepare_sync_update, if: -> { RenderSync::Model.enabled? }
|
54
|
+
end
|
55
|
+
|
56
|
+
if actions.include? :destroy
|
57
|
+
after_destroy :prepare_sync_destroy, if: -> { RenderSync::Model.enabled? }
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
# Set up a sync scope for the model defining a set of records to be
|
63
|
+
# updated via sync
|
64
|
+
#
|
65
|
+
# name - The name of the scope
|
66
|
+
# lambda - A lambda defining the scope.
|
67
|
+
# Has to return an ActiveRecord::Relation.
|
68
|
+
#
|
69
|
+
# You can define the lambda with arguments (see examples).
|
70
|
+
# Note that the naming of the parameters is very important. Only use
|
71
|
+
# names of methods or ActiveRecord attributes defined on the model (e.g.
|
72
|
+
# user_id). This way sync will be able to pass changed records to the
|
73
|
+
# lambda and track changes to the scope.
|
74
|
+
#
|
75
|
+
# Example:
|
76
|
+
#
|
77
|
+
# class Todo < ActiveRecord::Base
|
78
|
+
# belongs_to :user
|
79
|
+
# belongs_to :project
|
80
|
+
# scope :incomplete, -> { where(complete: false) }
|
81
|
+
#
|
82
|
+
# sync :all
|
83
|
+
#
|
84
|
+
# sync_scope :complete, -> { where(complete: true) }
|
85
|
+
# sync_scope :by_project, ->(project_id) { where(project_id: project_id) }
|
86
|
+
# sync_scope :my_incomplete_todos, ->(user) { incomplete.where(user_id: user.id) }
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# To subscribe to these scopes you would put these lines into your views:
|
90
|
+
#
|
91
|
+
# <%= sync partial: "todo", collection: @todos, scope: Todo.complete %>
|
92
|
+
#
|
93
|
+
# If the collection you want to render is exactly defined be the given
|
94
|
+
# scope the scope can be omitted:
|
95
|
+
#
|
96
|
+
# <%= sync partial: "todo", collection: Todo.complete %>
|
97
|
+
#
|
98
|
+
# For rendering my_incomplete_todos:
|
99
|
+
#
|
100
|
+
# <%= sync partial: "todo", collection: Todo.my_incomplete_todos(current_user) %>
|
101
|
+
#
|
102
|
+
# The render_new call has to look like this:
|
103
|
+
#
|
104
|
+
# <%= sync_new partial: "todo", resource: Todo.new, scope: Todo.complete %>
|
105
|
+
#
|
106
|
+
# Now when a record changes sync will use the names of the lambda
|
107
|
+
# parameters (project_id and user), get the corresponding attributes from
|
108
|
+
# the record (project_id column or user association) and pass it to the
|
109
|
+
# lambda. This way sync can identify if a record has been added or
|
110
|
+
# removed from a scope and will then publish the changes to subscribers
|
111
|
+
# on all scoped channels.
|
112
|
+
#
|
113
|
+
# Beware that chaining of sync scopes in the view is currently not
|
114
|
+
# possible. So the following example would raise an exception:
|
115
|
+
#
|
116
|
+
# <%= sync_new partial: "todo", Todo.new, scope: Todo.mine(current_user).incomplete %>
|
117
|
+
#
|
118
|
+
# To work around this just create an explicit sync_scope for your problem:
|
119
|
+
#
|
120
|
+
# sync_scope :my_incomplete_todos, ->(user) { incomplete.mine(current_user) }
|
121
|
+
#
|
122
|
+
# And in the view:
|
123
|
+
#
|
124
|
+
# <%= sync_new partial: "todo", Todo.new, scope: Todo.my_incomplete_todos(current_user) %>
|
125
|
+
#
|
126
|
+
def sync_scope(name, lambda)
|
127
|
+
if self.respond_to?(name)
|
128
|
+
raise ArgumentError, "invalid scope name '#{name}'. Already defined on #{self.name}"
|
129
|
+
end
|
130
|
+
|
131
|
+
@sync_scope_definitions[name] = RenderSync::ScopeDefinition.new(self, name, lambda)
|
132
|
+
|
133
|
+
singleton_class.send(:define_method, name) do |*args|
|
134
|
+
RenderSync::Scope.new_from_args(@sync_scope_definitions[name], args)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Register one or more associations to be sync'd when this record changes.
|
139
|
+
#
|
140
|
+
# Example:
|
141
|
+
#
|
142
|
+
# class Todo < ActiveRecord::Base
|
143
|
+
# belongs_to :project
|
144
|
+
# belongs_to :user
|
145
|
+
#
|
146
|
+
# sync :all
|
147
|
+
# sync_touch :project, :user
|
148
|
+
# end
|
149
|
+
#
|
150
|
+
def sync_touch(*args)
|
151
|
+
# Only load Modules and set up callbacks if sync_touch wasn't
|
152
|
+
# called before
|
153
|
+
if @sync_touches.blank?
|
154
|
+
include ModelActions unless include?(ModelActions)
|
155
|
+
include ModelChangeTracking unless include?(ModelChangeTracking)
|
156
|
+
include ModelTouching
|
157
|
+
|
158
|
+
@sync_touches ||= []
|
159
|
+
|
160
|
+
after_create :prepare_sync_touches, if: -> { RenderSync::Model.enabled? }
|
161
|
+
after_update :prepare_sync_touches, if: -> { RenderSync::Model.enabled? }
|
162
|
+
after_destroy :prepare_sync_touches, if: -> { RenderSync::Model.enabled? }
|
163
|
+
end
|
164
|
+
|
165
|
+
options = args.extract_options!
|
166
|
+
args.each do |arg|
|
167
|
+
@sync_touches.push(arg)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module RenderSync
|
2
|
+
module ModelActions
|
3
|
+
# Set up instance variable holding the collected sync actions
|
4
|
+
# to be published later on.
|
5
|
+
#
|
6
|
+
attr_accessor :sync_actions
|
7
|
+
|
8
|
+
# Set up ActiveRecord callbacks to prepare for collecting
|
9
|
+
# publish sync actions and publishing them after commit
|
10
|
+
#
|
11
|
+
def self.included(base)
|
12
|
+
base.class_eval do
|
13
|
+
@sync_scope_definitions ||= {}
|
14
|
+
|
15
|
+
before_create :prepare_sync_actions, if: -> { RenderSync::Model.enabled? }
|
16
|
+
before_update :prepare_sync_actions, if: -> { RenderSync::Model.enabled? }
|
17
|
+
before_destroy :prepare_sync_actions, if: -> { RenderSync::Model.enabled? }
|
18
|
+
|
19
|
+
after_commit :publish_sync_actions, if: -> { RenderSync::Model.enabled? }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def sync_default_scope
|
24
|
+
return nil unless self.class.sync_default_scope
|
25
|
+
send self.class.sync_default_scope
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def sync_render_context
|
31
|
+
RenderSync::Model.context || super
|
32
|
+
end
|
33
|
+
|
34
|
+
def prepare_sync_actions
|
35
|
+
self.sync_actions = []
|
36
|
+
end
|
37
|
+
|
38
|
+
# Add a new aync action to the list of actions to be published later on
|
39
|
+
#
|
40
|
+
def add_sync_action(action_name, record, options = {})
|
41
|
+
sync_actions.push(Action.new(record, action_name, options))
|
42
|
+
end
|
43
|
+
|
44
|
+
# Run the collected actions on after_commit callback
|
45
|
+
# Triggers the syncing of the partials
|
46
|
+
#
|
47
|
+
def publish_sync_actions
|
48
|
+
sync_actions.each(&:perform)
|
49
|
+
end
|
50
|
+
|
51
|
+
def sync_scope_definitions
|
52
|
+
self.class.sync_scope_definitions.values
|
53
|
+
end
|
54
|
+
|
55
|
+
def sync_render_context
|
56
|
+
RenderSync::Model.context || super
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|