roda-component 0.0.5 → 0.0.6
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/lib/roda/component/faye.rb +100 -25
- data/lib/roda/component/instance.rb +3 -3
- data/lib/roda/component/models/channel.rb +11 -0
- data/lib/roda/component/models/user.rb +12 -0
- data/lib/roda/component/ohm.rb +8 -0
- data/lib/roda/component/version.rb +1 -1
- data/lib/roda/component.rb +68 -7
- data/lib/roda/plugins/component.rb +39 -48
- data/roda-component.gemspec +3 -0
- metadata +47 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a0aee4b44c06ddda8a7f16cadc0ab4f36cb8bdf
|
4
|
+
data.tar.gz: 3b43bcaccdcd4946f8e4cabcfabb9eae516c5d88
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd9fad6927044e7d4bf367ee524c68c4c600c93a3e93a26af8d5996d0669b7edecdf4d91f6c28ee47ba93b2160b8d63e7f9fc2eafb7d02ced7bd4e7b341a087f
|
7
|
+
data.tar.gz: e7c055e597beccfd745f60a08b8cd56947e2d5613aa93d97427e2f033cd9fb95aef33a6b4aaa9c7e6ec6b39d886fa991065d207475fe982dcca64b6b127f5db5
|
data/lib/roda/component/faye.rb
CHANGED
@@ -6,32 +6,79 @@ if RUBY_ENGINE == 'opal'
|
|
6
6
|
class Faye
|
7
7
|
include Native
|
8
8
|
|
9
|
-
def initialize url
|
10
|
-
super `new Faye.Client(#{url})`
|
11
|
-
end
|
12
|
-
|
13
9
|
alias_native :subscribe
|
10
|
+
alias_native :unsubscribe
|
14
11
|
alias_native :publish
|
12
|
+
alias_native :bind
|
13
|
+
alias_native :cancel
|
14
|
+
alias_native :on
|
15
|
+
alias_native :then
|
15
16
|
alias_native :set_header, :setHeader
|
16
17
|
alias_native :add_extension, :addExtension
|
18
|
+
|
19
|
+
def initialize url
|
20
|
+
super `new Faye.Client(#{url})`
|
21
|
+
set_header 'X-CSRF-TOKEN', Element.find('meta[name=_csrf]').attr('content')
|
22
|
+
add_extension({
|
23
|
+
incoming: ->(message, block) { incoming message, block },
|
24
|
+
outgoing: ->(message, block) { outgoing message, block }
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
28
|
+
def public_id
|
29
|
+
@public_id ||= generate_id
|
30
|
+
end
|
31
|
+
|
32
|
+
def private_id
|
33
|
+
@private_id ||= generate_id
|
34
|
+
end
|
35
|
+
|
36
|
+
def incoming message, block
|
37
|
+
msg = Native(message)
|
38
|
+
|
39
|
+
if (!@public_id && !@private_id) && msg[:channel] == '/meta/handshake'
|
40
|
+
subscribe "/components/incoming/#{private_id}/#{public_id}" do |data|
|
41
|
+
data = Native(data)
|
42
|
+
event_id = data[:event_id]
|
43
|
+
body = Element['body']
|
44
|
+
|
45
|
+
body.trigger(event_id, data[:local], data)
|
46
|
+
body.off event_id
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
block.call message
|
51
|
+
end
|
52
|
+
|
53
|
+
def outgoing message, block
|
54
|
+
message = %x{
|
55
|
+
message = #{message}
|
56
|
+
message.ext = message.ext || {};
|
57
|
+
message.ext.csrfToken = $('meta[name=_csrf]').attr('content');
|
58
|
+
}
|
59
|
+
block.call message
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def generate_id
|
65
|
+
o = [('a'..'z'), ('A'..'Z'), (0..9)].map { |i| i.to_a }.flatten
|
66
|
+
(0...50).map { o[rand(o.length)] }.join
|
67
|
+
end
|
17
68
|
end
|
18
69
|
end
|
19
70
|
end
|
20
71
|
else
|
72
|
+
require 'faye'
|
73
|
+
require 'roda/component/ohm'
|
74
|
+
require 'roda/component/models/user'
|
75
|
+
require 'roda/component/models/channel'
|
76
|
+
|
21
77
|
class Roda
|
22
78
|
class Component
|
23
79
|
class Faye
|
24
80
|
class CsrfProtection
|
25
|
-
def incoming(
|
26
|
-
# # fix due to opal and wrapping message in native like Native(message)
|
27
|
-
message = { '_id' => m['_id']}
|
28
|
-
message.merge! m['native']
|
29
|
-
|
30
|
-
ap '======================'
|
31
|
-
ap message
|
32
|
-
ap request.session
|
33
|
-
ap '======================'
|
34
|
-
|
81
|
+
def incoming(message, request, callback)
|
35
82
|
session_token = request.session['csrf.token']
|
36
83
|
message_token = message['ext'] && message['ext'].delete('csrfToken')
|
37
84
|
|
@@ -41,19 +88,47 @@ else
|
|
41
88
|
|
42
89
|
callback.call(message)
|
43
90
|
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class ChannelManager
|
94
|
+
def incoming(message, request, callback)
|
95
|
+
app = get_app(request)
|
96
|
+
|
97
|
+
if data = message['data']
|
98
|
+
case data['type']
|
99
|
+
when 'event'
|
100
|
+
options = { local: data['local'] }
|
101
|
+
data['event_type'] == 'call' \
|
102
|
+
? options[:call] = data['event_method'] \
|
103
|
+
: options[:trigger] = data['event_method']
|
104
|
+
|
105
|
+
message['data']['local'] = app.roda_component(:"#{data['name']}", options)
|
106
|
+
message['channel'] = message['channel'].gsub(/outgoing/, 'incoming')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
callback.call message
|
111
|
+
end
|
112
|
+
|
113
|
+
# /components/:id/:comp/:action
|
114
|
+
# def outgoing(message, request, callback)
|
115
|
+
# app = get_app request
|
44
116
|
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
# ap '
|
48
|
-
# ap
|
49
|
-
# ap
|
50
|
-
#
|
51
|
-
#
|
52
|
-
# # unless session_token == message_token
|
53
|
-
# # message['error'] = '401::Access denied'
|
54
|
-
# # end
|
55
|
-
# callback.call(m)
|
117
|
+
# # message[:data] = app.roda_component(:auth, call: :cow) || false
|
118
|
+
#
|
119
|
+
# ap '====OUTGOING===='
|
120
|
+
# ap message
|
121
|
+
# ap '================'
|
122
|
+
#
|
123
|
+
# callback.call message
|
56
124
|
# end
|
125
|
+
|
126
|
+
def get_app request
|
127
|
+
request.env['RODA_COMPONENT_FROM_FAYE'] = true
|
128
|
+
a = Class.new(Roda::Component.app.class).new
|
129
|
+
a.instance_variable_set(:@_request, request)
|
130
|
+
a
|
131
|
+
end
|
57
132
|
end
|
58
133
|
end
|
59
134
|
end
|
@@ -10,11 +10,11 @@ class Roda
|
|
10
10
|
|
11
11
|
# this is a hack because it seems like display is a ruby object method
|
12
12
|
# when doing method(:display) it gives #<Method: # Roda::Component::Instance(Kernel)#display>
|
13
|
-
def display *args
|
14
|
-
method_missing(*args)
|
13
|
+
def display *args, &block
|
14
|
+
method_missing('display', *args, &block)
|
15
15
|
end
|
16
16
|
|
17
|
-
def method_missing method
|
17
|
+
def method_missing method, *args, &block
|
18
18
|
if instance.respond_to? method, true
|
19
19
|
instance.send method, *args, &block
|
20
20
|
elsif server && scope && scope.respond_to?(method, true)
|
data/lib/roda/component.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
unless RUBY_ENGINE == 'opal'
|
2
2
|
require 'tilt'
|
3
|
+
require 'awesome_print'
|
3
4
|
end
|
4
5
|
|
5
6
|
require 'opal'
|
@@ -18,12 +19,35 @@ if RUBY_ENGINE == 'opal'
|
|
18
19
|
}
|
19
20
|
end
|
20
21
|
|
22
|
+
module Overrideable
|
23
|
+
def self.included(c)
|
24
|
+
c.instance_methods(false).each do |m|
|
25
|
+
m = m.to_sym
|
26
|
+
c.class_eval %Q{
|
27
|
+
alias #{m}_original #{m}
|
28
|
+
def #{m}(*args, &block)
|
29
|
+
puts "Foo"
|
30
|
+
result = #{m}_original(*args, &block)
|
31
|
+
puts "Bar"
|
32
|
+
result
|
33
|
+
end
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
21
39
|
class Roda
|
22
40
|
class Component
|
23
41
|
attr_accessor :scope
|
24
42
|
|
25
43
|
def initialize(scope = false)
|
26
44
|
@scope = scope
|
45
|
+
|
46
|
+
if client?
|
47
|
+
$faye.subscribe "/components/#{self.class._name}" do |msg|
|
48
|
+
`window.console.log(#{msg})`
|
49
|
+
end
|
50
|
+
end
|
27
51
|
end
|
28
52
|
|
29
53
|
class << self
|
@@ -37,6 +61,38 @@ class Roda
|
|
37
61
|
end
|
38
62
|
end
|
39
63
|
|
64
|
+
def on_server &block
|
65
|
+
if server?
|
66
|
+
yield
|
67
|
+
else
|
68
|
+
m = Module.new(&block)
|
69
|
+
|
70
|
+
m.public_instance_methods(false).each do |meth|
|
71
|
+
define_method "#{meth}" do |*args, &blk|
|
72
|
+
name = self.class._name
|
73
|
+
event_id = "comp-event-#{$faye.generate_id}"
|
74
|
+
|
75
|
+
Element['body'].on event_id do |event, local, data|
|
76
|
+
blk.call local, event, data
|
77
|
+
end
|
78
|
+
|
79
|
+
$faye.publish("/components/outgoing/#{$faye.private_id}/#{$faye.public_id}", {
|
80
|
+
name: name,
|
81
|
+
type: 'event',
|
82
|
+
event_type: 'call',
|
83
|
+
event_method: meth,
|
84
|
+
event_id: event_id,
|
85
|
+
local: args.first || nil
|
86
|
+
})
|
87
|
+
|
88
|
+
true
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
include m
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
40
96
|
# The name of the component
|
41
97
|
def name _name
|
42
98
|
@_name = _name.to_s
|
@@ -78,6 +134,7 @@ class Roda
|
|
78
134
|
unless @_cache
|
79
135
|
@_cache ||= Roda::RodaCache.new
|
80
136
|
@_cache[:tmpl] = {}
|
137
|
+
@_cache[:server_methods] = []
|
81
138
|
end
|
82
139
|
|
83
140
|
@_cache
|
@@ -146,22 +203,26 @@ class Roda
|
|
146
203
|
end
|
147
204
|
|
148
205
|
def dom
|
149
|
-
|
150
|
-
|
206
|
+
if server?
|
207
|
+
@_dom ||= DOM.new cache[:dom].dup || begin
|
151
208
|
Nokogiri::HTML cache[:html]
|
152
|
-
else
|
153
|
-
Element
|
154
209
|
end
|
210
|
+
else
|
211
|
+
@_dom ||= DOM.new(Element)
|
155
212
|
end
|
156
213
|
end
|
157
214
|
|
158
215
|
# Grab the template from the cache, use the nokogiri dom or create a
|
159
216
|
# jquery element for server side
|
160
217
|
def tmpl name
|
161
|
-
if
|
162
|
-
|
218
|
+
if t = cache[:tmpl][name]
|
219
|
+
if server?
|
220
|
+
DOM.new t[:dom].dup
|
221
|
+
else
|
222
|
+
DOM.new Element[t[:html].dup]
|
223
|
+
end
|
163
224
|
else
|
164
|
-
|
225
|
+
false
|
165
226
|
end
|
166
227
|
end
|
167
228
|
|
@@ -3,6 +3,7 @@ require 'faye'
|
|
3
3
|
require 'faye/redis'
|
4
4
|
require 'roda/component'
|
5
5
|
require 'roda/component/faye'
|
6
|
+
require 'roda/component/ohm'
|
6
7
|
require 'json'
|
7
8
|
require "base64"
|
8
9
|
|
@@ -13,12 +14,6 @@ class Roda
|
|
13
14
|
Faye::WebSocket.load_adapter('thin')
|
14
15
|
|
15
16
|
app.plugin :csrf, header: 'X-CSRF-TOKEN'
|
16
|
-
|
17
|
-
app.use Faye::RackAdapter,
|
18
|
-
mount: '/faye',
|
19
|
-
timeout: 25,
|
20
|
-
extensions: [Roda::Component::Faye::CsrfProtection.new],
|
21
|
-
:engine => { :type => Faye::Redis }
|
22
17
|
end
|
23
18
|
|
24
19
|
def self.configure(app, opts={})
|
@@ -28,16 +23,33 @@ class Roda
|
|
28
23
|
app.opts[:component] = opts.dup
|
29
24
|
end
|
30
25
|
|
31
|
-
opts
|
32
|
-
opts[:cache]
|
33
|
-
opts[:path]
|
34
|
-
opts[:route]
|
35
|
-
opts[:assets_route]
|
36
|
-
opts[:class]
|
37
|
-
opts[:settings]
|
38
|
-
opts[:class_name]
|
39
|
-
opts[:events]
|
40
|
-
opts[:
|
26
|
+
opts = app.opts[:component]
|
27
|
+
opts[:cache] = app.thread_safe_cache if opts.fetch(:cache, true)
|
28
|
+
opts[:path] ||= 'components'
|
29
|
+
opts[:route] ||= 'components'
|
30
|
+
opts[:assets_route] ||= 'assets/components'
|
31
|
+
opts[:class] ||= Roda::Component
|
32
|
+
opts[:settings] ||= {}
|
33
|
+
opts[:class_name] ||= {}
|
34
|
+
opts[:events] ||= {}
|
35
|
+
opts[:user_model] ||= 'User'
|
36
|
+
opts[:redis_namespace] ||= 'roda:component:'
|
37
|
+
opts[:cache][:tmpl] ||= {}
|
38
|
+
|
39
|
+
app.use(Faye::RackAdapter, {
|
40
|
+
mount: '/faye',
|
41
|
+
extensions: [
|
42
|
+
Roda::Component::Faye::CsrfProtection.new,
|
43
|
+
Roda::Component::Faye::ChannelManager.new
|
44
|
+
],
|
45
|
+
engine: {
|
46
|
+
type: Faye::Redis,
|
47
|
+
uri: opts[:redis_uri],
|
48
|
+
namespace: opts[:redis_namespace]
|
49
|
+
}
|
50
|
+
})
|
51
|
+
|
52
|
+
Roda::Component::Ohm.redis = Redic.new opts[:redis_uri]
|
41
53
|
|
42
54
|
# Set the current app
|
43
55
|
opts[:class].set_app app
|
@@ -66,35 +78,10 @@ class Roda
|
|
66
78
|
options = Base64.encode64 options.to_json
|
67
79
|
comp_name = comp.class._name
|
68
80
|
|
69
|
-
# client.addExtension({
|
70
|
-
# outgoing: function(message, callback) {
|
71
|
-
# message.ext = message.ext || {};
|
72
|
-
# message.ext.csrfToken = $('meta[name=csrf-token]').attr('content');
|
73
|
-
# callback(message);
|
74
|
-
# }
|
75
|
-
# });
|
76
81
|
js = <<-EOF
|
77
82
|
Document.ready? do
|
78
83
|
unless $faye
|
79
84
|
$faye = Roda::Component::Faye.new('/faye')
|
80
|
-
|
81
|
-
$faye.set_header 'X-CSRF-TOKEN', Element.find('meta[name=_csrf]').attr('content')
|
82
|
-
|
83
|
-
$faye.add_extension({
|
84
|
-
outgoing: ->(message, block) {
|
85
|
-
message = Native(message)
|
86
|
-
message.ext = message.ext || {}
|
87
|
-
message.ext.csrfToken = Element.find('meta[name=_csrf]').attr('content')
|
88
|
-
|
89
|
-
block.call message
|
90
|
-
}
|
91
|
-
})
|
92
|
-
|
93
|
-
$faye.subscribe '/foo' do |message|
|
94
|
-
puts '===================='
|
95
|
-
puts message
|
96
|
-
puts '===================='
|
97
|
-
end
|
98
85
|
end
|
99
86
|
|
100
87
|
unless $component_opts[:comp][:"#{comp_name}"]
|
@@ -126,15 +113,19 @@ class Roda
|
|
126
113
|
end
|
127
114
|
end
|
128
115
|
|
129
|
-
if
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
116
|
+
if !env['RODA_COMPONENT_FROM_FAYE']
|
117
|
+
if comp_response.is_a? Roda::Component::DOM
|
118
|
+
content = comp_response.to_html
|
119
|
+
else
|
120
|
+
content = comp_response.to_s
|
121
|
+
end
|
134
122
|
|
135
|
-
|
123
|
+
content += load_component_js comp, action
|
136
124
|
|
137
|
-
|
125
|
+
content
|
126
|
+
else
|
127
|
+
comp_response
|
128
|
+
end
|
138
129
|
end
|
139
130
|
alias :comp :component
|
140
131
|
alias :roda_component :component
|
data/roda-component.gemspec
CHANGED
@@ -24,6 +24,9 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_runtime_dependency "faye-redis"
|
25
25
|
spec.add_runtime_dependency "tilt"
|
26
26
|
spec.add_runtime_dependency "rack_csrf"
|
27
|
+
spec.add_runtime_dependency "ohm"
|
28
|
+
spec.add_runtime_dependency "ohm-contrib"
|
29
|
+
spec.add_runtime_dependency "ohm-sorted"
|
27
30
|
spec.add_development_dependency "bundler", "~> 1.7"
|
28
31
|
spec.add_development_dependency "rake", "~> 10.0"
|
29
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roda-component
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- cj
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -94,6 +94,48 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: ohm
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: ohm-contrib
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: ohm-sorted
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
97
139
|
- !ruby/object:Gem::Dependency
|
98
140
|
name: bundler
|
99
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,6 +184,9 @@ files:
|
|
142
184
|
- lib/roda/component/events.rb
|
143
185
|
- lib/roda/component/faye.rb
|
144
186
|
- lib/roda/component/instance.rb
|
187
|
+
- lib/roda/component/models/channel.rb
|
188
|
+
- lib/roda/component/models/user.rb
|
189
|
+
- lib/roda/component/ohm.rb
|
145
190
|
- lib/roda/component/version.rb
|
146
191
|
- lib/roda/plugins/component.rb
|
147
192
|
- roda-component.gemspec
|