rumx 0.0.8 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/History.md +28 -0
  2. data/README.md +8 -6
  3. data/examples/bean_hash/README +2 -0
  4. data/examples/bean_hash/config.ru +9 -0
  5. data/examples/bean_hash/my_bean.rb +44 -0
  6. data/examples/bean_list/my_bean.rb +3 -3
  7. data/examples/embedded/my_bean.rb +3 -2
  8. data/examples/hash/README +2 -0
  9. data/examples/hash/config.ru +9 -0
  10. data/examples/hash/my_bean.rb +30 -0
  11. data/examples/list/my_bean.rb +5 -2
  12. data/examples/monitor_script/README +8 -0
  13. data/examples/monitor_script/rumx_attributes +67 -0
  14. data/examples/simple/config.ru +3 -1
  15. data/examples/simple/my_other_bean.rb +11 -0
  16. data/examples/timer/README +1 -1
  17. data/examples/timer/my_bean.rb +2 -1
  18. data/examples/timer_hash/README +2 -0
  19. data/examples/timer_hash/config.ru +9 -0
  20. data/examples/timer_hash/my_bean.rb +29 -0
  21. data/lib/rumx.rb +5 -0
  22. data/lib/rumx/attribute.rb +26 -17
  23. data/lib/rumx/attribute_info.rb +12 -0
  24. data/lib/rumx/bean.rb +146 -248
  25. data/lib/rumx/beans.rb +2 -0
  26. data/lib/rumx/beans/error.rb +1 -1
  27. data/lib/rumx/beans/hash.rb +34 -0
  28. data/lib/rumx/beans/timer.rb +2 -2
  29. data/lib/rumx/beans/timer_and_error.rb +1 -1
  30. data/lib/rumx/beans/timer_hash.rb +9 -0
  31. data/lib/rumx/hash_attribute.rb +39 -0
  32. data/lib/rumx/hash_bean.rb +55 -0
  33. data/lib/rumx/list_attribute.rb +65 -0
  34. data/lib/rumx/list_bean.rb +52 -0
  35. data/lib/rumx/server.rb +65 -69
  36. data/lib/rumx/server/views/attribute_value_tag.haml +3 -3
  37. data/lib/rumx/server/views/content_attributes.haml +4 -4
  38. data/lib/rumx/server/views/content_operations.haml +2 -2
  39. data/lib/rumx/server/views/tree_bean_attributes.haml +0 -4
  40. data/lib/rumx/server/views/tree_bean_operations.haml +2 -2
  41. data/lib/rumx/type.rb +15 -7
  42. metadata +21 -3
  43. data/lib/rumx/server/views/content_attribute.haml +0 -35
data/lib/rumx/beans.rb CHANGED
@@ -3,3 +3,5 @@ require 'rumx/beans/message'
3
3
  require 'rumx/beans/timer'
4
4
  require 'rumx/beans/error'
5
5
  require 'rumx/beans/timer_and_error'
6
+ require 'rumx/beans/hash'
7
+ require 'rumx/beans/timer_hash'
@@ -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
- bean_attr_embed_list :errors, 'List of the last occurring errors'
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
@@ -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#bean_mutex to avoid race condition (See bean.rb)
16
- bean_mutex
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
- bean_attr_embed_list :errors, 'List of the last occurring errors'
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,9 @@
1
+ module Rumx
2
+ module Beans
3
+ class TimerHash < Hash
4
+ def initialize
5
+ super { Timer.new }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -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.bean_children.each do |name, 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, rel_path)
81
- partial :link_to_content, :locals => {:href => attribute_path(parent_path+'/'+rel_path), :name => rel_path}
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, rel_path)
89
- partial :link_to_content, :locals => {:href => operation_path(parent_path+'/'+rel_path), :name => rel_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(attribute, param_name, value)
93
- partial :attribute_value_tag, :locals => {:attribute => attribute, :param_name => param_name, :value => value}
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
- if params[:format]
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
- if params[:format]
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
- hash = {}
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
- hash = {}
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 with_indexed_params(params)
232
- i = 0
233
- while (prefix = params[prefix_key = "prefix_#{i}"]) && (bean_name = params[bean_key = "bean_#{i}"])
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
- postfix = "_#{i}"
236
- bean = Bean.find(bean_name.split('/'))
237
- params.each do |key, value|
238
- if key.end_with?(postfix) && key != prefix_key && key != bean_key
239
- new_params[key[0...-(postfix.size)]] = value
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
- yield prefix, bean, new_params
243
- i += 1
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