rhodes-translator 0.0.1

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.
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