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,21 @@
|
|
1
|
+
module RenderSync
|
2
|
+
class RefetchPartialCreator < PartialCreator
|
3
|
+
|
4
|
+
def initialize(name, resource, scoped_resource, context)
|
5
|
+
super
|
6
|
+
self.partial = RefetchPartial.new(name, self.resource.model, nil, context)
|
7
|
+
end
|
8
|
+
|
9
|
+
def message
|
10
|
+
RenderSync.client.build_message(channel,
|
11
|
+
refetch: true,
|
12
|
+
resourceId: resource.id,
|
13
|
+
authToken: partial.auth_token,
|
14
|
+
channelUpdate: partial.channel_for_action(:update),
|
15
|
+
channelDestroy: partial.channel_for_action(:destroy),
|
16
|
+
selectorStart: partial.selector_start,
|
17
|
+
selectorEnd: partial.selector_end
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RenderSync
|
2
|
+
class Renderer
|
3
|
+
|
4
|
+
attr_accessor :context
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
self.context = ApplicationController.new.view_context
|
8
|
+
self.context.instance_eval do
|
9
|
+
def url_options
|
10
|
+
ActionMailer::Base.default_url_options
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def render_to_string(options)
|
16
|
+
context.render(options)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module RenderSync
|
4
|
+
class Resource
|
5
|
+
attr_accessor :model, :scopes
|
6
|
+
|
7
|
+
# Constructor
|
8
|
+
#
|
9
|
+
# model - The ActiveModel instace for this Resource
|
10
|
+
# scopes - The optional scopes to prefix polymorphic paths with.
|
11
|
+
# Can be a Symbol/String, a parent model or an RenderSync::Scope
|
12
|
+
# or an Array with any combination.
|
13
|
+
#
|
14
|
+
# Examples
|
15
|
+
#
|
16
|
+
# class User < ActiveRecord::Base
|
17
|
+
# sync :all
|
18
|
+
# sync_scope :cool, -> { where(cool: true) }
|
19
|
+
# sync_scope :in_group, ->(group) { where(group_id: group.id) }
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# user = User.find(1)
|
23
|
+
#
|
24
|
+
# resource = Resource.new(user)
|
25
|
+
# resource.polymorphic_path => "/users/1"
|
26
|
+
# resource.polymorphic_new_path => "/users/new"
|
27
|
+
#
|
28
|
+
# resource = Resource.new(user, :admin)
|
29
|
+
# resource.polymorphic_path => "/admin/users/1"
|
30
|
+
# resource.polymorphic_new_path => "/admin/users/new"
|
31
|
+
#
|
32
|
+
# resource = Resource.new(user, [:staff, :restricted])
|
33
|
+
# resource.polymorphic_path => "/staff/restricted/users/1"
|
34
|
+
# resource.polymorphic_new_path => "/staff/restricted/users/new"
|
35
|
+
#
|
36
|
+
# resource = Resource.new(user, project)
|
37
|
+
# resource.polymorphic_path => "/projects/2/users/1"
|
38
|
+
# resource.polymorphic_new_path => "/projects/2/users/new"
|
39
|
+
#
|
40
|
+
# resource = Resource.new(user, User.cool)
|
41
|
+
# resource.polymorphic_path => "/cool/users/2"
|
42
|
+
# resource.polymorphic_new_path => "/cool/users/new"
|
43
|
+
#
|
44
|
+
# resource = Resource.new(user, User.in_group(group))
|
45
|
+
# resource.polymorphic_path => "/in_group/group/3/users/2"
|
46
|
+
# resource.polymorphic_new_path => "/in_group/group/3/users/new"
|
47
|
+
#
|
48
|
+
# resource = Resource.new(user, [:admin, User.cool, User.in_group(group)])
|
49
|
+
# resource.polymorphic_path => "admin/cool/in_group/group/3/users/2"
|
50
|
+
# resource.polymorphic_new_path => "admin/cool/in_group/group/3/users/new"
|
51
|
+
#
|
52
|
+
# resource = Resource.new(user, [:admin, project])
|
53
|
+
# resource.polymorphic_path => "/admin/projects/2/users/1"
|
54
|
+
# resource.polymorphic_new_path => "/admin/projects/2/users/new"
|
55
|
+
#
|
56
|
+
def initialize(model, scopes = nil)
|
57
|
+
self.model = model
|
58
|
+
self.scopes = scopes
|
59
|
+
end
|
60
|
+
|
61
|
+
def scopes=(new_scopes)
|
62
|
+
new_scopes = [new_scopes] unless new_scopes.nil? or new_scopes.is_a? Array
|
63
|
+
@scopes = new_scopes
|
64
|
+
end
|
65
|
+
|
66
|
+
def id
|
67
|
+
model.id
|
68
|
+
end
|
69
|
+
|
70
|
+
def name
|
71
|
+
model.class.model_name.to_s.underscore
|
72
|
+
end
|
73
|
+
|
74
|
+
def base_name
|
75
|
+
name.split('/').last
|
76
|
+
end
|
77
|
+
|
78
|
+
def plural_name
|
79
|
+
name.pluralize
|
80
|
+
end
|
81
|
+
|
82
|
+
def scopes_path
|
83
|
+
path = Pathname.new('/')
|
84
|
+
unless scopes.nil?
|
85
|
+
paths = scopes.map do |scope|
|
86
|
+
if scope.is_a?(RenderSync::Scope)
|
87
|
+
scope.polymorphic_path.relative_path_from(path)
|
88
|
+
elsif scope.class.respond_to? :model_name
|
89
|
+
Resource.new(scope).polymorphic_path.relative_path_from(path)
|
90
|
+
else
|
91
|
+
scope.to_s
|
92
|
+
end
|
93
|
+
end
|
94
|
+
path = path.join(*paths)
|
95
|
+
end
|
96
|
+
path
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns an unscoped Pathname for the model (e.g. /users/1)
|
100
|
+
def model_path
|
101
|
+
Pathname.new('/').join(plural_name, id.to_s)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns the scoped Pathname for the model (e.g. /users/1/todos/2)
|
105
|
+
def polymorphic_path
|
106
|
+
scopes_path.join(plural_name, id.to_s)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Returns the scoped Pathname for a new model (e.g. /users/1/todos/new)
|
110
|
+
def polymorphic_new_path
|
111
|
+
scopes_path.join(plural_name, "new")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module RenderSync
|
2
|
+
class Scope
|
3
|
+
attr_accessor :scope_definition, :args, :valid
|
4
|
+
|
5
|
+
def initialize(scope_definition, args)
|
6
|
+
@scope_definition = scope_definition
|
7
|
+
@args = args
|
8
|
+
end
|
9
|
+
|
10
|
+
# Return a new sync scope by passing a scope definition (containing a lambda and parameter names)
|
11
|
+
# and a set of arguments to be handed over to the lambda
|
12
|
+
def self.new_from_args(scope_definition, args)
|
13
|
+
if args.length != scope_definition.parameters.length
|
14
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for #{scope_definition.parameters.length})"
|
15
|
+
end
|
16
|
+
|
17
|
+
# Classes currently supported as Arguments for the sync scope lambda
|
18
|
+
supported_arg_types = [Fixnum, Integer, ActiveRecord::Base]
|
19
|
+
|
20
|
+
# Check passed args for types. Raise ArgumentError if arg class is not supported
|
21
|
+
args.each_with_index do |arg, i|
|
22
|
+
|
23
|
+
unless supported_arg_types.find { |klass| break true if arg.is_a?(klass) }
|
24
|
+
param = scope_definition.parameters[i]
|
25
|
+
raise ArgumentError, "invalid argument '#{param}' (#{arg.class.name}). Currently only #{supported_arg_types.map(&:name).join(", ")} are supported"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
new(scope_definition, args)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return a new sync scope by passing a scope definition (containing a lambda and parameter names)
|
33
|
+
# and an ActiveRecord model object. The args List will be filled with the model attributes
|
34
|
+
# corrensponding to the parameter names defined in the scope_definition
|
35
|
+
def self.new_from_model(scope_definition, model)
|
36
|
+
new(scope_definition, scope_definition.parameters.map { |p| model.send(p) })
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return the ActiveRecord Relation by calling the lamda with the given args.
|
40
|
+
#
|
41
|
+
def relation
|
42
|
+
scope_definition.lambda.call(*args)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Check if the combination of stored AR relation and args is valid by calling exists? on it.
|
46
|
+
# This may raise an exception depending on the args, so we have to rescue the block
|
47
|
+
#
|
48
|
+
def valid?
|
49
|
+
@valid ||= begin
|
50
|
+
relation.exists?
|
51
|
+
true # set valid to true, if relation.exists?(model) does not throw any exception
|
52
|
+
rescue
|
53
|
+
false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def invalid?
|
58
|
+
!valid?
|
59
|
+
end
|
60
|
+
|
61
|
+
# Check if the given record falls under the narrowing by the stored ActiveRecord Relation.
|
62
|
+
# Depending on the arguments set in args this can lead to an exception (e.g. when a nil is passed)
|
63
|
+
# Also set the value of valid to avoid another DB query.
|
64
|
+
#
|
65
|
+
def contains?(record)
|
66
|
+
begin
|
67
|
+
val = relation.exists?(record.id)
|
68
|
+
@valid = true # set valid to true, if relation.exists?(model) does not throw any exception
|
69
|
+
val
|
70
|
+
rescue
|
71
|
+
@valid = false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Generates an Array of path elements based on the given lambda args and their
|
76
|
+
# name which is saved in scope_definition.parameters
|
77
|
+
#
|
78
|
+
def args_path
|
79
|
+
scope_definition.parameters.each_with_index.map do |parameter, i|
|
80
|
+
if args[i].is_a? ActiveRecord::Base
|
81
|
+
[parameter.to_s, args[i].send(args[i].class.primary_key).to_s]
|
82
|
+
else
|
83
|
+
[parameter.to_s, args[i].to_s]
|
84
|
+
end
|
85
|
+
end.flatten
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the Pathname for this scope
|
89
|
+
# Example:
|
90
|
+
# class User < ActiveRecord::Base
|
91
|
+
# sync :all
|
92
|
+
# belongs_to :group
|
93
|
+
# sync_scope :in_group, ->(group) { where(group_id: group.id) }
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# group = Group.first
|
97
|
+
# User.in_group(group).polymorphic_path.to_s
|
98
|
+
# # => "/in_group/group/1"
|
99
|
+
#
|
100
|
+
def polymorphic_path
|
101
|
+
Pathname.new('/').join(*([scope_definition.name.to_s, args_path].flatten))
|
102
|
+
end
|
103
|
+
|
104
|
+
# Delegate all undefined methods to the relation, so that
|
105
|
+
# the scope behaves like an ActiveRecord::Relation, e.g. call count
|
106
|
+
# on the relation (User.in_group(group).count)
|
107
|
+
#
|
108
|
+
def method_missing(method, *args, &block)
|
109
|
+
relation.send(method, *args, &block)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RenderSync
|
2
|
+
class ScopeDefinition
|
3
|
+
attr_accessor :klass, :name, :lambda, :parameters, :args
|
4
|
+
|
5
|
+
def initialize(klass, name, lambda)
|
6
|
+
self.class.ensure_valid_params!(klass, lambda)
|
7
|
+
|
8
|
+
@klass = klass
|
9
|
+
@name = name
|
10
|
+
@lambda = lambda
|
11
|
+
@parameters = lambda.parameters.map { |p| p[1] }
|
12
|
+
end
|
13
|
+
|
14
|
+
# Checks the validity of the parameter names contained in the lambda definition.
|
15
|
+
# E.g. if the lambda looks like this:
|
16
|
+
#
|
17
|
+
# ->(user) { where(user_id: user.id) }
|
18
|
+
#
|
19
|
+
# The name of the passed argument (user) must be present as a column name or an
|
20
|
+
# instance method (e.g. an association) of the ActiveRecord object.
|
21
|
+
#
|
22
|
+
def self.ensure_valid_params!(klass, lambda)
|
23
|
+
unless (invalid = lambda.parameters.map { |p| p[1] } - klass.column_names.map(&:to_sym) - klass.instance_methods) == []
|
24
|
+
raise ArgumentError, "Invalid parameters #{invalid}. Parameter names of the sync_scope lambda definition may only contain ActiveRecord column names or instance methods of #{klass.name}."
|
25
|
+
end
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module RenderSync
|
2
|
+
|
3
|
+
module ViewHelpers
|
4
|
+
|
5
|
+
# Surround partial render in script tags, watching for
|
6
|
+
# sync_update and sync_destroy channels from pubsub server
|
7
|
+
#
|
8
|
+
# options - The Hash of options
|
9
|
+
# partial - The String partial filename without leading underscore
|
10
|
+
# resource - The ActiveModel resource
|
11
|
+
# collection - The Array of ActiveModel resources to use in place of
|
12
|
+
# single resource
|
13
|
+
#
|
14
|
+
# Examples
|
15
|
+
# <%= sync partial: 'todo', resource: todo %>
|
16
|
+
# <%= sync partial: 'todo', collection: todos %>
|
17
|
+
#
|
18
|
+
def sync(options = {})
|
19
|
+
collection = options[:collection] || [options.fetch(:resource)]
|
20
|
+
scope = options[:channel] || options[:scope] || (collection.is_a?(RenderSync::Scope) ? collection : nil)
|
21
|
+
partial_name = options.fetch(:partial, scope)
|
22
|
+
refetch = options.fetch(:refetch, false)
|
23
|
+
|
24
|
+
results = []
|
25
|
+
collection.each do |resource|
|
26
|
+
if refetch
|
27
|
+
partial = RefetchPartial.new(partial_name, resource, scope, self)
|
28
|
+
else
|
29
|
+
partial = Partial.new(partial_name, resource, scope, self)
|
30
|
+
end
|
31
|
+
results << "
|
32
|
+
<script type='text/javascript' data-sync-id='#{partial.selector_start}'>
|
33
|
+
RenderSync.onReady(function(){
|
34
|
+
var partial = new RenderSync.Partial({
|
35
|
+
name: '#{partial.name}',
|
36
|
+
resourceName: '#{partial.resource.name}',
|
37
|
+
resourceId: '#{resource.id}',
|
38
|
+
authToken: '#{partial.refetch_auth_token}',
|
39
|
+
channelUpdate: '#{partial.channel_for_action(:update)}',
|
40
|
+
channelDestroy: '#{partial.channel_for_action(:destroy)}',
|
41
|
+
selectorStart: '#{partial.selector_start}',
|
42
|
+
selectorEnd: '#{partial.selector_end}',
|
43
|
+
refetch: #{refetch}
|
44
|
+
});
|
45
|
+
partial.subscribe();
|
46
|
+
});
|
47
|
+
</script>
|
48
|
+
".squish.html_safe
|
49
|
+
results << partial.render
|
50
|
+
results << "
|
51
|
+
<script type='text/javascript' data-sync-id='#{partial.selector_end}'>
|
52
|
+
</script>
|
53
|
+
".squish.html_safe
|
54
|
+
end
|
55
|
+
|
56
|
+
safe_join(results)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Setup listener for new resource from sync_new channel, appending
|
60
|
+
# partial in place
|
61
|
+
#
|
62
|
+
# options - The Hash of options
|
63
|
+
# partial - The String partial filename without leading underscore
|
64
|
+
# resource - The ActiveModel resource
|
65
|
+
# scope - The ActiveModel resource to scope the new channel publishes to.
|
66
|
+
# Used for restricting new resource publishes to 'owner' models.
|
67
|
+
# ie, current_user, project, group, etc. When excluded, listens
|
68
|
+
# for global resource creates.
|
69
|
+
#
|
70
|
+
# direction - The String/Symbol direction to insert rendered partials.
|
71
|
+
# One of :append, :prepend. Defaults to :append
|
72
|
+
#
|
73
|
+
# Examples
|
74
|
+
# <%= sync_new partial: 'todo', resource: Todo.new, scope: @project %>
|
75
|
+
# <%= sync_new partial: 'todo', resource: Todo.new, scope: @project, direction: :prepend %>
|
76
|
+
#
|
77
|
+
def sync_new(options = {})
|
78
|
+
partial_name = options.fetch(:partial)
|
79
|
+
scope = options[:scope]
|
80
|
+
direction = options.fetch :direction, 'append'
|
81
|
+
refetch = options.fetch(:refetch, false)
|
82
|
+
resource = scope.is_a?(RenderSync::Scope) ? scope.new : options.fetch(:resource)
|
83
|
+
|
84
|
+
if refetch
|
85
|
+
creator = RefetchPartialCreator.new(partial_name, resource, scope, self)
|
86
|
+
else
|
87
|
+
creator = PartialCreator.new(partial_name, resource, scope, self)
|
88
|
+
end
|
89
|
+
"
|
90
|
+
<script type='text/javascript' data-sync-id='#{creator.selector}'>
|
91
|
+
RenderSync.onReady(function(){
|
92
|
+
var creator = new RenderSync.PartialCreator({
|
93
|
+
name: '#{partial_name}',
|
94
|
+
resourceName: '#{creator.resource.name}',
|
95
|
+
channel: '#{creator.channel}',
|
96
|
+
selector: '#{creator.selector}',
|
97
|
+
direction: '#{direction}',
|
98
|
+
refetch: #{refetch}
|
99
|
+
});
|
100
|
+
creator.subscribe();
|
101
|
+
});
|
102
|
+
</script>
|
103
|
+
".html_safe
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|
data/test/dummy/Rakefile
ADDED