volt 0.8.14 → 0.8.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/Readme.md +8 -2
  4. data/VERSION +1 -1
  5. data/app/volt/controllers/notices_controller.rb +1 -1
  6. data/app/volt/models/user.rb +2 -2
  7. data/app/volt/tasks/live_query/live_query_pool.rb +1 -1
  8. data/app/volt/tasks/query_tasks.rb +1 -1
  9. data/app/volt/tasks/store_tasks.rb +1 -1
  10. data/app/volt/tasks/user_tasks.rb +2 -2
  11. data/lib/volt/boot.rb +2 -2
  12. data/lib/volt/cli/asset_compile.rb +31 -27
  13. data/lib/volt/cli.rb +64 -65
  14. data/lib/volt/config.rb +25 -23
  15. data/lib/volt/console.rb +17 -16
  16. data/lib/volt/controllers/model_controller.rb +82 -80
  17. data/lib/volt/data_stores/data_store.rb +2 -2
  18. data/lib/volt/data_stores/mongo_driver.rb +2 -2
  19. data/lib/volt/extra_core/inflections.rb +2 -2
  20. data/lib/volt/extra_core/inflector/inflections.rb +185 -183
  21. data/lib/volt/extra_core/inflector/methods.rb +50 -48
  22. data/lib/volt/extra_core/string.rb +2 -2
  23. data/lib/volt/models/array_model.rb +93 -92
  24. data/lib/volt/models/cursor.rb +3 -2
  25. data/lib/volt/models/model.rb +248 -251
  26. data/lib/volt/models/model_hash_behaviour.rb +44 -44
  27. data/lib/volt/models/model_helpers.rb +38 -36
  28. data/lib/volt/models/model_state.rb +16 -17
  29. data/lib/volt/models/model_wrapper.rb +25 -24
  30. data/lib/volt/models/persistors/array_store.rb +145 -143
  31. data/lib/volt/models/persistors/base.rb +18 -16
  32. data/lib/volt/models/persistors/flash.rb +24 -22
  33. data/lib/volt/models/persistors/local_store.rb +46 -44
  34. data/lib/volt/models/persistors/model_identity_map.rb +10 -8
  35. data/lib/volt/models/persistors/model_store.rb +76 -76
  36. data/lib/volt/models/persistors/params.rb +19 -17
  37. data/lib/volt/models/persistors/query/query_listener.rb +65 -63
  38. data/lib/volt/models/persistors/query/query_listener_pool.rb +12 -10
  39. data/lib/volt/models/persistors/store.rb +28 -28
  40. data/lib/volt/models/persistors/store_factory.rb +12 -10
  41. data/lib/volt/models/persistors/store_state.rb +33 -31
  42. data/lib/volt/models/url.rb +96 -104
  43. data/lib/volt/models/validations.rb +56 -54
  44. data/lib/volt/models/validators/length_validator.rb +24 -22
  45. data/lib/volt/models/validators/presence_validator.rb +14 -12
  46. data/lib/volt/page/bindings/attribute_binding.rb +106 -106
  47. data/lib/volt/page/bindings/base_binding.rb +23 -21
  48. data/lib/volt/page/bindings/component_binding.rb +3 -1
  49. data/lib/volt/page/bindings/content_binding.rb +34 -34
  50. data/lib/volt/page/bindings/each_binding.rb +113 -113
  51. data/lib/volt/page/bindings/event_binding.rb +38 -34
  52. data/lib/volt/page/bindings/if_binding.rb +56 -54
  53. data/lib/volt/page/bindings/template_binding/grouped_controllers.rb +24 -22
  54. data/lib/volt/page/bindings/template_binding.rb +182 -185
  55. data/lib/volt/page/channel.rb +79 -77
  56. data/lib/volt/page/channel_stub.rb +29 -27
  57. data/lib/volt/page/document.rb +6 -5
  58. data/lib/volt/page/document_events.rb +54 -52
  59. data/lib/volt/page/page.rb +139 -138
  60. data/lib/volt/page/string_template_renderer.rb +36 -36
  61. data/lib/volt/page/sub_context.rb +26 -25
  62. data/lib/volt/page/targets/attribute_section.rb +27 -25
  63. data/lib/volt/page/targets/attribute_target.rb +7 -6
  64. data/lib/volt/page/targets/base_section.rb +27 -26
  65. data/lib/volt/page/targets/binding_document/base_node.rb +3 -1
  66. data/lib/volt/page/targets/binding_document/component_node.rb +85 -82
  67. data/lib/volt/page/targets/binding_document/html_node.rb +11 -9
  68. data/lib/volt/page/targets/dom_section.rb +78 -77
  69. data/lib/volt/page/targets/dom_target.rb +8 -6
  70. data/lib/volt/page/targets/dom_template.rb +90 -88
  71. data/lib/volt/page/targets/helpers/comment_searchers.rb +51 -49
  72. data/lib/volt/page/tasks.rb +59 -57
  73. data/lib/volt/page/template_renderer.rb +17 -14
  74. data/lib/volt/page/url_tracker.rb +26 -24
  75. data/lib/volt/reactive/computation.rb +87 -88
  76. data/lib/volt/reactive/dependency.rb +30 -28
  77. data/lib/volt/reactive/eventable.rb +64 -62
  78. data/lib/volt/reactive/hash_dependency.rb +25 -23
  79. data/lib/volt/reactive/reactive_accessors.rb +34 -32
  80. data/lib/volt/reactive/reactive_array.rb +162 -162
  81. data/lib/volt/reactive/reactive_hash.rb +37 -35
  82. data/lib/volt/router/routes.rb +99 -101
  83. data/lib/volt/server/component_handler.rb +20 -21
  84. data/lib/volt/server/component_templates.rb +72 -70
  85. data/lib/volt/server/html_parser/attribute_scope.rb +109 -99
  86. data/lib/volt/server/html_parser/each_scope.rb +17 -16
  87. data/lib/volt/server/html_parser/if_view_scope.rb +51 -49
  88. data/lib/volt/server/html_parser/sandlebars_parser.rb +184 -177
  89. data/lib/volt/server/html_parser/textarea_scope.rb +24 -22
  90. data/lib/volt/server/html_parser/view_handler.rb +66 -65
  91. data/lib/volt/server/html_parser/view_parser.rb +23 -21
  92. data/lib/volt/server/html_parser/view_scope.rb +142 -141
  93. data/lib/volt/server/rack/asset_files.rb +81 -79
  94. data/lib/volt/server/rack/component_code.rb +17 -15
  95. data/lib/volt/server/rack/component_html_renderer.rb +14 -12
  96. data/lib/volt/server/rack/component_paths.rb +72 -71
  97. data/lib/volt/server/rack/index_files.rb +36 -39
  98. data/lib/volt/server/rack/opal_files.rb +43 -41
  99. data/lib/volt/server/rack/source_map_server.rb +23 -21
  100. data/lib/volt/server/socket_connection_handler.rb +46 -45
  101. data/lib/volt/server/socket_connection_handler_stub.rb +21 -19
  102. data/lib/volt/server.rb +60 -58
  103. data/lib/volt/spec/setup.rb +3 -3
  104. data/lib/volt/tasks/dispatcher.rb +24 -23
  105. data/lib/volt/tasks/task_handler.rb +35 -33
  106. data/lib/volt/utils/ejson.rb +8 -6
  107. data/lib/volt/utils/generic_counting_pool.rb +33 -31
  108. data/lib/volt/utils/generic_pool.rb +73 -70
  109. data/lib/volt/utils/local_storage.rb +42 -38
  110. data/lib/volt/volt/environment.rb +1 -1
  111. data/lib/volt.rb +44 -42
  112. data/spec/apps/kitchen_sink/app/main/assets/css/todos.css +28 -0
  113. data/spec/apps/kitchen_sink/app/main/config/routes.rb +1 -0
  114. data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +2 -2
  115. data/spec/apps/kitchen_sink/app/main/controllers/todos_controller.rb +17 -0
  116. data/spec/apps/kitchen_sink/app/main/views/main/main.html +1 -0
  117. data/spec/apps/kitchen_sink/app/main/views/todos/index.html +24 -0
  118. data/spec/apps/kitchen_sink/config.ru +1 -1
  119. data/spec/controllers/reactive_accessors_spec.rb +5 -5
  120. data/spec/extra_core/inflector_spec.rb +2 -2
  121. data/spec/integration/list_spec.rb +68 -0
  122. data/spec/models/model_spec.rb +57 -57
  123. data/spec/models/persistors/params_spec.rb +6 -6
  124. data/spec/models/persistors/store_spec.rb +7 -7
  125. data/spec/models/validations_spec.rb +3 -3
  126. data/spec/page/bindings/content_binding_spec.rb +7 -7
  127. data/spec/page/bindings/template_binding_spec.rb +4 -5
  128. data/spec/page/sub_context_spec.rb +2 -2
  129. data/spec/reactive/computation_spec.rb +10 -10
  130. data/spec/reactive/dependency_spec.rb +2 -2
  131. data/spec/reactive/eventable_spec.rb +4 -4
  132. data/spec/reactive/reactive_array_spec.rb +13 -13
  133. data/spec/router/routes_spec.rb +5 -5
  134. data/spec/server/html_parser/sandlebars_parser_spec.rb +9 -9
  135. data/spec/server/html_parser/view_parser_spec.rb +27 -27
  136. data/spec/server/rack/asset_files_spec.rb +5 -5
  137. data/spec/server/rack/component_paths_spec.rb +2 -2
  138. data/spec/tasks/live_query_spec.rb +2 -2
  139. data/spec/tasks/query_tasks.rb +1 -1
  140. data/spec/tasks/query_tracker_spec.rb +1 -1
  141. data/spec/templates/targets/binding_document/component_node_spec.rb +2 -2
  142. data/spec/utils/generic_counting_pool_spec.rb +2 -2
  143. data/spec/utils/generic_pool_spec.rb +2 -2
  144. data/templates/component/controllers/main_controller.rb +1 -1
  145. data/templates/model/model.rb.tt +2 -2
  146. data/templates/newgem/app/newgem/controllers/main_controller.rb.tt +2 -2
  147. data/templates/project/app/main/controllers/main_controller.rb +1 -1
  148. data/templates/project/config.ru +1 -1
  149. metadata +10 -3
  150. data/app/volt/assets/js/vertxbus.js +0 -216
