rhodes-translator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/lib/rhodes_translator.rb +6 -0
  2. data/lib/rhodes_translator/binding.rb +86 -0
  3. data/lib/rhodes_translator/templates/checkbox.erb +11 -0
  4. data/lib/rhodes_translator/templates/content.erb +3 -0
  5. data/lib/rhodes_translator/templates/form.erb +6 -0
  6. data/lib/rhodes_translator/templates/hidden.erb +1 -0
  7. data/lib/rhodes_translator/templates/iuipanel.erb +8 -0
  8. data/lib/rhodes_translator/templates/labeledinputli.bb.erb +7 -0
  9. data/lib/rhodes_translator/templates/labeledinputli.erb +8 -0
  10. data/lib/rhodes_translator/templates/labeledrow.erb +4 -0
  11. data/lib/rhodes_translator/templates/labeledvalueli.bb.erb +4 -0
  12. data/lib/rhodes_translator/templates/labeledvalueli.erb +4 -0
  13. data/lib/rhodes_translator/templates/link.erb +1 -0
  14. data/lib/rhodes_translator/templates/link_row.erb +3 -0
  15. data/lib/rhodes_translator/templates/linkli.bb.erb +5 -0
  16. data/lib/rhodes_translator/templates/linkli.erb +6 -0
  17. data/lib/rhodes_translator/templates/list.bb.erb +3 -0
  18. data/lib/rhodes_translator/templates/list.erb +3 -0
  19. data/lib/rhodes_translator/templates/maplink.erb +39 -0
  20. data/lib/rhodes_translator/templates/panel.erb +2 -0
  21. data/lib/rhodes_translator/templates/password.erb +11 -0
  22. data/lib/rhodes_translator/templates/select.erb +14 -0
  23. data/lib/rhodes_translator/templates/submit.erb +4 -0
  24. data/lib/rhodes_translator/templates/table.erb +3 -0
  25. data/lib/rhodes_translator/templates/telephone.erb +1 -0
  26. data/lib/rhodes_translator/templates/text.erb +4 -0
  27. data/lib/rhodes_translator/templates/textarea.erb +10 -0
  28. data/lib/rhodes_translator/templates/textinput.erb +11 -0
  29. data/lib/rhodes_translator/templates/title.erb +3 -0
  30. data/lib/rhodes_translator/templates/toolbar.bb.erb +4 -0
  31. data/lib/rhodes_translator/templates/toolbar.erb +8 -0
  32. data/lib/rhodes_translator/templates/view.erb +1 -0
  33. data/lib/rhodes_translator/translator.rb +39 -0
  34. data/lib/rhodes_translator/validation.rb +99 -0
  35. data/spec/binding_spec.rb +169 -0
  36. data/spec/spec_helper.rb +46 -0
  37. data/spec/stubs.rb +17 -0
  38. data/spec/translator_spec.rb +35 -0
  39. data/spec/validator_spec.rb +212 -0
  40. metadata +92 -0
