rumx 0.0.8 → 0.1.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.
- 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
|