@@ -1,40 +1,40 @@
1
1
  require 'volt/models/persistors/base'
2
2
  require 'volt/models/persistors/model_identity_map'
3
3
 
4
- module Persistors
5
- class Store < Base
4
+ module Volt
5
+ module Persistors
6
+ class Store < Base
6
7
 
7
- @@identity_map = ModelIdentityMap.new
8
+ @@identity_map = ModelIdentityMap.new
8
9
 
9
- def initialize(model, tasks=nil)
10
- @tasks = tasks
11
- @model = model
10
+ def initialize(model, tasks=nil)
11
+ @tasks = tasks
12
+ @model = model
12
13
 
13
- @saved = false
14
- end
15
-
16
- def saved?
17
- @saved
18
- end
19
-
20
- # On stores, we store the model so we don't have to look it up
21
- # every time we do a read.
22
- def read_new_model(method_name)
23
- # On stores, plural associations are automatically assumed to be
24
- # collections.
25
- options = @model.options.merge(parent: @model, path: @model.path + [method_name])
26
- if method_name.plural?
27
- model = @model.new_array_model([], options)
28
- else
29
- model = @model.new_model(nil, options)
30
-
31
- # TODO: Might not need to assign this
32
- @model.attributes ||= {}
33
- @model.attributes[method_name] = model
14
+ @saved = false
34
15
  end
