roda-component 0.0.4 → 0.0.5
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/events.rb +18 -28
- data/lib/roda/component/faye.rb +61 -0
- data/lib/roda/component/instance.rb +38 -0
- data/lib/roda/component/version.rb +1 -1
- data/lib/roda/component.rb +26 -7
- data/lib/roda/plugins/component.rb +58 -11
- data/roda-component.gemspec +2 -0
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e07b2592555f0305b5ff63e7b1a5d0cdc595f337
|
4
|
+
data.tar.gz: a9292504e6a90f5aec922f3908a8abed452cbb23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e3c511932310c7c1958b248944bd61b3507ce506191d4ced846618cc54a25b64ba955b1bd1c1cf83fbd140f3ac6d2f576f04b1e76f1a22b970532936e43cd70
|
7
|
+
data.tar.gz: 06c976af76747799ba76fe4661a21a00fa927a7614a8c4d7811f4261037ed53d31c05bab95a131a8da24f90861a2888557285c203e8675d86ff9dd096d06174c
|
@@ -2,24 +2,32 @@ class Roda
|
|
2
2
|
class Component
|
3
3
|
class Events < Struct.new(:klass, :component_opts, :scope)
|
4
4
|
def on name, options = {}, &block
|
5
|
+
limit_if = options.delete(:if) || []
|
6
|
+
limit_if = [limit_if] unless limit_if.is_a? Array
|
7
|
+
|
5
8
|
class_name = options.delete(:for) || klass._name
|
6
9
|
class_events = (events[class_name] ||= {})
|
7
|
-
event = (class_events[name] ||= [])
|
10
|
+
event = (class_events[name.to_s] ||= [])
|
11
|
+
|
12
|
+
# remove the type, if we have an on if and it isn't in the engine_type
|
13
|
+
if limit_if.any? && !limit_if.include?(engine_type.to_sym)
|
14
|
+
block = Proc.new {}
|
15
|
+
end
|
8
16
|
event << [block, klass._name, options]
|
9
17
|
end
|
10
18
|
|
11
19
|
def trigger name, options = {}
|
12
20
|
content = ''
|
13
21
|
|
14
|
-
events[klass._name][name].each do |event|
|
22
|
+
events[klass._name][name.to_s].each do |event|
|
15
23
|
block, comp, _ = event
|
16
24
|
|
17
|
-
response = Instance.new(component(comp), scope).instance_exec options, &block
|
25
|
+
response = Component::Instance.new(component(comp), scope).instance_exec options, &block
|
18
26
|
|
19
27
|
if response.is_a? Roda::Component::DOM
|
20
28
|
content = response.to_html
|
21
29
|
elsif response.is_a? String
|
22
|
-
content = response
|
30
|
+
content = response
|
23
31
|
end
|
24
32
|
end
|
25
33
|
|
@@ -40,37 +48,19 @@ class Roda
|
|
40
48
|
component_opts[:events]
|
41
49
|
end
|
42
50
|
|
51
|
+
def engine_type
|
52
|
+
RUBY_ENGINE == 'ruby' ? 'server' : 'client'
|
53
|
+
end
|
54
|
+
|
43
55
|
def server?
|
44
|
-
RUBY_ENGINE == 'ruby'
|
56
|
+
RUBY_ENGINE == 'ruby' ? 'server' : false
|
45
57
|
end
|
46
58
|
alias :server :server?
|
47
59
|
|
48
60
|
def client?
|
49
|
-
RUBY_ENGINE == 'opal'
|
61
|
+
RUBY_ENGINE == 'opal' ? 'client' : false
|
50
62
|
end
|
51
63
|
alias :client :client?
|
52
|
-
|
53
|
-
class Instance < Struct.new(:instance, :scope)
|
54
|
-
def method_missing method, *args, &block
|
55
|
-
if instance.respond_to? method, true
|
56
|
-
instance.send method, *args, &block
|
57
|
-
elsif server && scope.respond_to?(method, true)
|
58
|
-
scope.send method, *args, &block
|
59
|
-
else
|
60
|
-
super
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def server?
|
65
|
-
RUBY_ENGINE == 'ruby'
|
66
|
-
end
|
67
|
-
alias :server :server?
|
68
|
-
|
69
|
-
def client?
|
70
|
-
RUBY_ENGINE == 'opal'
|
71
|
-
end
|
72
|
-
alias :client :client?
|
73
|
-
end
|
74
64
|
end
|
75
65
|
end
|
76
66
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
if RUBY_ENGINE == 'opal'
|
2
|
+
require 'native'
|
3
|
+
|
4
|
+
class Roda
|
5
|
+
class Component
|
6
|
+
class Faye
|
7
|
+
include Native
|
8
|
+
|
9
|
+
def initialize url
|
10
|
+
super `new Faye.Client(#{url})`
|
11
|
+
end
|
12
|
+
|
13
|
+
alias_native :subscribe
|
14
|
+
alias_native :publish
|
15
|
+
alias_native :set_header, :setHeader
|
16
|
+
alias_native :add_extension, :addExtension
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
else
|
21
|
+
class Roda
|
22
|
+
class Component
|
23
|
+
class Faye
|
24
|
+
class CsrfProtection
|
25
|
+
def incoming(m, request, callback)
|
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
|
+
|
35
|
+
session_token = request.session['csrf.token']
|
36
|
+
message_token = message['ext'] && message['ext'].delete('csrfToken')
|
37
|
+
|
38
|
+
unless session_token == message_token
|
39
|
+
message['error'] = '401::Access denied'
|
40
|
+
end
|
41
|
+
|
42
|
+
callback.call(message)
|
43
|
+
end
|
44
|
+
#
|
45
|
+
# def outgoing(m, request, callback)
|
46
|
+
# ap '======================'
|
47
|
+
# ap 'outgoing'
|
48
|
+
# ap m
|
49
|
+
# ap request.session
|
50
|
+
# ap '======================'
|
51
|
+
# #
|
52
|
+
# # unless session_token == message_token
|
53
|
+
# # message['error'] = '401::Access denied'
|
54
|
+
# # end
|
55
|
+
# callback.call(m)
|
56
|
+
# end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Roda
|
2
|
+
class Component
|
3
|
+
class Instance
|
4
|
+
attr_accessor :instance, :scope
|
5
|
+
|
6
|
+
def initialize instance, scope = false
|
7
|
+
@instance = instance
|
8
|
+
@scope = scope
|
9
|
+
end
|
10
|
+
|
11
|
+
# this is a hack because it seems like display is a ruby object method
|
12
|
+
# when doing method(:display) it gives #<Method: # Roda::Component::Instance(Kernel)#display>
|
13
|
+
def display *args
|
14
|
+
method_missing(*args)
|
15
|
+
end
|
16
|
+
|
17
|
+
def method_missing method = 'display', *args, &block
|
18
|
+
if instance.respond_to? method, true
|
19
|
+
instance.send method, *args, &block
|
20
|
+
elsif server && scope && scope.respond_to?(method, true)
|
21
|
+
scope.send method, *args, &block
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def server?
|
28
|
+
RUBY_ENGINE == 'ruby'
|
29
|
+
end
|
30
|
+
alias :server :server?
|
31
|
+
|
32
|
+
def client?
|
33
|
+
RUBY_ENGINE == 'opal'
|
34
|
+
end
|
35
|
+
alias :client :client?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/roda/component.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
+
unless RUBY_ENGINE == 'opal'
|
2
|
+
require 'tilt'
|
3
|
+
end
|
4
|
+
|
1
5
|
require 'opal'
|
2
6
|
require 'opal-jquery'
|
3
7
|
require "base64"
|
8
|
+
require 'roda/component/faye'
|
9
|
+
require 'roda/component/instance'
|
4
10
|
require 'roda/component/dom'
|
5
11
|
require 'roda/component/events'
|
6
12
|
|
@@ -12,7 +18,6 @@ if RUBY_ENGINE == 'opal'
|
|
12
18
|
}
|
13
19
|
end
|
14
20
|
|
15
|
-
|
16
21
|
class Roda
|
17
22
|
class Component
|
18
23
|
attr_accessor :scope
|
@@ -34,11 +39,11 @@ class Roda
|
|
34
39
|
|
35
40
|
# The name of the component
|
36
41
|
def name _name
|
42
|
+
@_name = _name.to_s
|
43
|
+
|
37
44
|
if server?
|
38
|
-
component_opts[:class_name][_name] = self.to_s
|
45
|
+
component_opts[:class_name][@_name] = self.to_s
|
39
46
|
end
|
40
|
-
|
41
|
-
@_name = _name
|
42
47
|
end
|
43
48
|
|
44
49
|
# The html source
|
@@ -109,6 +114,14 @@ class Roda
|
|
109
114
|
end
|
110
115
|
end
|
111
116
|
|
117
|
+
def method_missing method, *args, &block
|
118
|
+
if server && app.respond_to?(method, true)
|
119
|
+
app.send method, *args, &block
|
120
|
+
else
|
121
|
+
super
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
112
125
|
private
|
113
126
|
|
114
127
|
def server?
|
@@ -133,15 +146,13 @@ class Roda
|
|
133
146
|
end
|
134
147
|
|
135
148
|
def dom
|
136
|
-
|
149
|
+
@_dom ||= DOM.new cache[:dom].dup || begin
|
137
150
|
if server?
|
138
151
|
Nokogiri::HTML cache[:html]
|
139
152
|
else
|
140
153
|
Element
|
141
154
|
end
|
142
155
|
end
|
143
|
-
|
144
|
-
DOM.new d
|
145
156
|
end
|
146
157
|
|
147
158
|
# Grab the template from the cache, use the nokogiri dom or create a
|
@@ -162,6 +173,14 @@ class Roda
|
|
162
173
|
events.trigger(*args)
|
163
174
|
end
|
164
175
|
|
176
|
+
def method_missing method, *args, &block
|
177
|
+
if server && scope.respond_to?(method, true)
|
178
|
+
scope.send method, *args, &block
|
179
|
+
else
|
180
|
+
super
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
165
184
|
private
|
166
185
|
|
167
186
|
def server?
|
@@ -1,11 +1,26 @@
|
|
1
1
|
require 'tilt'
|
2
|
+
require 'faye'
|
3
|
+
require 'faye/redis'
|
2
4
|
require 'roda/component'
|
5
|
+
require 'roda/component/faye'
|
3
6
|
require 'json'
|
4
7
|
require "base64"
|
5
8
|
|
6
9
|
class Roda
|
7
10
|
module RodaPlugins
|
8
11
|
module Component
|
12
|
+
def self.load_dependencies(app, opts={})
|
13
|
+
Faye::WebSocket.load_adapter('thin')
|
14
|
+
|
15
|
+
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
|
+
end
|
23
|
+
|
9
24
|
def self.configure(app, opts={})
|
10
25
|
if app.opts[:component]
|
11
26
|
app.opts[:component].merge!(opts)
|
@@ -35,7 +50,7 @@ class Roda
|
|
35
50
|
|
36
51
|
def load_component name
|
37
52
|
Object.const_get(
|
38
|
-
component_opts[:class_name][name.
|
53
|
+
component_opts[:class_name][name.to_s]
|
39
54
|
).new self
|
40
55
|
end
|
41
56
|
|
@@ -51,8 +66,37 @@ class Roda
|
|
51
66
|
options = Base64.encode64 options.to_json
|
52
67
|
comp_name = comp.class._name
|
53
68
|
|
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
|
+
# });
|
54
76
|
js = <<-EOF
|
55
77
|
Document.ready? do
|
78
|
+
unless $faye
|
79
|
+
$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
|
+
end
|
99
|
+
|
56
100
|
unless $component_opts[:comp][:"#{comp_name}"]
|
57
101
|
c = $component_opts[:comp][:"#{comp_name}"] = #{comp.class}.new
|
58
102
|
c.cache = JSON.parse Base64.decode64('#{cache}')
|
@@ -67,14 +111,19 @@ class Roda
|
|
67
111
|
def component name, options = {}, &block
|
68
112
|
comp = load_component name
|
69
113
|
|
70
|
-
action
|
114
|
+
action = options[:call] || :display
|
115
|
+
trigger = options[:trigger] || false
|
71
116
|
|
72
117
|
# call action
|
73
118
|
# TODO: make sure the single method parameter isn't a block
|
74
|
-
if
|
75
|
-
comp_response = comp.
|
119
|
+
if trigger
|
120
|
+
comp_response = comp.trigger trigger, options
|
76
121
|
else
|
77
|
-
|
122
|
+
if comp.method(action).parameters.length > 0
|
123
|
+
comp_response = comp.send(action, options, &block)
|
124
|
+
else
|
125
|
+
comp_response = comp.send(action, &block)
|
126
|
+
end
|
78
127
|
end
|
79
128
|
|
80
129
|
if comp_response.is_a? Roda::Component::DOM
|
@@ -84,6 +133,8 @@ class Roda
|
|
84
133
|
end
|
85
134
|
|
86
135
|
content += load_component_js comp, action
|
136
|
+
|
137
|
+
content
|
87
138
|
end
|
88
139
|
alias :comp :component
|
89
140
|
alias :roda_component :component
|
@@ -143,16 +194,12 @@ class Roda
|
|
143
194
|
end
|
144
195
|
|
145
196
|
on self.class.component_route_regex do |comp, type, action|
|
146
|
-
comp = scope.load_component(comp.to_sym)
|
147
|
-
|
148
197
|
case type
|
149
198
|
when 'call'
|
150
|
-
|
199
|
+
scope.roda_component(comp, call: action)
|
151
200
|
when 'trigger'
|
152
|
-
|
201
|
+
scope.roda_component(comp, trigger: action)
|
153
202
|
end
|
154
|
-
|
155
|
-
response.write scope.load_component_js comp, action
|
156
203
|
end
|
157
204
|
end
|
158
205
|
end
|
data/roda-component.gemspec
CHANGED
@@ -21,7 +21,9 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_runtime_dependency "opal"
|
22
22
|
spec.add_runtime_dependency "opal-jquery"
|
23
23
|
spec.add_runtime_dependency "faye"
|
24
|
+
spec.add_runtime_dependency "faye-redis"
|
24
25
|
spec.add_runtime_dependency "tilt"
|
26
|
+
spec.add_runtime_dependency "rack_csrf"
|
25
27
|
spec.add_development_dependency "bundler", "~> 1.7"
|
26
28
|
spec.add_development_dependency "rake", "~> 10.0"
|
27
29
|
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.5
|
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-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: faye-redis
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: tilt
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +80,20 @@ dependencies:
|
|
66
80
|
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rack_csrf
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: bundler
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,6 +140,8 @@ files:
|
|
112
140
|
- lib/roda/component.rb
|
113
141
|
- lib/roda/component/dom.rb
|
114
142
|
- lib/roda/component/events.rb
|
143
|
+
- lib/roda/component/faye.rb
|
144
|
+
- lib/roda/component/instance.rb
|
115
145
|
- lib/roda/component/version.rb
|
116
146
|
- lib/roda/plugins/component.rb
|
117
147
|
- roda-component.gemspec
|