rumx 0.0.8 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.md +28 -0
- data/README.md +8 -6
- data/examples/bean_hash/README +2 -0
- data/examples/bean_hash/config.ru +9 -0
- data/examples/bean_hash/my_bean.rb +44 -0
- data/examples/bean_list/my_bean.rb +3 -3
- data/examples/embedded/my_bean.rb +3 -2
- data/examples/hash/README +2 -0
- data/examples/hash/config.ru +9 -0
- data/examples/hash/my_bean.rb +30 -0
- data/examples/list/my_bean.rb +5 -2
- data/examples/monitor_script/README +8 -0
- data/examples/monitor_script/rumx_attributes +67 -0
- data/examples/simple/config.ru +3 -1
- data/examples/simple/my_other_bean.rb +11 -0
- data/examples/timer/README +1 -1
- data/examples/timer/my_bean.rb +2 -1
- data/examples/timer_hash/README +2 -0
- data/examples/timer_hash/config.ru +9 -0
- data/examples/timer_hash/my_bean.rb +29 -0
- data/lib/rumx.rb +5 -0
- data/lib/rumx/attribute.rb +26 -17
- data/lib/rumx/attribute_info.rb +12 -0
- data/lib/rumx/bean.rb +146 -248
- data/lib/rumx/beans.rb +2 -0
- data/lib/rumx/beans/error.rb +1 -1
- data/lib/rumx/beans/hash.rb +34 -0
- data/lib/rumx/beans/timer.rb +2 -2
- data/lib/rumx/beans/timer_and_error.rb +1 -1
- data/lib/rumx/beans/timer_hash.rb +9 -0
- data/lib/rumx/hash_attribute.rb +39 -0
- data/lib/rumx/hash_bean.rb +55 -0
- data/lib/rumx/list_attribute.rb +65 -0
- data/lib/rumx/list_bean.rb +52 -0
- data/lib/rumx/server.rb +65 -69
- data/lib/rumx/server/views/attribute_value_tag.haml +3 -3
- data/lib/rumx/server/views/content_attributes.haml +4 -4
- data/lib/rumx/server/views/content_operations.haml +2 -2
- data/lib/rumx/server/views/tree_bean_attributes.haml +0 -4
- data/lib/rumx/server/views/tree_bean_operations.haml +2 -2
- data/lib/rumx/type.rb +15 -7
- metadata +21 -3
- data/lib/rumx/server/views/content_attribute.haml +0 -35
data/lib/rumx/beans.rb
CHANGED
data/lib/rumx/beans/error.rb
CHANGED
@@ -4,7 +4,7 @@ module Rumx
|
|
4
4
|
include Bean
|
5
5
|
|
6
6
|
bean_attr_reader :error_count, :integer, 'Number of times the measured block has raised an exception'
|
7
|
-
|
7
|
+
bean_attr_reader :errors, :list, 'List of the last occurring errors', :list_type => :bean
|
8
8
|
|
9
9
|
def initialize(opts={})
|
10
10
|
@errors = []
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rumx
|
2
|
+
module Beans
|
3
|
+
class Hash
|
4
|
+
include Bean
|
5
|
+
|
6
|
+
def initialize(&block)
|
7
|
+
raise 'Must be given initialize instance to create the bean' unless block_given?
|
8
|
+
@block = block
|
9
|
+
# Hacks for potential race conditions
|
10
|
+
bean_children
|
11
|
+
bean_synchronize {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
child = bean_children[key]
|
16
|
+
return child if child
|
17
|
+
bean_synchronize do
|
18
|
+
# Try it again to prevent race
|
19
|
+
child = bean_children[key]
|
20
|
+
return child if child
|
21
|
+
child = @block.call(key)
|
22
|
+
bean_add_child(key, child)
|
23
|
+
end
|
24
|
+
return child
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete(key)
|
28
|
+
bean_synchronize do
|
29
|
+
bean_remove_child(key)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/rumx/beans/timer.rb
CHANGED
@@ -12,8 +12,8 @@ module Rumx
|
|
12
12
|
bean_writer :reset, :boolean, 'Reset the times and counts to zero (Note that last_time is not reset)'
|
13
13
|
|
14
14
|
def initialize(opts={})
|
15
|
-
# Force initialization of Bean#
|
16
|
-
|
15
|
+
# Force initialization of Bean#bean_monitor to avoid race condition (See bean.rb)
|
16
|
+
bean_monitor
|
17
17
|
@last_time = 0.0
|
18
18
|
self.reset = true
|
19
19
|
end
|
@@ -3,7 +3,7 @@ module Rumx
|
|
3
3
|
class TimerAndError < Timer
|
4
4
|
|
5
5
|
bean_attr_reader :error_count, :integer, 'Number of times the measured block has raised an exception'
|
6
|
-
|
6
|
+
bean_attr_reader :errors, :list, 'List of the last occurring errors', :list_type => :bean
|
7
7
|
|
8
8
|
def initialize(opts={})
|
9
9
|
super
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Rumx
|
2
|
+
class HashAttribute < Attribute
|
3
|
+
|
4
|
+
def initialize(name, type, description, allow_read, allow_write, options)
|
5
|
+
super
|
6
|
+
raise 'Hash attribute called without hash_type option' unless options[:hash_type]
|
7
|
+
@hash_type = Type.find(options[:hash_type])
|
8
|
+
end
|
9
|
+
|
10
|
+
def each_attribute_info(bean, ancestry, &block)
|
11
|
+
hash = bean.send(name)
|
12
|
+
child_ancestry = ancestry+[name]
|
13
|
+
index_index = child_ancestry.size
|
14
|
+
hash.each do |name, value|
|
15
|
+
value = nil unless allow_read
|
16
|
+
child_ancestry[index_index] = name
|
17
|
+
yield AttributeInfo.new(self, bean, child_ancestry, value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def write?(bean, params)
|
22
|
+
#puts "hash write params=#{params.inspect}"
|
23
|
+
return false unless params.kind_of?(Hash)
|
24
|
+
is_written = false
|
25
|
+
if allow_write
|
26
|
+
hash = bean.send(name)
|
27
|
+
param_value(params) do |hash_params|
|
28
|
+
if hash && hash_params && hash_params.kind_of?(Hash)
|
29
|
+
hash_params.each do |name, value|
|
30
|
+
hash[name.to_sym] = @hash_type.string_to_value(value)
|
31
|
+
is_written = true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
return is_written
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Rumx
|
2
|
+
class HashBean
|
3
|
+
include Bean
|
4
|
+
|
5
|
+
def initialize(hash)
|
6
|
+
@hash = hash
|
7
|
+
end
|
8
|
+
|
9
|
+
# Find the bean
|
10
|
+
def bean_find(name_array, index = 0)
|
11
|
+
return self if index == name_array.size
|
12
|
+
name = name_array[index].to_s
|
13
|
+
child = @hash[name] || @hash[name.to_sym]
|
14
|
+
return nil unless child
|
15
|
+
return child.bean_find(name_array, index+1)
|
16
|
+
end
|
17
|
+
|
18
|
+
def bean_each_embedded_child(&block)
|
19
|
+
@hash.each do |name, child|
|
20
|
+
yield name, child
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def do_bean_get_attributes(ancestry, &block)
|
27
|
+
return do_bean_get_attributes_json unless block_given?
|
28
|
+
child_ancestry = ancestry.dup
|
29
|
+
# Save some object creation
|
30
|
+
child_index = child_ancestry.size
|
31
|
+
@hash.each do |name, bean|
|
32
|
+
child_ancestry[child_index] = name
|
33
|
+
bean.bean_get_attributes(child_ancestry, &block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def do_bean_get_attributes_json
|
38
|
+
json_hash = {}
|
39
|
+
@hash.each do |name, bean|
|
40
|
+
json_hash[name] = bean.bean_get_attributes
|
41
|
+
end
|
42
|
+
return json_hash
|
43
|
+
end
|
44
|
+
|
45
|
+
def do_bean_set_attributes(params)
|
46
|
+
return if !params || params.empty?
|
47
|
+
changed = false
|
48
|
+
@hash.each do |name, bean|
|
49
|
+
changed = true
|
50
|
+
bean.bean_set_attributes(params[name] || params[name.to_sym])
|
51
|
+
end
|
52
|
+
bean_attributes_changed if changed
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Rumx
|
2
|
+
class ListAttribute < Attribute
|
3
|
+
|
4
|
+
# options
|
5
|
+
# list_type - any of the available types (required)
|
6
|
+
# max_size - max size of the list, can be a symbol representing a method or an integer (defaults to the current size of the list)
|
7
|
+
def initialize(name, type, description, allow_read, allow_write, options)
|
8
|
+
super
|
9
|
+
raise 'List attribute called without list_type option' unless options[:list_type]
|
10
|
+
@list_type = Type.find(options[:list_type])
|
11
|
+
end
|
12
|
+
|
13
|
+
def each_attribute_info(bean, ancestry, &block)
|
14
|
+
list = bean.send(name)
|
15
|
+
child_ancestry = ancestry+[name]
|
16
|
+
index_index = child_ancestry.size
|
17
|
+
list.each_with_index do |value, i|
|
18
|
+
value = nil unless allow_read
|
19
|
+
child_ancestry[index_index] = i
|
20
|
+
yield AttributeInfo.new(self, bean, child_ancestry, value)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def write?(bean, params)
|
25
|
+
#puts "list write params=#{params.inspect}"
|
26
|
+
is_written = false
|
27
|
+
if allow_write
|
28
|
+
list = bean.send(name)
|
29
|
+
return false unless list
|
30
|
+
max_size = self[:max_size]
|
31
|
+
if max_size
|
32
|
+
if max_size.kind_of?(Symbol)
|
33
|
+
max_size = bean.send(max_size)
|
34
|
+
end
|
35
|
+
else
|
36
|
+
# Default to current size of the list if unset
|
37
|
+
max_size = obj.size
|
38
|
+
end
|
39
|
+
param_value(params) do |sub_params|
|
40
|
+
each_param(sub_params) do |index, value|
|
41
|
+
if index < max_size
|
42
|
+
list[index] = @list_type.string_to_value(value)
|
43
|
+
is_written = true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
return is_written
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def each_param(params, &block)
|
54
|
+
if params.kind_of?(Hash)
|
55
|
+
params.each do |index, value|
|
56
|
+
yield index.to_i, value
|
57
|
+
end
|
58
|
+
elsif params.kind_of?(Array)
|
59
|
+
params.each_with_index do |value, index|
|
60
|
+
yield index, value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Rumx
|
2
|
+
class ListBean
|
3
|
+
include Bean
|
4
|
+
|
5
|
+
def initialize(list)
|
6
|
+
@list = list
|
7
|
+
end
|
8
|
+
|
9
|
+
# Find the bean
|
10
|
+
def bean_find(name_array, index = 0)
|
11
|
+
return self if index == name_array.size
|
12
|
+
name = name_array[index]
|
13
|
+
return nil unless name.match(/^\d+$/)
|
14
|
+
child = @list[name.to_i]
|
15
|
+
return nil unless child
|
16
|
+
return child.bean_find(name_array, index+1)
|
17
|
+
end
|
18
|
+
|
19
|
+
def bean_each_embedded_child(&block)
|
20
|
+
@list.each_with_index do |child, i|
|
21
|
+
yield i, child
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def do_bean_get_attributes(ancestry, &block)
|
28
|
+
return do_bean_get_attributes_json unless block_given?
|
29
|
+
child_ancestry = ancestry.dup
|
30
|
+
# Save some object creation
|
31
|
+
child_index = child_ancestry.size
|
32
|
+
@list.each_with_index do |bean, i|
|
33
|
+
child_ancestry[child_index] = i
|
34
|
+
bean.bean_get_attributes(child_ancestry, &block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def do_bean_get_attributes_json
|
39
|
+
@list.map { |bean| bean.bean_get_attributes }
|
40
|
+
end
|
41
|
+
|
42
|
+
def do_bean_set_attributes(params)
|
43
|
+
return if !params || params.empty?
|
44
|
+
changed = false
|
45
|
+
@list.each_with_index do |bean, i|
|
46
|
+
changed = true
|
47
|
+
bean.bean_set_attributes(params[i] || params[i.to_s])
|
48
|
+
end
|
49
|
+
bean_attributes_changed if changed
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/rumx/server.rb
CHANGED
@@ -2,6 +2,9 @@ require 'sinatra/base'
|
|
2
2
|
require 'json'
|
3
3
|
require 'haml'
|
4
4
|
require 'uri'
|
5
|
+
require 'cgi'
|
6
|
+
# See http://groups.google.com/group/sinatrarb/browse_thread/thread/87bf7613631e48aa
|
7
|
+
require 'rack/file'
|
5
8
|
|
6
9
|
module Rumx
|
7
10
|
class Server < Sinatra::Base
|
@@ -26,7 +29,7 @@ module Rumx
|
|
26
29
|
|
27
30
|
def render_tree_bean_children(parent_path, parent_bean)
|
28
31
|
val = ''
|
29
|
-
parent_bean.
|
32
|
+
parent_bean.bean_each_child do |name, bean|
|
30
33
|
#puts "in child name=#{name} bean=#{bean}"
|
31
34
|
path = "#{parent_path}/#{name}"
|
32
35
|
val << partial(:tree_bean, :locals => {:path => path, :name =>name, :bean => bean})
|
@@ -77,20 +80,33 @@ module Rumx
|
|
77
80
|
partial :link_to_content, :locals => {:href => attributes_path(path), :name => 'Attributes'}
|
78
81
|
end
|
79
82
|
|
80
|
-
def link_to_attribute(parent_path,
|
81
|
-
|
83
|
+
def link_to_attribute(parent_path, attribute_info)
|
84
|
+
path = rel_path(attribute_info.ancestry)
|
85
|
+
partial :link_to_content, :locals => {:href => attribute_path(parent_path+'/'+path), :name => path}
|
82
86
|
end
|
83
87
|
|
84
88
|
def link_to_operations(path)
|
85
89
|
partial :link_to_content, :locals => {:href => operations_path(path), :name => 'Operations'}
|
86
90
|
end
|
87
91
|
|
88
|
-
def link_to_operation(parent_path,
|
89
|
-
partial :link_to_content, :locals => {:href => operation_path(parent_path+'/'+
|
92
|
+
def link_to_operation(parent_path, operation)
|
93
|
+
partial :link_to_content, :locals => {:href => operation_path(parent_path+'/'+operation.name.to_s), :name => operation.name}
|
90
94
|
end
|
91
95
|
|
92
|
-
def attribute_value_tag(
|
93
|
-
partial :attribute_value_tag, :locals => {:
|
96
|
+
def attribute_value_tag(attribute_info)
|
97
|
+
partial :attribute_value_tag, :locals => {:attribute_info => attribute_info}
|
98
|
+
end
|
99
|
+
|
100
|
+
def rel_path(ancestry)
|
101
|
+
ancestry.join('/')
|
102
|
+
end
|
103
|
+
|
104
|
+
def param_name(ancestry)
|
105
|
+
pname = ancestry[0].to_s
|
106
|
+
ancestry[1..-1].each do |name|
|
107
|
+
pname += "[#{name}]"
|
108
|
+
end
|
109
|
+
return pname
|
94
110
|
end
|
95
111
|
end
|
96
112
|
|
@@ -99,70 +115,23 @@ module Rumx
|
|
99
115
|
end
|
100
116
|
|
101
117
|
get '/*/attributes.?:format?' do
|
102
|
-
path = params[:splat][0]
|
103
|
-
bean = Bean.find(path.split('/'))
|
104
|
-
return 404 unless bean
|
105
118
|
# For get we read, then write. post is the other way around.
|
106
|
-
|
107
|
-
handle_attributes(bean.bean_get_and_set_attributes(params), params[:format])
|
108
|
-
else
|
109
|
-
haml_for_ajax :content_attributes, :locals => {:get_set_method => :bean_get_and_set_attributes, :params => params, :path => path, :bean => bean}
|
110
|
-
end
|
119
|
+
do_get_or_post_splat_attributes(params, :bean_get_and_set_attributes)
|
111
120
|
end
|
112
121
|
|
113
122
|
post '/*/attributes.?:format?' do
|
114
|
-
path = params[:splat][0]
|
115
|
-
bean = Bean.find(path.split('/'))
|
116
|
-
return 404 unless bean
|
117
123
|
# For post we write, then read. get is the other way around.
|
118
|
-
|
119
|
-
handle_attributes(bean.bean_set_and_get_attributes(params), params[:format])
|
120
|
-
else
|
121
|
-
haml_for_ajax :content_attributes, :locals => {:get_set_method => :bean_set_and_get_attributes, :params => params, :path => path, :bean => bean}
|
122
|
-
end
|
124
|
+
do_get_or_post_splat_attributes(params, :bean_set_and_get_attributes)
|
123
125
|
end
|
124
126
|
|
125
127
|
# Allow a monitor to get the attributes from multiple beans.
|
126
128
|
# Use with params such as prefix_0=bean0&bean_0=MyFolder/MyBean&prefix_1=bean1&bean_1=MyOtherFolder/SomeOtherBean
|
127
129
|
get '/attributes.?:format?' do
|
128
|
-
|
129
|
-
with_indexed_params(params) do |prefix, bean, new_params|
|
130
|
-
return 404 unless bean
|
131
|
-
hash[prefix.to_sym] = bean.bean_get_and_set_attributes(new_params)
|
132
|
-
end
|
133
|
-
handle_attributes(hash, params[:format])
|
130
|
+
do_get_or_post_attributes(params, :bean_get_and_set_attributes)
|
134
131
|
end
|
135
132
|
|
136
133
|
post '/attributes.?:format?' do
|
137
|
-
|
138
|
-
with_indexed_params(params) do |prefix, bean, new_params|
|
139
|
-
return 404 unless bean
|
140
|
-
hash[prefix.to_sym] = bean.bean_set_and_get_attributes(new_params)
|
141
|
-
end
|
142
|
-
handle_attributes(hash, params[:format])
|
143
|
-
end
|
144
|
-
|
145
|
-
get '/*/attribute.?:format?' do
|
146
|
-
path = params[:splat][0]
|
147
|
-
bean, attribute, param_name, value = Bean.find_attribute(path.split('/'))
|
148
|
-
return 404 unless bean
|
149
|
-
if params[:format] == 'json'
|
150
|
-
else
|
151
|
-
haml_for_ajax :content_attribute, :locals => {:path => '/' + path, :bean => bean, :attribute => attribute, :param_name => param_name, :value => value}
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
post '/*/attribute.?:format?' do
|
156
|
-
path = params[:splat][0]
|
157
|
-
bean, attribute, param_name, value = Bean.find_attribute(path.split('/'))
|
158
|
-
return 404 unless bean
|
159
|
-
bean.bean_set_attributes(params)
|
160
|
-
# Do it again to get the updated value
|
161
|
-
bean, attribute, param_name, value = Bean.find_attribute(path.split('/'))
|
162
|
-
if params[:format] == 'json'
|
163
|
-
else
|
164
|
-
haml_for_ajax :content_attribute, :locals => {:path => '/' + path, :bean => bean, :attribute => attribute, :param_name => param_name, :value => value}
|
165
|
-
end
|
134
|
+
do_get_or_post_attributes(params, :bean_set_and_get_attributes)
|
166
135
|
end
|
167
136
|
|
168
137
|
get '/*/operations' do
|
@@ -228,21 +197,48 @@ module Rumx
|
|
228
197
|
return str
|
229
198
|
end
|
230
199
|
|
231
|
-
def
|
232
|
-
|
233
|
-
|
200
|
+
def do_get_or_post_splat_attributes(params, get_set_method)
|
201
|
+
#puts "params=#{params.inspect}"
|
202
|
+
path = params[:splat][0]
|
203
|
+
bean = Bean.find(path.split('/'))
|
204
|
+
return 404 unless bean
|
205
|
+
if params[:format]
|
206
|
+
handle_attributes(bean.send(get_set_method, params), params[:format])
|
207
|
+
else
|
208
|
+
haml_for_ajax :content_attributes, :locals => {:get_set_method => get_set_method, :params => params, :path => path, :bean => bean}
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def do_get_or_post_attributes(params, get_set_method)
|
213
|
+
hash = {}
|
214
|
+
index = 0
|
215
|
+
while query = params["query_#{index}"]
|
216
|
+
index += 1
|
217
|
+
uri = URI.parse(query)
|
218
|
+
prefix = nil
|
219
|
+
bean_path = uri.path
|
220
|
+
if i = bean_path.index('=')
|
221
|
+
prefix = bean_path[0,i]
|
222
|
+
bean_path = bean_path[(i+1)..-1]
|
223
|
+
end
|
224
|
+
bean = Bean.find(bean_path.split('/'))
|
225
|
+
return 404 unless bean
|
234
226
|
new_params = {}
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
new_params[key
|
227
|
+
if uri.query
|
228
|
+
cgi = CGI.parse(uri.query)
|
229
|
+
# We shouldn't have any dual params so let's turn this into a params object we can understand
|
230
|
+
cgi.each do |key, value|
|
231
|
+
new_params[key] = value[0]
|
240
232
|
end
|
241
233
|
end
|
242
|
-
|
243
|
-
|
234
|
+
bean_hash = bean.send(get_set_method, new_params)
|
235
|
+
if prefix
|
236
|
+
hash[prefix.to_sym] = bean_hash
|
237
|
+
else
|
238
|
+
hash = hash.merge(bean_hash)
|
239
|
+
end
|
244
240
|
end
|
241
|
+
handle_attributes(hash, params[:format])
|
245
242
|
end
|
246
|
-
|
247
243
|
end
|
248
244
|
end
|