35
16
 
17
+ def saved?
18
+ @saved
19
+ end
36
20
 
37
- return model
21
+ # On stores, we store the model so we don't have to look it up
22
+ # every time we do a read.
23
+ def read_new_model(method_name)
24
+ # On stores, plural associations are automatically assumed to be
25
+ # collections.
26
+ options = @model.options.merge(parent: @model, path: @model.path + [method_name])
27
+ if method_name.plural?
28
+ model = @model.new_array_model([], options)
29
+ else
30
+ model = @model.new_model(nil, options)
31
+
32
+ # TODO: Might not need to assign this
33
+ @model.attributes ||= {}
34
+ @model.attributes[method_name] = model
35
+ end
36
+ model
37
+ end
38
38
  end
39
39
  end
40
40
  end
@@ -1,14 +1,16 @@
1
- module Persistors
2
- class StoreFactory
3
- def initialize(tasks)
4
- @tasks = tasks
5
- end
1
+ module Volt
2
+ module Persistors
3
+ class StoreFactory
4
+ def initialize(tasks)
5
+ @tasks = tasks
6
+ end
6
7
 
7
- def new(model)
8
- if model.is_a?(ArrayModel)
9
- ArrayStore.new(model, @tasks)
10
- else
11
- ModelStore.new(model, @tasks)
8
+ def new(model)
9
+ if model.is_a?(ArrayModel)
10
+ ArrayStore.new(model, @tasks)
11
+ else
12
+ ModelStore.new(model, @tasks)
13
+ end
12
14
  end
