volt 0.9.0.pre7 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7b1a1de6a4ca5bb3040697994dc02235caef5df1
4
- data.tar.gz: 560933928252e51c201ffc9f0167d7a81255c415
3
+ metadata.gz: 1a09dcf76510b9f9be2a538e6dfc437cf74ccd1b
4
+ data.tar.gz: c6982a5ceaf9fd3a4ae463f185141e789bd93fb9
5
5
  SHA512:
6
- metadata.gz: 55024841e17f8e8f267f5728f5ed46ac81254c29c4fb3f494a840b2c337d5cbe901204bdac3396380465460b03cc2ebcaabc886d6a77b234ec50ce96d1b4a6be
7
- data.tar.gz: 72dccab3dfa677e6b444e152ca9b3654cf48317de5a65a2ac2494b6084bc862301dbedce6d8663a803c0e46b0bb0167a5549f042724c768975877f6fc89d7c94
6
+ metadata.gz: ba21338f15fece2dbfa90951956f9a73e93ead112259ffc87e7944a9f43368412f66f319fe265117b67d43bf783813058c3e1ea9b1b11403a666353718d4ee38
7
+ data.tar.gz: 2eb8459d1199bf301536c79335d1554ca7f84211251b5c772bef6637ee4440107bd1260880593537c656179d11c2580618b1d1c2495bad9ef9e43a2c4d95e369
data/CHANGELOG.md CHANGED
@@ -4,7 +4,7 @@
4
4
  ### Added
5
5
  - the permissions api has been added!
6
6
  - added has_many and belongs_to on models. See docs.
7
- - you can now serve http/rest from Volt. Thanks to @jfahrer for his great work. Docs coming soon.
7
+ - you can now serve http/rest from Volt. Thanks to @jfahrer for his great work. More docs coming soon.
8
8
  - there is now a generator for controllers and HttpControllers.
9
9
  - fixed generated component code
10
10
  - added .order for sorting on the data store (since .sort is a ruby Enum method)