@@ -0,0 +1,6 @@
1
+ require 'rhodes_translator/translator'
2
+ require 'rhodes_translator/binding'
3
+ require 'rhodes_translator/validation'
4
+
5
+ $rhodes_extensions = []
6
+ $rhodes_extensions << File.dirname(__FILE__)
@@ -0,0 +1,86 @@
1
+ module RhodesTranslator
2
+ module Binding
3
+
4
+ class << self
5
+ attr_accessor :metaorigdata
6
+ end
7
+ def bind(data,view_def,first=true)
8
+ Binding.metaorigdata = data if first
9
+
10
+ return if view_def.nil?
11
+
12
+ view_def['children'] ||= []
13
+
14
+ if view_def['repeatable'] and view_def['repeatable'] =~ /\{\{(.*?)\}\}/
15
+ pathstring = $1.strip
16
+ value = decode_path(data,pathstring)
17
+ new_children = []
18
+ repeat_def = view_def
19
+ repeat_def['repeatable'] = nil
20
+ if value.is_a? Array or value.is_a? Hash
21
+ value.each do |element|
22
+ new_def = Marshal.load(Marshal.dump(repeat_def))
23
+ new_child = self.bind(element,new_def,false)["children"]
24
+ new_child.each do |child|
25
+ new_children << child
26
+ end
27
+ end
28
+ end
29
+ view_def['children'] = new_children
30
+ else
31
+ view_def['children'].each do |child|
32
+ self.bind(data,child,false)
33
+ end
34
+
35
+ end
36
+
37
+
38
+ view_def.each do |k,v|
39
+ unless k == 'children'
40
+ if v.is_a? String
41
+ while v =~ /\{\{(.*?)\}\}/
42
+ pathstring = $1.strip
43
+ regexp = Regexp.escape('{{' + $1 + '}}')
44
+ value = decode_path(data,pathstring)
45
+ v.gsub!(Regexp.new(regexp) , value.to_s)
46
+ end
47
+ view_def[k] = v
48
+ end
49
+ end
50
+ end
51
+ Binding.metaorigdata = nil if first
52
+ view_def
53
+ end
54
+
55
+ def decode_path(data,pathstring)
56
+ data = Binding.metaorigdata if pathstring =~ /^\//
57
+ # puts "PATH: #{pathstring}, DATA: #{data.inspect}"
58
+ elements = pathstring.split('/')
59
+ elements.delete_at(0) if pathstring =~ /^\//
60
+ # puts "ELEMENTS: #{elements.inspect}"
61
+ current = data
62
+ while element = elements.delete_at(0)
63
+ element.strip!
64
+ if current.is_a? Array
65
+ index = element.to_i
66
+ return "INVALID INDEX" if index == 0 and element[0].chr != '0'
67
+ return "INVALID INDEX" if current[index].nil?
68
+ current = current[index]
69
+ elsif current.is_a? Hash
70
+ key = element.strip
71
+ return "INVALID KEY" if current[key].nil?
72
+ current = current[key]
73
+ elsif current
74
+ begin
75
+ current = current.send element.strip
76
+ rescue Exception => e
77
+ return "INVALID DATA TYPE"
78
+ end
79
+ end
80
+ end #while
81
+ current
82
+ end #decode_path
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,11 @@
1
+ <div <%= "class=\"#{@doc_def['div_class']}\"" if @doc_def['div_class']%> >
2
+ <label <%= "class=\"#{@doc_def['label_class']}\"" if @doc_def['label_class']%> ><%=@doc_def['label']%></label>
3
+ <input
4
+ type="checkbox"
5
+ <%= "name=\"#{@doc_def['name']}\"" if @doc_def['name'] %>
6
+ <% if @doc_def['value'] %>
7
+ <%= "checked" if @doc_def['value'] == 'true' %>
8
+ <% else %>
9
+ <%= "checked" if @doc_def['default_value'] %>
10
+ <% end %>/>
11
+ </div>
@@ -0,0 +1,3 @@
1
+ <div id="content">
2
+ <%= @content %>
3
+ </div>
@@ -0,0 +1,6 @@
1
+ <form
2
+ <%= "name=\"#{@doc_def['name']}\"" if @doc_def['name'] %>
3
+ <%= "action=\"#{@doc_def['action']}\"" if @doc_def['action'] %>
4
+ <%= "method=\"#{@doc_def['method']}\"" if @doc_def['method'] %> >
5
+ <input type="hidden" name="metadata_action" value="<%= @action %>"/>
6
+ <%@content.each_line do |line|%><%= " " + line%><%end%></form>
@@ -0,0 +1 @@
1
+ <input type="hidden" name="<%= @doc_def["name"]%>" value="<%= @doc_def["value"] %>"/>
@@ -0,0 +1,8 @@
1
+ <div class="toolbar">
2
+ <h1 id="pageTitle">
3
+ <%=@doc_def['title']%>
4
+ </h1>
5
+ </div>
6
+
7
+ <div class="panel" selected="true">
8
+ <%@content.each_line do |line|%><%= " " + line%><%end%></div>
@@ -0,0 +1,7 @@
1
+ <tr>
2
+ <td width="125" class="fieldLabel"><%= @doc_def["label"] %></td>
3
+ <td><input type="text"
4
+ <%= "name=\"#{@doc_def['name']}\"" if @doc_def['name']%>
5
+ <%= "value=\"#{@doc_def['value']}\"" if @doc_def['value']%>
6
+ /></td>
7
+ </tr>
@@ -0,0 +1,8 @@
1
+ <li>
2
+ <label <%= "for=\"#{@doc_def['name']}\"" if @doc_def['name']%> class="fieldLabel"><%= @doc_def["label"] %></label>
3
+ <input type="text"
4
+ <%= "name=\"#{@doc_def['name']}\"" if @doc_def['name']%>
5
+ <%= "value=\"#{@doc_def['value']}\"" if @doc_def['value']%>
6
+ <%= placeholder(@doc_def["label"]) if @doc_def['label']%>
7
+ />
8
+ </li>
@@ -0,0 +1,4 @@
1
+ <tr>
2
+ <td class="gridleft"><%=@doc_def['label']%></td>
3
+ <td class="gridright"><%=@doc_def['value']%></td>
4
+ </tr>
@@ -0,0 +1,4 @@
1
+ <tr>
2
+ <td><%= @doc_def["label"] %></td>
3
+ <td><%= @doc_def["value"] %></td>
4
+ </tr>
@@ -0,0 +1,4 @@
1
+ <li>
2
+ <div class="itemLabel"><%= @doc_def["label"] %></div>
3
+ <div class="itemValue"><%= @doc_def["value"] %></div>
4
+ </li>
@@ -0,0 +1 @@
1
+ <a href="<%= @doc_def['url'].to_s %>"><%= @doc_def['text'] %></a>
@@ -0,0 +1,3 @@
1
+ <tr>
2
+ <td class="gridleft"><a href='<%=@doc_def['model']%>/<%=@doc_def['id']%>/show'><%=@doc_def['value']%></a></td>
3
+ </tr>
@@ -0,0 +1,5 @@
1
+ <tr>
2
+ <td colspan="2">
3
+ <a href="<%= @doc_def["uri"] %>"><%= @doc_def["text"] %></a>
4
+ </td>
5
+ </tr>
@@ -0,0 +1,6 @@
1
+ <li>
2
+ <a href="<%= @doc_def["uri"] %>">
3
+ <span class="title"><%= @doc_def["text"] %></span>
4
+ <span class="disclosure_indicator"></span>
5
+ </a>
6
+ </li>
@@ -0,0 +1,3 @@
1
+ <table>
2
+ <%= @content %>
3
+ </table>
@@ -0,0 +1,3 @@
1
+ <ul>
2
+ <%= @content %>
3
+ </ul>
@@ -0,0 +1,39 @@
1
+
2
+ <%
3
+ puts "MAPLINK"
4
+ if @doc_def['showmap_url']
5
+ base_url = @doc_def['showmap_url']
6
+ else
7
+ base_url = url_for :action => show_map
8
+ end
9
+ base_url = base_url + "?"
10
+
11
+ base_url = base_url + "map_type=#{@doc_def['map_type']}&" if @doc_def['map_type']
12
+ base_url = base_url + "lat=#{@doc_def['lat']}&" if @doc_def['lat']
13
+ base_url = base_url + "long=#{@doc_def['long']}&" if @doc_def['long']
14
+ base_url = base_url + "scroll=#{@doc_def['scroll']}&" if @doc_def['scroll']
15
+ base_url = base_url + "zoom=#{@doc_def['zoom']}&" if @doc_def['zoom']
16
+ base_url = base_url + "show_user=#{@doc_def['show_user']}&" if @doc_def['show_user']
17
+ base_url = base_url + "pin_location=#{@doc_def['pin_location']}&" if @doc_def['pin_location']
18
+ base_url = base_url + "title_location=#{@doc_def['title_location']}&" if @doc_def['title_location']
19
+ base_url = base_url + "subtitle_location=#{@doc_def['subtitle_location']}&" if @doc_def['subtitle_location']
20
+ base_url = base_url + "url_location=#{@doc_def['url_location']}&" if @doc_def['url_location']
21
+ base_url = base_url + "api_key=#{@doc_def['api_key']}&" if @doc_def['api_key']
22
+ base_url = base_url + "next_uri=#{@doc_def['next_uri']}&" if @doc_def['next_uri']
23
+
24
+ if @doc_def['annotations']
25
+ annotations = ""
26
+ index = 0
27
+ @doc_def['annotations'].each do |annotation|
28
+ annotation.each do |k,v|
29
+ annotations = annotations + "annotations[#{index}][#{k}]=#{v}&"
30
+ end
31
+ index = index + 1
32
+ end
33
+ base_url = base_url + annotations
34
+ end
35
+
36
+
37
+ %>
38
+
39
+ <a href="<%= base_url %>"><%= @doc_def['text'] %></a>
@@ -0,0 +1,2 @@
1
+ <div class="panel">
2
+ <%@content.each_line do |line|%><%= " " + line%><%end%></div>
@@ -0,0 +1,11 @@
1
+ <div <%= "class=\"#{@doc_def['div_class']}\"" if @doc_def['div_class']%> >
2
+ <label <%= "class=\"#{@doc_def['label_class']}\"" if @doc_def['label_class']%> ><%=@doc_def['label']%></label>
3
+ <input
4
+ type="password"
5
+ <%= "name=\"#{@doc_def['name']}\"" if @doc_def['name']%>
6
+ <%= "class=\"#{@doc_def['value_class']}\"" if @doc_def['value_class']%>
7
+ <%= "value=\"#{@doc_def['value']}\"" if @doc_def['value']%>
8
+ <%= "disabled" if not @doc_def['editable'].nil? and not @doc_def['editable'] %>
9
+ >
10
+ </input>
11
+ </div>
@@ -0,0 +1,14 @@
1
+ <div <%= "class=\"#{@doc_def['div_class']}\"" if @doc_def['div_class']%> >
2
+ <label <%= "class=\"#{@doc_def['label_class']}\"" if @doc_def['label_class']%> ><%=@doc_def['label']%></label>
3
+ <select
4
+ <%= "size=\"#{@doc_def['size']}\"" if @doc_def['size'] %>
5
+ <%= "class=\"#{@doc_def['class']}\"" if @doc_def['class'] %>
6
+ <%= "multiple=\"yes\"" if @doc_def['allow_multi'] %>
7
+ <%= "disabled" if not @doc_def['editable'].nil? and not @doc_def['editable'] %>
8
+
9
+ >
10
+ <% @doc_def['values'].each do |value| %>
11
+ <option <%= "selected=\"yes\"" if @doc_def['value'] == value %>><%= value %></option>
12
+ <% end %>
13
+ </select>
14
+ </div>
@@ -0,0 +1,4 @@
1
+ <input type="submit"
2
+ <%= "name=\"#{@doc_def['name']}\"" if @doc_def['name']%>
3
+ class="<%= @doc_def['value_class'].nil? ? "standardButton" : @doc_def['value_class'] %>"
4
+ <%= "value=\"#{@doc_def['value']}\"" if @doc_def['value']%> />
@@ -0,0 +1,3 @@
1
+ <table
2
+ <%= "class=\"#{@doc_def['class']}\"" if @doc_def['class'] %> >
3
+ <%@content.each_line do |line|%><%= " " + line%><%end%></table>
@@ -0,0 +1 @@
1
+ <%= click_to_call @doc_def['number'], @doc_def['text'] %>
@@ -0,0 +1,4 @@
1
+ <div <%= "class=\"#{@doc_def['div_class']}\"" if @doc_def['div_class']%> >
2
+ <label <%= "class=\"#{@doc_def['label_class']}\"" if @doc_def['label_class']%> ><%=@doc_def['label']%></label>
3
+ <span <%= "class=\"#{@doc_def['value_class']}\"" if @doc_def['value_class']%>><%=@doc_def['value']%></span>
4
+ </div>
@@ -0,0 +1,10 @@
1
+ <textarea
2
+ type="textarea"
3
+ <%= "name=\"#{@doc_def['name']}\"" if @doc_def['name']%>
4
+ <%= "class=\"#{@doc_def['value_class']}\"" if @doc_def['value_class']%>
5
+ <%= "value=\"#{@doc_def['value']}\"" if @doc_def['value']%>
6
+ <%= "rows=\"#{@doc_def['rows']}\"" if @doc_def['rows']%>
7
+ <%= "cols=\"#{@doc_def['cols']}\"" if @doc_def['cols']%>
8
+ <%= "disabled" if not @doc_def['editable'].nil? and not @doc_def['editable'] %>
9
+ >
10
+ </textarea>
@@ -0,0 +1,11 @@
1
+ <div <%= "class=\"#{@doc_def['div_class']}\"" if @doc_def['div_class']%> >
2
+ <label <%= "class=\"#{@doc_def['label_class']}\"" if @doc_def['label_class']%> ><%=@doc_def['label']%></label>
3
+ <input
4
+ type="text"
5
+ <%= "name=\"#{@doc_def['name']}\"" if @doc_def['name']%>
6
+ <%= "class=\"#{@doc_def['value_class']}\"" if @doc_def['value_class']%>
7
+ <%= "value=\"#{@doc_def['value']}\"" if @doc_def['value']%>
8
+ <%= "disabled" if not @doc_def['editable'].nil? and not @doc_def['editable'] %>
9
+ >
10
+ </input>
11
+ </div>
@@ -0,0 +1,3 @@
1
+ <div id="<%= @doc_def["divid"].nil? ? "pageTitle" : @doc_def["divid"] %>">
2
+ <h1><%= @doc_def["title"] %></h1>
3
+ </div>
@@ -0,0 +1,4 @@
1
+ <div id="toolbar">
2
+ <a href="<%= @doc_def["lefturi"] %>"><%= @doc_def["lefttext"] %></a>
3
+ <a href="<%= @doc_def["righturi"] %>"><%= @doc_def["righttext"] %></a>
4
+ </div>
@@ -0,0 +1,8 @@
1
+ <div id="toolbar">
2
+ <div id="leftItem"
3
+ class="<%= @doc_def["leftclass"].nil? ? "regularButton" : @doc_def["leftclass"] %>"
4
+ ><a href="<%= @doc_def["lefturi"] %>"><%= @doc_def["lefttext"] %></a></div>
5
+ <div id="rightItem"
6
+ class="<%= @doc_def["rightclass"].nil? ? "regularButton" : @doc_def["rightclass"] %>"
7
+ ><a href="<%= @doc_def["righturi"] %>"><%= @doc_def["righttext"] %></a></div>
8
+ </div>
@@ -0,0 +1 @@
1
+ <%=@content%>
@@ -0,0 +1,39 @@
1
+ module RhodesTranslator
2
+ module Translator
3
+ # Return the translated html for a
4
+ # given a view action and view definition
5
+ def translate(view_def, action='')
6
+ @content = ''
7
+ view_def['children'] ||= []
8
+ view_def['children'].each do |child|
9
+ @content += self.translate(child,action) unless child.nil?
10
+ end
11
+ load_erb(view_def,action)
12
+ end
13
+ # returns compiled erb with specified def
14
+ def load_erb(doc_def,action)
15
+ @action = action
16
+ @doc_def = doc_def
17
+
18
+ require 'rho/rhoviewhelpers'
19
+
20
+
21
+ file = File.join(Rho::RhoFSConnector.get_app_path('app'),
22
+ 'templates',
23
+ "#{doc_def['type']}_erb.iseq")
24
+
25
+
26
+ file = File.join(File.dirname(File.join(__rhoGetCurrentDir(), __FILE__)),
27
+
28
+ 'templates',
29
+ "#{doc_def['type']}_erb.iseq") unless File.exist? file
30
+
31
+ retval = ""
32
+
33
+ retval = eval_compiled_file(file, binding ) if File.exist? file
34
+
35
+ retval
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,99 @@
1
+ module RhodesTranslator
2
+ module Validation
3
+ VALIDATORS = {
4
+ 'required' => '^.+$',
5
+ 'number' => '[0-9]+',
6
+ 'currency' => '[0-9]+\.[0-9][0-9]',
7
+ 'email' => '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$',
8
+ 'phone' => '^[0-9\- ]+$'
9
+ }
10
+
11
+ def validate(metadata, params)
12
+ @errors = nil
13
+
14
+ # action = metadata
15
+ #
16
+ # if action.nil?
17
+ # @errors = ["Unable to determine action"]
18
+ # return @errors
19
+ # end
20
+ #
21
+ # metadata = metadata[action] unless metadata.nil?
22
+ if metadata.nil?
23
+ @errors = ["No metadata found"]
24
+ return @errors
25
+ end
26
+
27
+ @errors = []
28
+
29
+ self.validate_data(metadata,params)
30
+ unless @errors.empty?
31
+ return @errors
32
+ end
33
+ end
34
+
35
+ def validate_data(metadata,params)
36
+ metadata['children'] ||= []
37
+ metadata['children'].each do |child|
38
+ self.validate_data(child,params)
39
+ end
40
+
41
+ unless metadata['validation'].nil?
42
+ if metadata['name'].nil?
43
+ @errors << "Metadata element has validation with no name"
44
+ return
45
+ end
46
+
47
+ if params[metadata['name']].nil?
48
+ @errors << "No value submitted for metadata element with name #{metadata['name']}"
49
+ return
50
+ end
51
+
52
+ value = params[metadata['name']]
53
+
54
+
55
+ return if value.to_s == "" and (metadata['validation']['validators'].nil? or not metadata['validation']['validators'].include? "required")
56
+
57
+ unless metadata['validation']['regexp'].nil?
58
+ unless value =~ Regexp.new(metadata['validation']['regexp'])
59
+ @errors << "#{metadata['label']} did not pass regexp validation"
60
+ end
61
+ end
62
+
63
+ unless metadata['validation']['validators'].nil?
64
+ metadata['validation']['validators'].each do |validator|
65
+ unless value =~ Regexp.new(RhodesTranslator::Validation::VALIDATORS[validator])
66
+ @errors << "#{metadata['label']} did not pass validation #{validator}"
67
+ end
68
+ end
69
+ end
70
+
71
+ unless metadata['validation']['min_len'].nil?
72
+ if value.length < metadata['validation']['min_len'].to_i
73
+ @errors << "#{metadata['label']} too short"
74
+ end
75
+ end
76
+
77
+ unless metadata['validation']['max_len'].nil?
78
+ if value.length > metadata['validation']['max_len'].to_i
79
+ @errors << "#{metadata['label']} too long"
80
+ end
81
+ end
82
+
83
+ unless metadata['validation']['min_value'].nil?
84
+ if value.to_i < metadata['validation']['min_value'].to_i
85
+ @errors << "#{metadata['label']} too small"
86
+ end
87
+ end
88
+
89
+ unless metadata['validation']['max_value'].nil?
90
+ if value.to_i > metadata['validation']['max_value'].to_i
91
+ @errors << "#{metadata['label']} too large"
92
+ end
93
+ end
94
+
95
+ end
96
+ end
97
+
98
+ end
99
+ end
@@ -0,0 +1,169 @@
1
+ require File.join(File.dirname(__FILE__),'spec_helper')
2
+ $:.unshift File.join(__FILE__,'..','lib')
3
+ require 'rhodes_translator'
4
+ include RhodesTranslator::Binding
5
+ describe "Binding" do
6
+
7
+ it_should_behave_like "RhodesTranslatorHelper"
8
+
9
+ before(:each) do
10
+ #@b = RhodesTranslator::Binding.new
11
+ end
12
+
13
+ it "should handle hashes" do
14
+ textfieldbind = { 'label' => 'Address',
15
+ 'value' => '{{first_name}} {{last_name}}',
16
+ 'name' => 'address1',
17
+ 'type' => 'text',
18
+ 'type_class' => 'show_text' }
19
+
20
+ data = {'first_name' => 'Some', 'last_name' => 'Name'}
21
+
22
+ (bind(data,textfieldbind))['value'].should == "Some Name"
23
+ end
24
+
25
+ it "should handle nested hashes" do
26
+ textfieldbind = { 'label' => 'Address',
27
+ 'value' => '{{user1/first_name}} {{user1/last_name}}',
28
+ 'name' => 'address1',
29
+ 'type' => 'text',
30
+ 'type_class' => 'show_text' }
31
+
32
+ data = {
33
+ 'baduser' => {'first_name' => 'Not', 'last_name' => 'Me'},
34
+ 'user1' => {'first_name' => 'Some', 'last_name' => 'Name'}
35
+ }
36
+
37
+ (bind(data,textfieldbind))['value'].should == "Some Name"
38
+ end
39
+
40
+ it "should be an error for bad hash key" do
41
+ textfieldbind = { 'label' => 'Address',
42
+ 'value' => '{{bad_key}}',
43
+ 'name' => 'address1',
44
+ 'type' => 'text',
45
+ 'type_class' => 'show_text' }
46
+
47
+ data = {'first_name' => 'Some', 'last_name' => 'Name'}
48
+
49
+ (bind(data,textfieldbind))['value'].should == "INVALID KEY"
50
+
51
+ end
52
+
53
+ it "should handle arrays" do
54
+ textfieldbind = { 'label' => 'Address',
55
+ 'value' => '{{1/first_name}} {{1/last_name}}',
56
+ 'name' => 'address1',
57
+ 'type' => 'text',
58
+ 'type_class' => 'show_text' }
59
+
60
+ data = [ {'first_name' => 'Not', 'last_name' => 'Me'},
61
+ {'first_name' => 'Some', 'last_name' => 'Name'} ]
62
+
63
+ (bind(data,textfieldbind))['value'].should == "Some Name"
64
+ end
65
+
66
+ it "should handle objects" do
67
+ textfieldbind = { 'label' => 'Address',
68
+ 'value' => '{{0/first_name}} {{0/last_name}}',
69
+ 'name' => 'address1',
70
+ 'type' => 'text',
71
+ 'type_class' => 'show_text' }
72
+ class TestObject
73
+ def first_name
74
+ 'Not'
75
+ end
76
+ def last_name
77
+ 'Me'
78
+ end
79
+ end
80
+
81
+ testobj = TestObject.new
82
+ data = [ testobj ,
83
+ {'first_name' => 'Some', 'last_name' => 'Name'} ]
84
+
85
+ (bind(data,textfieldbind))['value'].should == "Not Me"
86
+
87
+ end
88
+
89
+ it "should handle have error for object" do
90
+ textfieldbind = { 'label' => 'Address',
91
+ 'value' => '{{0/first}} {{0/last_name}}',
92
+ 'name' => 'address1',
93
+ 'type' => 'text',
94
+ 'type_class' => 'show_text' }
95
+ class TestObject
96
+ def first_name
97
+ 'Not'
98
+ end
99
+ def last_name
100
+ 'Me'
101
+ end
102
+ end
103
+
104
+ testobj = TestObject.new
105
+ data = [ testobj ,
106
+ {'first_name' => 'Some', 'last_name' => 'Name'} ]
107
+
108
+ (bind(data,textfieldbind))['value'].should == "INVALID DATA TYPE Me"
109
+
110
+ end
111
+
112
+
113
+ it "should be an error for a non-integer array index" do
114
+ textfieldbind = { 'label' => 'Address',
115
+ 'value' => '{{user1/first_name}}',
116
+ 'name' => 'address1',
117
+ 'type' => 'text',
118
+ 'type_class' => 'show_text' }
119
+
120
+ data = [ {'first_name' => 'Not', 'last_name' => 'Me'},
121
+ {'first_name' => 'Some', 'last_name' => 'Name'} ]
122
+
123
+ (bind(data,textfieldbind))['value'].should == "INVALID INDEX"
124
+ end
125
+
126
+ it "should be an error for invalid index" do
127
+ textfieldbind = { 'label' => 'Address',
128
+ 'value' => '{{9/first_name}}',
129
+ 'name' => 'address1',
130
+ 'type' => 'text',
131
+ 'type_class' => 'show_text' }
132
+
133
+ data = [ {'first_name' => 'Not', 'last_name' => 'Me'},
134
+ {'first_name' => 'Some', 'last_name' => 'Name'} ]
135
+
136
+ (bind(data,textfieldbind))['value'].should == "INVALID INDEX"
137
+ end
138
+
139
+
140
+ it "should expand repeatables" do
141
+ row3 = { 'label' => '{{/names/0/first_name}}',
142
+ 'value' => '{{first_name}}, {{last_name}}',
143
+ 'name' => 'address2',
144
+ 'type' => 'labeledrow' }
145
+
146
+
147
+ table = { 'label' => 'Table',
148
+ 'type' => 'table',
149
+ 'children' => [ row3 ],
150
+ 'repeatable' => '{{names}}' }
151
+
152
+
153
+
154
+ view = { 'title' => 'IUI meta panel',
155
+ 'type' => 'iuipanel',
156
+ 'children' => [table] }
157
+
158
+ data = {'names' => [ {'first_name' => 'Not', 'last_name' => 'Me'},
159
+ {'first_name' => 'Some', 'last_name' => 'Name'} ] }
160
+ bind(data,view)
161
+
162
+ view['children'][0]['children'][0]['label'].should == "Not"
163
+ view['children'][0]['children'][0]['value'].should == "Not, Me"
164
+ view['children'][0]['children'][1]['label'].should == "Not"
165
+ view['children'][0]['children'][1]['value'].should == "Some, Name"
166
+
167
+
168
+ end
169
+ end
@@ -0,0 +1,46 @@
1
+ $:.unshift File.join(__FILE__,'..','lib')
2
+ require 'rhodes_translator'
3
+ require 'stubs'
4
+
5
+ describe "RhodesTranslatorHelper", :shared => true do
6
+ before(:each) do
7
+ @textfield = { 'label' => 'Address',
8
+ 'value' => '5th St.',
9
+ 'name' => 'address1',
10
+ 'type' => 'text',
11
+ 'type_class' => 'show_text' }
12
+
13
+
14
+ @numberfield = { 'label' => 'Some Number',
15
+ 'value' => 12345,
16
+ 'name' => 'number1',
17
+ 'type' => 'number',
18
+ 'type_class' => 'show_number' }
19
+
20
+ @panel1 = { 'title' => 'Some Panel',
21
+ 'type' => 'panel',
22
+ 'children' => [@textfield] }
23
+
24
+ @panel2 = { 'title' => 'Some Panel',
25
+ 'type' => 'panel',
26
+ 'children' => [@textfield] }
27
+ @panel3 = { 'title' => 'Some Panel',
28
+ 'type' => 'panel',
29
+ 'children' => [@panel2] }
30
+
31
+ @view1 = { 'title' => 'View 1',
32
+ 'type' => 'view',
33
+ 'children' => [@panel1,@panel2] }
34
+
35
+ @view2 = { 'title' => 'View 2',
36
+ 'type' => 'view',
37
+ 'children' => [@view1,@view1] }
38
+ @complex = { 'title' => 'View 2',
39
+ 'type' => 'view',
40
+ 'children' => [@textfield,@view2,@panel3,@textfield] }
41
+ end
42
+
43
+ def get_template(name)
44
+ File.join(File.dirname(__FILE__),'expected',"#{name}")
45
+ end
46
+ end
data/spec/stubs.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'erb'
2
+
3
+ module RhodesTranslator
4
+ module Translator
5
+
6
+ def load_erb(doc_def,action)
7
+ @action = action
8
+ @doc_def = doc_def
9
+ file = File.join(File.dirname(__FILE__),
10
+ '..',
11
+ 'lib',
12
+ 'rhodes_translator',
13
+ 'templates',"#{doc_def['type']}.erb")
14
+ ERB.new(open(file).read).result(binding)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ require File.join(File.dirname(__FILE__),'spec_helper')
2
+ $:.unshift File.join(__FILE__,'..','lib')
3
+ require 'rhodes_translator'
4
+ include RhodesTranslator::Translator
5
+
6
+ describe "Translator" do
7
+
8
+ it_should_behave_like "RhodesTranslatorHelper"
9
+
10
+ before(:each) do
11
+ # @t = RhodesTranslator::Translator.new
12
+ end
13
+
14
+ it "should translate show view with nested div" do
15
+ expected = open(get_template('view_show.html')).read
16
+ translate(@view1).split.join('').should == expected.split.join('')
17
+ end
18
+
19
+ it "should translate textfield show action" do
20
+ expected = open(get_template('text_show.html')).read
21
+ translate(@textfield).should == expected
22
+ end
23
+
24
+ it "should handle nested views" do
25
+ expected = open(get_template('nest_show.html')).read
26
+ translate(@view2).should == expected
27
+ end
28
+
29
+ it "should handle complex templates" do
30
+ expected = open(get_template('complex_show.html')).read
31
+ translate(@complex).should == expected
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,212 @@
1
+ require File.join(File.dirname(__FILE__),'spec_helper')
2
+ $:.unshift File.join(__FILE__,'..','lib')
3
+ require 'rhodes_translator'
4
+ include RhodesTranslator::Validation
5
+ describe "Validation" do
6
+
7
+ it_should_behave_like "RhodesTranslatorHelper"
8
+
9
+ before(:each) do
10
+ #@v = RhodesTranslator::Validation.new
11
+ @meta = { 'label' => 'Address',
12
+ 'value' => '123 fake st',
13
+ 'name' => 'address1',
14
+ 'validation' => {
15
+ }
16
+ }
17
+
18
+ end
19
+
20
+ it "should validate using custom regexp" do
21
+
22
+ @meta['validation']['regexp'] = '123 fake st'
23
+
24
+ data = {'address1' => '123 fake st'}
25
+
26
+
27
+ validate(@meta,data).should == nil
28
+
29
+ data = {'address1' => 'bad data'}
30
+
31
+ validate(@meta,data).length.should == 1
32
+ end
33
+
34
+ it "should have required validator" do
35
+
36
+ data = {'address1' => ''}
37
+ @meta['validation']['validators'] = ['required']
38
+
39
+ validate(@meta,data).length.should == 1
40
+
41
+ data = {'address1' => 'required'}
42
+
43
+ validate(@meta,data).should == nil
44
+ end
45
+
46
+ it "should have number validator" do
47
+ @meta['validation']['validators'] = ['number']
48
+ data = {'address1' => '1234'}
49
+
50
+ validate(@meta,data).should == nil
51
+
52
+ data = {'address1' => 'not a number'}
53
+
54
+ validate(@meta,data).length.should == 1
55
+
56
+ end
57
+
58
+ it "should have currency validator" do
59
+ @meta['validation']['validators'] = ['currency']
60
+ data = {'address1' => '10.00'}
61
+
62
+ validate(@meta,data).should == nil
63
+
64
+ data = {'address1' => '123'}
65
+
66
+ validate(@meta,data).length.should == 1
67
+
68
+ end
69
+
70
+ it "should have email validator" do
71
+ @meta['validation']['validators'] = ['email']
72
+ data = {'address1' => 'blah@blah.com'}
73
+
74
+ validate(@meta,data).should == nil
75
+
76
+ data = {'address1' => 'not an email'}
77
+
78
+ validate(@meta,data).length.should == 1
79
+
80
+ end
81
+
82
+ it "should have phone validator" do
83
+ @meta['validation']['validators'] = ['phone']
84
+ data = {'address1' => '408-555-1212'}
85
+
86
+ validate(@meta,data).should == nil
87
+
88
+ data = {'address1' => 'not an phone'}
89
+
90
+ validate(@meta,data).length.should == 1
91
+
92
+ end
93
+
94
+ it "should have min_len validator" do
95
+ @meta['validation']['min_len'] = 10
96
+ data = {'address1' => '1234567890'}
97
+
98
+ validate(@meta,data).should == nil
99
+
100
+ data = {'address1' => '12345'}
101
+
102
+ validate(@meta,data).length.should == 1
103
+
104
+ end
105
+
106
+ it "should have max_len validator" do
107
+ @meta['validation']['max_len'] = 10
108
+ data = {'address1' => '12345'}
109
+
110
+ validate(@meta,data).should == nil
111
+
112
+ data = {'address1' => '12345678901'}
113
+
114
+ validate(@meta,data).length.should == 1
115
+
116
+ end
117
+
118
+ it "should have min_value validator" do
119
+ @meta['validation']['min_value'] = 10
120
+ data = {'address1' => '12'}
121
+
122
+ validate(@meta,data).should == nil
123
+
124
+ data = {'address1' => '2'}
125
+
126
+ validate(@meta,data).length.should == 1
127
+
128
+ end
129
+
130
+ it "should have max_value validator" do
131
+ @meta['validation']['max_value'] = 10
132
+ data = {'address1' => '9'}
133
+
134
+ validate(@meta,data).should == nil
135
+
136
+ data = {'address1' => '11'}
137
+
138
+ validate(@meta,data).length.should == 1
139
+
140
+ end
141
+
142
+ it "should handle multiple errors" do
143
+ @address1 = { 'label' => 'Address',
144
+ 'value' => '123 fake st',
145
+ 'name' => 'address1',
146
+ 'validation' => {
147
+ 'validators' => ['required']
148
+ }
149
+ }
150
+
151
+ @address2 = { 'label' => 'Address',
152
+ 'value' => '123 fake st',
153
+ 'name' => 'address2',
154
+ 'validation' => {
155
+ 'max_value' => 15,
156
+ 'min_value' => 10
157
+ }
158
+ }
159
+
160
+ @address3 = { 'label' => 'Address',
161
+ 'value' => '123 fake st',
162
+ 'name' => 'address3',
163
+ 'validation' => {
164
+ 'max_value' => 20,
165
+ 'min_value' => 12
166
+ }
167
+ }
168
+
169
+ @meta = { 'children' => [@address1, @address2, @address3] }
170
+
171
+ data = {'address1' => '11', 'address2' => '12', 'address3' =>'17'}
172
+ validate(@meta,data).should == nil
173
+
174
+ data = {'address1' => '', 'address2' => '12', 'address3' =>'17'}
175
+ validate(@meta,data).length.should == 1
176
+
177
+ data = {'address1' => '', 'address2' => '9', 'address3' =>'17'}
178
+ validate(@meta,data).length.should == 2
179
+
180
+ data = {'address1' => '', 'address2' => '9', 'address3' =>'22'}
181
+ validate(@meta,data).length.should == 3
182
+
183
+ end
184
+
185
+ it "should have an error for nil metadata" do
186
+ data = {'address1' => '12'}
187
+
188
+ validate(nil,data)[0].should == "No metadata found"
189
+ end
190
+
191
+ it "should have an error for validation with no name" do
192
+ @meta = { 'label' => 'Address',
193
+ 'validation' => {
194
+ 'validators' => ['required']
195
+ }
196
+ }
197
+
198
+
199
+ data = {'address1' => '12'}
200
+
201
+ validate(@meta,data)[0].should == "Metadata element has validation with no name"
202
+
203
+ end
204
+
205
+ it "should have an error name with no value" do
206
+ data = {'address111' => '12'}
207
+
208
+ validate(@meta,data)[0].should == "No value submitted for metadata element with name address1"
209
+
210
+ end
211
+
212
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rhodes-translator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rhomobile
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-06-07 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Extension that provides metadata capability for the Rhodes framework
17
+ email: dev@rhomobile.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/rhodes_translator.rb
26
+ - lib/rhodes_translator/binding.rb
27
+ - lib/rhodes_translator/templates/checkbox.erb
28
+ - lib/rhodes_translator/templates/content.erb
29
+ - lib/rhodes_translator/templates/form.erb
30
+ - lib/rhodes_translator/templates/hidden.erb
31
+ - lib/rhodes_translator/templates/iuipanel.erb
32
+ - lib/rhodes_translator/templates/labeledinputli.bb.erb
33
+ - lib/rhodes_translator/templates/labeledinputli.erb
34
+ - lib/rhodes_translator/templates/labeledrow.erb
35
+ - lib/rhodes_translator/templates/labeledvalueli.bb.erb
36
+ - lib/rhodes_translator/templates/labeledvalueli.erb
37
+ - lib/rhodes_translator/templates/link.erb
38
+ - lib/rhodes_translator/templates/link_row.erb
39
+ - lib/rhodes_translator/templates/linkli.bb.erb
40
+ - lib/rhodes_translator/templates/linkli.erb
41
+ - lib/rhodes_translator/templates/list.bb.erb
42
+ - lib/rhodes_translator/templates/list.erb
43
+ - lib/rhodes_translator/templates/maplink.erb
44
+ - lib/rhodes_translator/templates/panel.erb
45
+ - lib/rhodes_translator/templates/password.erb
46
+ - lib/rhodes_translator/templates/select.erb
47
+ - lib/rhodes_translator/templates/submit.erb
48
+ - lib/rhodes_translator/templates/table.erb
49
+ - lib/rhodes_translator/templates/telephone.erb
50
+ - lib/rhodes_translator/templates/text.erb
51
+ - lib/rhodes_translator/templates/textarea.erb
52
+ - lib/rhodes_translator/templates/textinput.erb
53
+ - lib/rhodes_translator/templates/title.erb
54
+ - lib/rhodes_translator/templates/toolbar.bb.erb
55
+ - lib/rhodes_translator/templates/toolbar.erb
56
+ - lib/rhodes_translator/templates/view.erb
57
+ - lib/rhodes_translator/translator.rb
58
+ - lib/rhodes_translator/validation.rb
59
+ has_rdoc: true
60
+ homepage: http://rhomobile.com/
61
+ licenses: []
62
+
63
+ post_install_message:
64
+ rdoc_options:
65
+ - --charset=UTF-8
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ version:
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 1.3.5
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: Rhodes Metadata
87
+ test_files:
88
+ - spec/binding_spec.rb
89
+ - spec/spec_helper.rb
90
+ - spec/stubs.rb
91
+ - spec/translator_spec.rb
92
+ - spec/validator_spec.rb