13
15
  end
14
16
  end
@@ -1,37 +1,39 @@
1
- # StoreState provides method for a store to track its loading state.
2
- module StoreState
3
-
4
- # Called when a collection loads
5
- def loaded(initial_state=nil)
6
- change_state_to(initial_state || :not_loaded)
7
- end
8
-
9
- def state
10
- @state_dep ||= Dependency.new
11
- @state_dep.depend
12
-
13
- return @state
14
- end
15
-
16
- # Called from the QueryListener when the data is loaded
17
- def change_state_to(new_state, skip_trigger=false)
18
- old_state = @state
19
- @state = new_state
20
-
21
- # Trigger changed on the 'state' method
22
- unless skip_trigger
23
- if old_state != @state
24
- @state_dep.changed! if @state_dep
1
+ module Volt
2
+ module Persistors
3
+ # StoreState provides method for a store to track its loading state.
4
+ module StoreState
5
+
6
+ # Called when a collection loads
7
+ def loaded(initial_state=nil)
8
+ change_state_to(initial_state || :not_loaded)
25
9
  end
26
- end
27
10
 
28
- if @state == :loaded && @fetch_promises
29
- # Trigger each waiting fetch
30
- @fetch_promises.compact.each {|fp| fp.resolve(@model) }
31
- @fetch_promises = nil
11
+ def state
12
+ @state_dep ||= Dependency.new
13
+ @state_dep.depend
14
+ @state
15
+ end
32
16
 
33
- stop_listening
17
+ # Called from the QueryListener when the data is loaded
18
+ def change_state_to(new_state, skip_trigger=false)
19
+ old_state = @state
20
+ @state = new_state
21
+
22
+ # Trigger changed on the 'state' method
23
+ unless skip_trigger
24
+ if old_state != @state
25
+ @state_dep.changed! if @state_dep
26
+ end
27
+ end
28
+
29
+ if @state == :loaded && @fetch_promises
30
+ # Trigger each waiting fetch
31
+ @fetch_promises.compact.each { |fp| fp.resolve(@model) }
32
+ @fetch_promises = nil
33
+
34
+ stop_listening
35
+ end
36
+ end
34
37
  end
35
38
  end
36
-
37
39
  end
@@ -1,124 +1,117 @@
1
1
  # The url class handles parsing and updating the url
2
2
  require 'volt/reactive/reactive_accessors'
3
+ module Volt
4
+ class URL
5
+ include ReactiveAccessors
3
6
 
4
- class URL
5
- include ReactiveAccessors
7
+ # TODO: we need to make it so change events only trigger on changes
8
+ reactive_accessor :scheme, :host, :port, :path, :query, :params, :fragment
9
+ attr_accessor :router
6
10
 
7
- # TODO: we need to make it so change events only trigger on changes
8
- reactive_accessor :scheme, :host, :port, :path, :query, :params, :fragment
9
- attr_accessor :router
10
-
11
- def initialize(router=nil)
12
- @router = router
13
- @params = Model.new({}, persistor: Persistors::Params)
14
- end
11
+ def initialize(router = nil)
12
+ @router = router
13
+ @params = Model.new({}, persistor: Persistors::Params)
14
+ end
15
15
 