data/README.md CHANGED
@@ -1,3 +1,4 @@
1
+ [![Gratipay](http://img.shields.io/gratipay/voltframework.svg)](https://www.gratipay.com/voltframework/)
1
2
  [![Gem Version](https://badge.fury.io/rb/volt.svg)](http://badge.fury.io/rb/volt)
2
3
  [![Code Climate](https://codeclimate.com/github/voltrb/volt/badges/gpa.svg)](https://codeclimate.com/github/voltrb/volt)
3
4
  [![Build Status](http://img.shields.io/travis/voltrb/volt/master.svg?style=flat)](https://travis-ci.org/voltrb/volt)
@@ -12,7 +13,8 @@ Instead of syncing data between the client and server via HTTP, Volt uses a pers
12
13
  Pages HTML is written in a template language where you can put Ruby between `{{` and `}}`. Volt uses data flow/reactive programming to automatically and intelligently propagate changes to the DOM (or any other code wanting to know when a value updates). When something in the DOM changes, Volt intelligently updates only the nodes that need to be changed.
13
14
 
14
15
  See some demo videos here:
15
- - [Volt Todos Example](https://www.youtube.com/watch?v=Tg-EtRnMz7o)
16
+ - [Volt Todos Example](https://www.youtube.com/watch?v=KbFtIt7-ge8)
17
+ - [What Is Volt in 6 Minutes](https://www.youtube.com/watch?v=P27EPQ4ne7o)
16
18
  - [Pagination Example](https://www.youtube.com/watch?v=1uanfzMLP9g)
17
19
  - [Routes and Templates](https://www.youtube.com/watch?v=1yNMP3XR6jU)
18
20
  - [Isomorphic App Development - RubyConf 2014](https://www.youtube.com/watch?v=7i6AL7Walc4)
@@ -20,8 +22,8 @@ See some demo videos here:
20
22
  **Note:** The blog video is outdated, expect an updated version soon.
21
23
 
22
24
  Check out demo apps:
23
- - https://github.com/voltrb/todos3
24
- - https://github.com/voltrb/contactsdemo
25
+ - https://github.com/voltrb/todomvc
26
+ - https://github.com/voltrb/blog5
25
27
 
26
28
  # Docs
27
29
 
@@ -33,4 +35,5 @@ There is also a [work in progress tutorial](https://github.com/rhgraysonii/volt_
33
35
 
34
36
  You want to contribute? Great! Thanks for being awesome! At the moment, we have a big internal todo list, hop on https://gitter.im/voltrb/volt so we don't duplicate work. Pull requests are always welcome, but asking about helping on Gitter should save some duplication.
35
37
 
36
- [![Pledgie](https://pledgie.com/campaigns/26731.png?skin_name=chrome)](https://pledgie.com/campaigns/26731)
38
+
39
+ [![Gratipay](//img.shields.io/gratipay/voltframework.svg)](https://www.gratipay.com/voltframework/)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.0.pre7
1
+ 0.9.0
@@ -7,57 +7,58 @@ module Volt
7
7
  def save!(&block)
8
8
  # TODO: this shouldn't need to be run, but if no attributes are assigned, then
9
9
  # if needs to be run. Maybe there's a better way to handle it.
10
- validate!
11
-
12
- # Get errors from validate
13
- errors = self.errors.to_h
14
-
15
- result = nil
10
+ return validate!.then do
11
+
12
+ # Get errors from validate
13
+ errors = self.errors.to_h
14
+
15
+ result = nil
16
+
17
+ if errors.size == 0
18
+ save_to = options[:save_to]
19
+ if save_to
20
+ if save_to.is_a?(ArrayModel)
21
+ # Add to the collection
22
+ promise = save_to.append(attributes)
23
+ else
24
+ # We have a saved model
25
+ promise = save_to.assign_attributes(attributes)
26
+ end
16
27
 
17
- if errors.size == 0
18
- save_to = options[:save_to]
19
- if save_to
20
- if save_to.is_a?(ArrayModel)
21
- # Add to the collection
22
- promise = save_to.append(attributes)
23
- else
24
- # We have a saved model
25
- promise = save_to.assign_attributes(attributes)
26
- end
28
+ result = promise.then do |new_model|
29
+ # The main model saved, so mark the buffer as not new
30
+ @new = false
27
31
 
28
- result = promise.then do |new_model|
29
- # The main model saved, so mark the buffer as not new
30
- @new = false
32
+ if new_model
33
+ # Mark the model as loaded
34
+ new_model.change_state_to(:loaded_state, :loaded)
31
35
 
32
- if new_model
33
- # Mark the model as loaded
34
- new_model.change_state_to(:loaded_state, :loaded)
36
+ # Set the buffer's id to track the main model's id
37
+ attributes[:_id] = new_model._id
38
+ options[:save_to] = new_model
39
+ end
35
40
 
36
- # Set the buffer's id to track the main model's id
37
- attributes[:_id] = new_model._id
38
- options[:save_to] = new_model
39
- end
41
+ nil
42
+ end.fail do |errors|
43
+ if errors.is_a?(Hash)
44
+ server_errors.replace(errors)
45
+ end
40
46
 
41
- nil
42
- end.fail do |errors|
43
- if errors.is_a?(Hash)
44
- server_errors.replace(errors)
47
+ promise_for_errors(errors)
45
48
  end
46
-
47
- promise_for_errors(errors)
49
+ else
50
+ fail 'Model is not a buffer, can not be saved, modifications should be persisted as they are made.'
48
51
  end
49
52
  else
50
- fail 'Model is not a buffer, can not be saved, modifications should be persisted as they are made.'
53
+ # Some errors, mark all fields
54
+ result = promise_for_errors(errors)
51
55
  end
52
- else
53
- # Some errors, mark all fields
54
- result = promise_for_errors(errors)
55
- end
56
56
 
57
- # If passed a block, call then on it with the block.
58
- result = result.then(&block) if block
57
+ # If passed a block, call then on it with the block.
58
+ result = result.then(&block) if block
59
59
 
60
- return result
60
+ result
61
+ end
61
62
  end
62
63
 
63
64
  # When errors come in, we mark all fields and return a rejected promise.
@@ -152,12 +152,17 @@ module Volt
152
152
  # Save the changes
153
153
  if initial_setup
154
154
  # Run initial validation
155
- errs = Volt.in_mode?(:no_validate) ? nil : validate!
156
-
157
- if errs && errs.size > 0
158
- return Promise.new.reject(errs)
155
+ if Volt.in_mode?(:no_validate)
156
+ # No validate, resolve nil
157
+ Promise.new.resolve(nil)
159
158
  else
160
- return Promise.new.resolve(nil)
159
+ return validate!.then do |errs|
160
+ if errs && errs.size > 0
161
+ Promise.new.reject(errs)
162
+ else
163
+ Promise.new.resolve(nil)
164
+ end
165
+ end
161
166
  end
162
167
  else
163
168
  return run_changed
@@ -404,51 +409,56 @@ module Volt
404
409
  # @return [Promise|nil] a promise for when the save is
405
410
  # complete
406
411
  def run_changed(attribute_name=nil)
407
- result = nil
408
-
409
412
  # no_validate mode should only be used internally. no_validate mode is a
410
413
  # performance optimization that prevents validation from running after each
411
414
  # change when assigning multile attributes.
412
415
  unless Volt.in_mode?(:no_validate)
413
416
  # Run the validations for all fields
414
- validate!
415
-
416
- # Buffers are allowed to be in an invalid state
417
- unless buffer?
418
- # First check that all local validations pass
419
- if error_in_changed_attributes?
420
- # Some errors are present, revert changes
421
- revert_changes!
422
-
423
- # After we revert, we need to validate again to get the error messages back
424
- # TODO: Could probably cache the previous errors.
425
- errs = validate!
426
-
427
- result = Promise.new.reject(errs)
428
- else
429
- # No errors, tell the persistor to handle the change (usually save)
430
-
431
- # Don't save right now if we're in a nosave block
432
- unless Volt.in_mode?(:no_save)
433
- # the changed method on a persistor should return a promise that will
434
- # be resolved when the save is complete, or fail with a hash of errors.
435
- if @persistor
436
- result = @persistor.changed(attribute_name)
437
- else
438
- result = Promise.new.resolve(nil)
417
+ result = nil
418
+ return validate!.then do
419
+
420
+ # Buffers are allowed to be in an invalid state
421
+ unless buffer?
422
+ # First check that all local validations pass
423
+ if error_in_changed_attributes?
424
+ # Some errors are present, revert changes
425
+ revert_changes!
426
+
427
+ # After we revert, we need to validate again to get the error messages back
428
+ # TODO: Could probably cache the previous errors.
429
+ result = validate!.then do
430
+ # Reject the promise with the errors
431
+ Promise.new.reject(errs)
432
+ end
433
+ else
434
+ # No errors, tell the persistor to handle the change (usually save)
435
+
436
+ # Don't save right now if we're in a nosave block
437
+ unless Volt.in_mode?(:no_save)
438
+ # the changed method on a persistor should return a promise that will
439
+ # be resolved when the save is complete, or fail with a hash of errors.
440
+ if @persistor
441
+ result = @persistor.changed(attribute_name)
442
+ else
443
+ result = Promise.new.resolve(nil)
444
+ end
445
+
446
+ # Saved, no longer new
447
+ @new = false
448
+
449
+ # Clear the change tracking
450
+ clear_tracked_changes!
439
451
  end
440
-
441
- # Saved, no longer new
442
- @new = false
443
-
444
- # Clear the change tracking
445
- clear_tracked_changes!
446
452
  end
447
453
  end
454
+
455
+ # Return result inside of the validate! promise
456
+ result
448
457
  end
449
458
  end
450
459
 
451
- return result
460
+ # Didn't run validations
461
+ return nil
452
462
  end
453
463
  end
454
464
  end
@@ -82,16 +82,18 @@ module Volt
82
82
  def validate!
83
83
  errors.clear
84
84
 
85
- run_validations
85
+ run_validations.then do
86
86
 
87
- # See if any server errors are in place and merge them in if they are
88
- if Volt.client?
89
- errors.merge!(server_errors.to_h)
87
+ # See if any server errors are in place and merge them in if they are
88
+ if Volt.client?
89
+ errors.merge!(server_errors.to_h)
90
+ end
91
+ end.then do
92
+ run_custom_validations
93
+ end.then do
94
+ # Return the errors object
95
+ errors
90
96
  end
91
-
92
- run_custom_validations
93
-
94
- errors
95
97
  end
96
98
 
97
99
  # Returns true if any of the changed fields now has an error
@@ -111,7 +113,10 @@ module Volt
111
113
  private
112
114
 
113
115
  # Runs through each of the normal validations.
116
+ # @return [Promise] a promsie to run all validations
114
117
  def run_validations
118
+ promise = Promise.new.resolve(nil)
119
+
115
120
  validations = self.class.validations
116
121
  if validations
117
122
 
@@ -123,8 +128,12 @@ module Volt
123
128
  klass = validation_class(validation, args)
124
129
 
125
130
  if klass
126
- result = klass.validate(self, field_name, args)
127
- errors.merge!(result)
131
+ # Chain on the promises
132
+ promise = promise.then do
133
+ klass.validate(self, field_name, args)
134
+ end.then do |errs|
135
+ errors.merge!(errs)
136
+ end
128
137
  else
129
138
  fail "validation type #{validation} is not specified."
130
139
  end
@@ -132,19 +141,26 @@ module Volt
132
141
  end
133
142
  end
134
143
 
135
- errors
144
+ return promise
136
145
  end
137
146
 
138
147
  def run_custom_validations
148
+ promise = Promise.new.resolve(nil)
139
149
  # Call all of the custom validations
140
150
  custom_validations = self.class.custom_validations
141
151
  if custom_validations
142
152
  custom_validations.each do |custom_validation|
143
- # Run the validator in the context of the model
144
- result = instance_exec(&custom_validation)
145
- errors.merge!(result)
153
+ # Add to the promise chain
154
+ promise = promise.then do
155
+ # Run the validator in the context of the model
156
+ instance_exec(&custom_validation)
157
+ end.then do |errs|
158
+ errors.merge!(errs)
159
+ end
146
160
  end
147
161
  end
162
+
163
+ return promise
148
164
  end
149
165
 
150
166
  def validation_class(validation, args)
@@ -68,7 +68,7 @@ module Volt
68
68
  current_value = value
69
69
  end
70
70
 
71
- if current_value && !current_value.nil? && !current_value.is_a?(Exception)
71
+ if current_value && !current_value.is_a?(Exception)
72
72
  # This branch is currently true
73
73
  true_template = template_name
74
74
  break
@@ -85,7 +85,6 @@ module Volt
85
85
  remove_starting_controller
86
86
  else
87
87
  # None of the actions stopped the chain
88
-
89
88
  # Wait until the controller is loaded before we actually render.
90
89
  @waiting_for_load = -> { @starting_controller_handler.controller.loaded? }.watch_until!(true) do
91
90
  render_next_template(full_path, path)
@@ -4,7 +4,7 @@ module Volt
4
4
 
5
5
  def initialize(controller, action)
6
6
  @controller = controller
7
- @action = action.to_sym
7
+ @action = action.to_sym if action
8
8
  end
9
9
 
10
10
  def call_action(stage_prefix=nil, stage_suffix=nil)
@@ -57,9 +57,7 @@ module Volt
57
57
  unless @invalidated
58
58
  @invalidated = true
59
59
 
60
- unless @stopped || @computing
61
- queue_flush!
62
- end
60
+ queue_flush! unless @stopped
63
61
 
64
62
  invalidations = @invalidations
65
63
  @invalidations = []
@@ -15,6 +15,19 @@ describe Volt::Model do
15
15
  end
16
16
  end
17
17
 
18
+ let(:test_model_with_promises) do
19
+ Class.new(Volt::Model) do
20
+ attr_accessor :ran_promise
21
+ validate do
22
+
23
+ Promise.new.then do
24
+ self.ran_promise = true
25
+ {name: 'Invalid'}
26
+ end
27
+ end
28
+ end
29
+ end
30
+
18
31
  it 'should return errors for all failed validations' do
19
32
  model.validate!
20
33
  expect(model.errors).to eq(
@@ -37,6 +50,15 @@ describe Volt::Model do
37
50
  )
38
51
  end
39
52
 
53
+ it 'should resolve promises returned from inside of validations' do
54
+ model = test_model_with_promises.new
55
+
56
+ model.validate!.then do |errs|
57
+ expect(errs).to eq({name: 'Invalid'})
58
+ expect(model.ran_promise).to eq(true)
59
+ end
60
+ end
61
+
40
62
  describe 'builtin validations' do
41
63
  shared_examples_for 'a built in validation' do |field, message|
42
64
  specify do
@@ -150,10 +150,10 @@ describe Volt::Computation do
150
150
  describe 'when computing' do
151
151
  before(:each) { computation.instance_variable_set :@computing, true }
152
152
 
153
- it "doesn't add self to flush queue" do
153
+ it "should still add itself to flush queue" do
154
154
  computation.invalidate!
155
155
 
156
- expect(Volt::Computation.class_variable_get :@@flush_queue).to be_empty
156
+ expect(Volt::Computation.class_variable_get :@@flush_queue).not_to be_empty
157
157
  end
158
158
  end
159
159
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: volt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0.pre7
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Stout
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-16 00:00:00.000000000 Z
11
+ date: 2015-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -827,9 +827,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
827
827
  version: '0'
828
828
  required_rubygems_version: !ruby/object:Gem::Requirement
829
829
  requirements:
830
- - - ">"
830
+ - - ">="
831
831
  - !ruby/object:Gem::Version
832
- version: 1.3.1
832
+ version: '0'
833
833
  requirements: []
834
834
  rubyforge_project:
835
835
  rubygems_version: 2.4.5