16
- # Parse takes in a url and extracts each sections.
17
- # It also assigns and changes to the params.
18
- def parse(url)
19
- if url[0] == '#'
20
- # url only updates fragment
21
- self.fragment = url[1..-1]
22
- update!
23
- else
24
- host = `document.location.host`
25
- protocol = `document.location.protocol`
26
-
27
- if url !~ /[:]\/\//
28
- # Add the host for local urls
29
- url = protocol + "//#{host}" + url
16
+ # Parse takes in a url and extracts each sections.
17
+ # It also assigns and changes to the params.
18
+ def parse(url)
19
+ if url[0] == '#'
20
+ # url only updates fragment
21
+ self.fragment = url[1..-1]
22
+ update!
30
23
  else
31
- # Make sure its on the same protocol and host, otherwise its external.
32
- if url !~ /#{protocol}\/\/#{host}/
33
- # Different host, don't process
34
- return false
24
+ host = `document.location.host`
25
+ protocol = `document.location.protocol`
26
+
27
+ if url !~ /[:]\/\//
28
+ # Add the host for local urls
29
+ url = protocol + "//#{host}" + url
30
+ else
31
+ # Make sure its on the same protocol and host, otherwise its external.
32
+ if url !~ /#{protocol}\/\/#{host}/
33
+ # Different host, don't process
34
+ return false
35
+ end
35
36
  end
36
- end
37
37
 
38
- matcher = url.match(/^(#{protocol[0..-2]})[:]\/\/([^\/]+)(.*)$/)
39
- self.scheme = matcher[1]
40
- host, port = matcher[2].split(':')
38
+ matcher = url.match(/^(#{protocol[0..-2]})[:]\/\/([^\/]+)(.*)$/)
39
+ self.scheme = matcher[1]
40
+ self.host, port = matcher[2].split(':')
41
41
 
42
- self.host = host
43
- self.port = (port || 80).to_i
42
+ self.port = (port || 80).to_i
44
43
 
45
- path = matcher[3]
46
- path, fragment = path.split('#', 2)
47
- path, query = path.split('?', 2)
44
+ path = matcher[3]
45
+ path, fragment = path.split('#', 2)
46
+ path, query = path.split('?', 2)
48
47
 
49
- self.path = path
50
- self.fragment = fragment
51
- self.query = query
48
+ self.path = path
49
+ self.fragment = fragment
50
+ self.query = query
52
51
 
53
- assign_query_hash_to_params
54
- end
52
+ assign_query_hash_to_params
53
+ end
55
54
 
56
- scroll
55
+ scroll
57
56
 
58
- return true
59
- end
57
+ return true
58
+ end
60
59
 
61
- # Full url rebuilds the url from it's constituent parts
62
- def full_url
63
- if port && port != 80
64
- host_with_port = "#{host}:#{port}"
65
- else
60
+ # Full url rebuilds the url from it's constituent parts
61
+ def full_url
66
62
  host_with_port = host
67
- end
63
+ host_with_port += ":#{port}" if port && port != 80
68
64
 
69
- path, params = @router.params_to_url(@params.to_h)
65
+ self.path, params = @router.params_to_url(@params.to_h)
70
66
 
71
- self.path = path if path
67
+ new_url = "#{scheme}://#{host_with_port}#{path.chomp('/')}"
72
68
 
73
- new_url = "#{scheme}://#{host_with_port}#{(path || self.path).chomp('/')}"
69
+ # Add query params
70
+ params_str = ''
71
+ unless params.empty?
72
+ query_parts = []
73
+ nested_params_hash(params).each_pair do |key, value|
74
+ # remove the _ from the front
75
+ value = `encodeURI(value)`
76
+ query_parts << "#{key[1..-1]}=#{value}"
77
+ end
74
78
 
75
- params_str = ''
76
- unless params.empty?
77
- query_parts = []
78
- nested_params_hash(params).each_pair do |key,value|
79
- # remove the _ from the front
80
- value = `encodeURI(value)`
81
- query_parts << "#{key[1..-1]}=#{value}"
79
+ if query_parts.size > 0
80
+ self.query = query_parts.join('&')
81
+ new_url += '?' + self.query
82
+ end
82
83
  end
83
84
 
84
- if query_parts.size > 0
85
- self.query = query_parts.join('&')
86
- new_url += '?' + self.query
87
- end
88
- end
85
+ # Add fragment
86
+ frag = self.fragment
87
+ new_url += '#' + frag if frag.present?
89
88
 
90
- frag = self.fragment
91
- if frag.present?
92
- self.fragment = frag
93
- new_url += '#' + frag
89
+ return new_url
94
90
  end
95
91
 
96
- return new_url
97
- end
98
-
99
- # Called when the state has changed and the url in the
100
- # browser should be updated
101
- # Called when an attribute changes to update the url
102
- def update!
103
- if Volt.client?
104
- new_url = full_url()
92
+ # Called when the state has changed and the url in the
93
+ # browser should be updated
94
+ # Called when an attribute changes to update the url
95
+ def update!
96
+ if Volt.client?
97
+ new_url = full_url()
105
98
 
106
- # Push the new url if pushState is supported
107
- # TODO: add fragment fallback
108
- %x{
99
+ # Push the new url if pushState is supported
100
+ # TODO: add fragment fallback
101
+ %x{
109
102
  if (document.location.href != new_url && history && history.pushState) {
110
103
  history.pushState(null, null, new_url);
111
104
  }
112
105
  }
106
+ end
113
107
  end
114
- end
115
108
 
116
- def scroll
117
- if Volt.client?
118
- frag = self.fragment
119
- if frag
120
- # Scroll to anchor via http://www.w3.org/html/wg/drafts/html/master/browsers.html#scroll-to-fragid
121
- %x{
109
+ def scroll
110
+ if Volt.client?
111
+ frag = self.fragment
112
+ if frag
113
+ # Scroll to anchor via http://www.w3.org/html/wg/drafts/html/master/browsers.html#scroll-to-fragid
114
+ %x{
122
115
  var anchor = $('#' + frag);
123
116
  if (anchor.length == 0) {
124
117
  anchor = $('*[name="' + frag + '"]:first');
@@ -128,14 +121,14 @@ class URL
128
121
  $(document.body).scrollTop(anchor.offset().top);
129
122
  }
130
123
  }
131
- else
132
- # Scroll to the top by default
133
- `$(document.body).scrollTop(0);`
124
+ else
125
+ # Scroll to the top by default
126
+ `$(document.body).scrollTop(0);`
127
+ end
134
128
  end
135
129
  end
136
- end
137
130
 
138
- private
131
+ private
139
132
  # Assigning the params is tricky since we don't want to trigger changed on
140
133
  # any values that have not changed. So we first loop through all current
141
134
  # url params, removing any not present in the params, while also removing
@@ -165,7 +158,7 @@ class URL
165
158
  def assign_from_old(params, new_params)
166
159
  queued_deletes = []
167
160
 
168
- params.attributes.each_pair do |name,old_val|
161
+ params.attributes.each_pair do |name, old_val|
169
162
  # If there is a new value, see if it has [name]
170
163
  new_val = new_params ? new_params[name] : nil
171
164
 
@@ -183,7 +176,7 @@ class URL
183
176
  end
184
177
  end
185
178
 
186
- queued_deletes.each {|name| params.delete(name) }
179
+ queued_deletes.each { |name| params.delete(name) }
187
180
  end
188
181
 
189
182
  # Assign any new params, which weren't in the old params.
@@ -200,10 +193,10 @@ class URL
200
193
 
201
194
  def query_hash
202
195
  query_hash = {}
203
- qury = self.query
196
+ qury = self.query
204
197
  if qury
205
- qury.split('&').reject {|v| v == '' }.each do |part|
206
- parts = part.split('=').reject {|v| v == '' }
198
+ qury.split('&').reject { |v| v == '' }.each do |part|
199
+ parts = part.split('=').reject { |v| v == '' }
207
200
 
208
201
  # Decode string
209
202
  # parts[0] = `decodeURI(parts[0])`
@@ -212,7 +205,7 @@ class URL
212
205
  sections = query_key_sections(parts[0])
213
206
 
214
207
  hash_part = query_hash
215
- sections.each_with_index do |section,index|
208
+ sections.each_with_index do |section, index|
216
209
  if index == sections.size-1
217
210
  # Last part, assign the value
218
211
  hash_part[section] = parts[1]
@@ -231,14 +224,13 @@ class URL
231
224
  # Example:
232
225
  # user[name]=Ryan would parse as [:_user, :_name]
233
226
  def query_key_sections(key)
234
- key.split(/\[([^\]]+)\]/).reject(&:empty?).map {|v| :"_#{v}"}
227
+ key.split(/\[([^\]]+)\]/).reject(&:empty?).map { |v| :"_#{v}" }
235
228
  end
236
229
 
237
230
  # Generate the key for a nested param attribute
238
231
  def query_key(path)
239
232
  i = 0
240
233
  path.map do |v|
241
- # v = v[1..-1]
242
234
  i += 1
243
235
  if i != 1
244
236
  "[#{v}]"
@@ -251,7 +243,7 @@ class URL
251
243
  def nested_params_hash(params, path=[])
252
244
  results = {}
253
245
 
254
- params.each_pair do |key,value|
246
+ params.each_pair do |key, value|
255
247
  unless value.nil?
256
248
  if value.respond_to?(:persistor) && value.persistor && value.persistor.is_a?(Persistors::Params)
257
249
  # TODO: Should be a param
@@ -264,5 +256,5 @@ class URL
264
256
 
265
257
  return results
266
258
  end
267
-
259
+ end
268
260
  end
@@ -2,77 +2,78 @@
2
2
  require 'volt/models/validators/length_validator'
3
3
  require 'volt/models/validators/presence_validator'
4
4
 
5
- # Include in any class to get validation logic
6
- module Validations
7
- module ClassMethods
8
- def validate(field_name, options)
9
- @validations ||= {}
10
- @validations[field_name] = options
11
- end
5
+ module Volt
6
+ # Include in any class to get validation logic
7
+ module Validations
8
+ module ClassMethods
9
+ def validate(field_name, options)
10
+ @validations ||= {}
11
+ @validations[field_name] = options
12
+ end
12
13
 
13
- def validations
14
- @validations
14
+ def validations
15
+ @validations
16
+ end
15
17
  end
16
- end
17
18
 
18
- def self.included(base)
19
- base.send :extend, ClassMethods
20
- end
19
+ def self.included(base)
20
+ base.send :extend, ClassMethods
21
+ end
21
22
 
22
- # Once a field is ready, we can use include_in_errors! to start
23
- # showing its errors.
24
- def mark_field!(field_name, trigger_changed=true)
25
- marked_fields[field_name] = true
26
- end
23
+ # Once a field is ready, we can use include_in_errors! to start
24
+ # showing its errors.
25
+ def mark_field!(field_name, trigger_changed=true)
26
+ marked_fields[field_name] = true
27
+ end
27
28
 
28
- def marked_fields
29
- @marked_fields ||= ReactiveHash.new
30
- end
29
+ def marked_fields
30
+ @marked_fields ||= ReactiveHash.new
31
+ end
31
32
 
32
- def marked_errors
33
- errors(true)
34
- end
33
+ def marked_errors
34
+ errors(true)
35
+ end
35
36
 
36
- # TODO: Errors is being called for any validation change. We should have errors return a
37
- # hash like object that only calls the validation for each one.
38
- def errors(marked_only=false)
39
- errors = {}
37
+ # TODO: Errors is being called for any validation change. We should have errors return a
38
+ # hash like object that only calls the validation for each one.
39
+ def errors(marked_only=false)
40
+ errors = {}
40
41
 
41
- validations = self.class.validations
42
+ validations = self.class.validations
42
43
 
43
- if validations
44
- # Merge into errors, combining any error arrays
45
- merge = Proc.new do |new_errors|
46
- errors.merge!(new_errors) do |key, new_val, old_val|
47
- new_val + old_val
44
+ if validations
45
+ # Merge into errors, combining any error arrays
46
+ merge = Proc.new do |new_errors|
47
+ errors.merge!(new_errors) do |key, new_val, old_val|
48
+ new_val + old_val
49
+ end
48
50
  end
49
- end
50
51
 
51
- # Run through each validation
52
- validations.each_pair do |field_name, options|
53
- if marked_only
54
- # When marked only, skip any validations on non-marked fields
55
- next unless marked_fields[field_name]
56
- end
52
+ # Run through each validation
53
+ validations.each_pair do |field_name, options|
54
+ if marked_only
55
+ # When marked only, skip any validations on non-marked fields
56
+ next unless marked_fields[field_name]
57
+ end
57
58
 
58
- options.each_pair do |validation, args|
59
- # Call the specific validator, then merge the results back
60
- # into one large errors hash.
61
- klass = validation_class(validation, args)
59
+ options.each_pair do |validation, args|
60
+ # Call the specific validator, then merge the results back
61
+ # into one large errors hash.
62
+ klass = validation_class(validation, args)
62
63
 
63
- if klass
64
- validate_with(merge, klass, field_name, args)
65
- else
66
- raise "validation type #{validation} is not specified."
64
+ if klass
65
+ validate_with(merge, klass, field_name, args)
66
+ else
67
+ raise "validation type #{validation} is not specified."
68
+ end
67
69
  end
68
70
  end
69
71
  end
70
- end
71
72
 
72
- return errors
73
- end
73
+ return errors
74
+ end
74
75
 
75
- private
76
+ private
76
77
  # calls the validate method on the class, passing the right arguments.
77
78
  def validate_with(merge, klass, field_name, args)
78
79
  return merge.call(klass.validate(self, field_name, args))
@@ -80,9 +81,10 @@ module Validations
80
81
 
81
82
  def validation_class(validation, args)
82
83
  begin
83
- Object.const_get(:"#{validation.camelize}Validator")
84
+ Volt.const_get(:"#{validation.camelize}Validator")
84
85
  rescue NameError => e
85
86
  puts "Unable to find #{validation} validator"
86
87
  end
87
88
  end
89
+ end
88
90
  end
@@ -1,28 +1,30 @@
1
- class LengthValidator
2
- def self.validate(model, field_name, args)
3
- errors = {}
4
- value = model.send(field_name)
1
+ module Volt
2
+ class LengthValidator
3
+ def self.validate(model, field_name, args)
4
+ errors = {}
5
+ value = model.send(field_name)
5
6
 
6
- if args.is_a?(Fixnum)
7
- min = args
8
- max = nil
9
- message = nil
10
- elsif args.is_a?(Hash)
11
- min = args[:length] || args[:minimum]
12
- max = args[:maximum]
13
- raise "length or minimum must be specified" unless min.is_a?(Fixnum)
7
+ if args.is_a?(Fixnum)
8
+ min = args
9
+ max = nil
10
+ message = nil
11
+ elsif args.is_a?(Hash)
12
+ min = args[:length] || args[:minimum]
13
+ max = args[:maximum]
14
+ raise "length or minimum must be specified" unless min.is_a?(Fixnum)
14
15
 
15
- message = args[:message]
16
- else
17
- raise "The arguments to length must be a number or a hash"
18
- end
16
+ message = args[:message]
17
+ else
18
+ raise "The arguments to length must be a number or a hash"
19
+ end
19
20
 
20
- if !value || value.size < min
21
- errors[field_name] = [message || "must be at least #{args} characters"]
22
- elsif max && value.size > max
23
- errors[field_name] = [message || "must be less than #{args} characters"]
24
- end
21
+ if !value || value.size < min
22
+ errors[field_name] = [message || "must be at least #{args} characters"]
23
+ elsif max && value.size > max
24
+ errors[field_name] = [message || "must be less than #{args} characters"]
25
+ end
25
26
 
26
- return errors
27
+ return errors
28
+ end
27
29
  end
28
30
  end