volt 0.9.4.pre1 → 0.9.4.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/README.md +5 -5
- data/app/volt/models/user.rb +23 -20
- data/app/volt/tasks/user_tasks.rb +1 -14
- data/docs/UPGRADE_GUIDE.md +19 -0
- data/lib/volt/controllers/http_controller.rb +4 -4
- data/lib/volt/controllers/model_controller.rb +2 -2
- data/lib/volt/models/array_model.rb +39 -29
- data/lib/volt/models/associations.rb +7 -0
- data/lib/volt/models/buffer.rb +6 -4
- data/lib/volt/models/field_helpers.rb +4 -2
- data/lib/volt/models/model.rb +5 -3
- data/lib/volt/models/model_helpers/model_change_helpers.rb +15 -3
- data/lib/volt/models/model_helpers/model_helpers.rb +11 -0
- data/lib/volt/models/persistors/array_store.rb +8 -11
- data/lib/volt/models/persistors/model_store.rb +4 -14
- data/lib/volt/models/url.rb +2 -2
- data/lib/volt/page/bindings/event_binding.rb +12 -3
- data/lib/volt/page/bindings/view_binding/controller_handler.rb +2 -2
- data/lib/volt/server/component_templates.rb +8 -3
- data/lib/volt/{controllers/actions.rb → utils/lifecycle_callbacks.rb} +20 -16
- data/lib/volt/version.rb +1 -1
- data/lib/volt/volt/users.rb +29 -2
- data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +12 -0
- data/spec/apps/kitchen_sink/app/main/models/user.rb +7 -0
- data/spec/apps/kitchen_sink/app/main/views/main/bindings.html +6 -0
- data/spec/integration/bindings_spec.rb +19 -0
- data/spec/models/associations_spec.rb +6 -6
- data/spec/models/buffer_spec.rb +19 -1
- data/spec/models/model_helpers/model_helpers_spec.rb +8 -0
- data/spec/models/url_spec.rb +16 -0
- data/spec/models/user_spec.rb +19 -20
- data/spec/models/user_validation_spec.rb +8 -0
- data/spec/{controllers/actions_spec.rb → utils/lifecycle_callbacks_spec.rb} +10 -10
- data/templates/project/app/main/models/user.rb +8 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: acec655ed08b959c64ad4fa1a1d70a8c202d6061
|
4
|
+
data.tar.gz: 16d6eba62257243a2ea66bacfafb64ebd4ece87a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86d429de470cc56e6434e9fe0f0822d840bc4a9c8d9d2e1f686d18c01ba4bb7e709c4de84b4e474d2b9dd00c78968e5b69bb98fc804b038535892557e6b66212
|
7
|
+
data.tar.gz: f5cb8e59e91b908203d7bede6ae2fcaae6e84f091d65e5a61ca6b890a721b2e79edef6bc6bc31a887ac307c1c6b0d59596e4b7b4d1d8dc3c6d40a18b5d2d1984
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
## 0.9.4.pre1
|
4
4
|
### Added
|
5
|
+
- ```root``` can now be called from a model to get the root model on the collection. (So if the model is on store, it will return ```store```)
|
6
|
+
- ```store``` can now be called from inside of a model
|
5
7
|
|
6
8
|
### Changed
|
7
9
|
- fixed bug with ReactiveHash#to_json
|
data/README.md
CHANGED
@@ -7,11 +7,11 @@
|
|
7
7
|
|
8
8
|
For the current status of Volt, read: http://voltframework.com/blog
|
9
9
|
|
10
|
-
Volt is a Ruby web framework where your Ruby code runs on both the server and the client (via [Opal](https://github.com/opal/opal)). The DOM automatically updates as the user interacts with the page. Page state can be stored in the URL. If the user hits a URL directly, the HTML will first be rendered on the server for faster load times and easier indexing by search engines.
|
10
|
+
Volt is a Ruby web framework where your Ruby code runs on both the server and the client (via [Opal](https://github.com/opal/opal)). The DOM automatically updates as the user interacts with the page. Page state can be stored in the URL. If the user hits a URL directly, the HTML will first be rendered on the server for faster load times and easier indexing by search engines. Subsequent local page interactions will be rendered on the client.
|
11
11
|
|
12
12
|
Instead of syncing data between the client and server via HTTP, Volt uses a persistent connection between the client and server. When data is updated on one client, it is updated in the database and any other listening clients (with almost no setup code needed).
|
13
13
|
|
14
|
-
|
14
|
+
Page HTML is written in a templating language where you can put Ruby between `{{` and `}}`. Volt uses data flow/reactive programming to automatically and intelligently propagate changes to the DOM (or to any other code that wants to know when a value has changed). When something in the DOM changes, Volt intelligently updates only the DOM nodes that need to be changed.
|
15
15
|
|
16
16
|
See some demo videos here:
|
17
17
|
- [Volt Todos Example](https://www.youtube.com/watch?v=KbFtIt7-ge8)
|
@@ -43,15 +43,15 @@ Rick Carlino has been putting together some great volt tutorial videos also.
|
|
43
43
|
|
44
44
|
# Getting Help
|
45
45
|
|
46
|
-
Have a question and need help? The volt team watches [stackoverflow](http://stackoverflow.com/search?q=voltrb) for questions and will get back to you quickly. Be sure to post the question with the #voltrb tag. If you have something you
|
46
|
+
Have a question and need help? The volt team watches [stackoverflow](http://stackoverflow.com/search?q=voltrb) for questions and will get back to you quickly. Be sure to post the question with the #voltrb tag. If you have something you'd like to discuss, drop into our [gitter room](https://gitter.im/voltrb/volt).
|
47
47
|
|
48
48
|
# Contributing
|
49
49
|
|
50
|
-
You want to contribute? Great! Thanks for being awesome! At the moment, we have a big internal todo list
|
50
|
+
You want to contribute? Great! Thanks for being awesome! At the moment, we have a big internal todo list. Please hop on https://gitter.im/voltrb/volt so that we don't duplicate work. Pull requests are always welcome, but asking about helping on Gitter should save some duplication.
|
51
51
|
|
52
52
|
# Support
|
53
53
|
|
54
|
-
VoltFramework is currently a labor of love mainly built by a small group of core developers. Donations are always welcome and will help Volt get to production faster :-) Also, if you or your company is interested in sponsoring Volt, please talk to @ryanstout in
|
54
|
+
VoltFramework is currently a labor of love mainly built by a small group of core developers. Donations are always welcome and will help Volt get to production faster :-) Also, if you or your company is interested in sponsoring Volt, please talk to @ryanstout in [gitter](https://gitter.im/voltrb/volt).
|
55
55
|
|
56
56
|
[![Pledgie](https://pledgie.com/campaigns/26731.png?skin_name=chrome)](https://pledgie.com/campaigns/26731)
|
57
57
|
|
data/app/volt/models/user.rb
CHANGED
@@ -2,9 +2,6 @@ require 'bcrypt' unless RUBY_PLATFORM == 'opal'
|
|
2
2
|
|
3
3
|
module Volt
|
4
4
|
class User < Model
|
5
|
-
field :username
|
6
|
-
field :email
|
7
|
-
field :name
|
8
5
|
field :password
|
9
6
|
|
10
7
|
# returns login field name depending on config settings
|
@@ -16,9 +13,6 @@ module Volt
|
|
16
13
|
end
|
17
14
|
end
|
18
15
|
|
19
|
-
validate login_field, unique: true, length: 8
|
20
|
-
validate :email, email: true
|
21
|
-
|
22
16
|
permissions(:read) do
|
23
17
|
# Never pass the hashed_password to the client
|
24
18
|
deny :hashed_password
|
@@ -27,23 +21,32 @@ module Volt
|
|
27
21
|
deny if !id == Volt.current_user_id && !new?
|
28
22
|
end
|
29
23
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
if changed?(:password)
|
34
|
-
# Don't validate on the server
|
35
|
-
validate :password, length: 8
|
36
|
-
end
|
24
|
+
unless RUBY_PLATFORM == 'opal'
|
25
|
+
permissions(:update) do
|
26
|
+
deny unless id == Volt.current_user_id
|
37
27
|
end
|
38
28
|
end
|
39
29
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
30
|
+
validations do
|
31
|
+
# Only validate password when it has changed
|
32
|
+
if changed?(:password)
|
33
|
+
# Don't validate on the server
|
34
|
+
validate :password, length: 8
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# On the server, we hash the password and remove it (so we just store the hash)
|
39
|
+
unless RUBY_PLATFORM == 'opal'
|
40
|
+
before_save :hash_password
|
41
|
+
|
42
|
+
def hash_password
|
43
|
+
password = get('password')
|
44
|
+
|
45
|
+
# Clear the password
|
46
|
+
set('password', nil)
|
47
|
+
|
48
|
+
# Set the hashed_password field instead
|
49
|
+
set('hashed_password', BCrypt::Password.create(password))
|
47
50
|
end
|
48
51
|
end
|
49
52
|
end
|
@@ -16,22 +16,9 @@ class UserTasks < Volt::Task
|
|
16
16
|
|
17
17
|
match_pass = BCrypt::Password.new(user._hashed_password)
|
18
18
|
fail 'Password did not match' unless match_pass == password
|
19
|
-
fail 'app_secret is not configured' unless Volt.config.app_secret
|
20
19
|
|
21
|
-
|
22
|
-
# Salt the user id with the app_secret so the end user can't
|
23
|
-
# tamper with the cookie
|
24
|
-
signature = Digest::SHA256.hexdigest(salty_user_id(user.id))
|
25
|
-
|
26
|
-
# Return user_id:hash on user id
|
27
|
-
next "#{user.id}:#{signature}"
|
20
|
+
next Volt.user_login_signature(user)
|
28
21
|
end
|
29
22
|
end
|
30
23
|
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def salty_user_id(user_id)
|
35
|
-
"#{Volt.config.app_secret}::#{user_id}"
|
36
|
-
end
|
37
24
|
end
|
data/docs/UPGRADE_GUIDE.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
# 0.9.3 to 0.9.4
|
2
|
+
|
3
|
+
We moved logic out of Volt::User and into the generated user file, so it is easier to customize. Add the following to your app/main/models/user.rb:
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
# The login_field method returns the name that should be used for the field
|
7
|
+
# where the users e-mail is stored. (usually :username or :email)
|
8
|
+
def self.login_field
|
9
|
+
:email
|
10
|
+
end
|
11
|
+
|
12
|
+
# login_field is set to :email by default and can be set to
|
13
|
+
field login_field
|
14
|
+
field :name
|
15
|
+
|
16
|
+
validate login_field, unique: true, length: 8
|
17
|
+
validate :email, email: true
|
18
|
+
```
|
19
|
+
|
1
20
|
# 0.9.2 to 0.9.3
|
2
21
|
|
3
22
|
Upgrading from 0.9.2 should be fairly simple, just implement the following:
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'volt/server/rack/http_response_header'
|
2
2
|
require 'volt/server/rack/http_response_renderer'
|
3
|
-
require 'volt/
|
3
|
+
require 'volt/utils/lifecycle_callbacks'
|
4
4
|
|
5
5
|
module Volt
|
6
6
|
# Allow you to create controllers that act as http endpoints
|
7
7
|
class HttpController
|
8
|
-
include
|
8
|
+
include LifecycleCallbacks
|
9
9
|
|
10
10
|
#TODO params is only public for testing
|
11
11
|
attr_accessor :params
|
@@ -23,9 +23,9 @@ module Volt
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def perform(action='index')
|
26
|
-
filtered =
|
26
|
+
filtered = run_callbacks(:before_action, action)
|
27
27
|
send(action.to_sym) unless filtered
|
28
|
-
|
28
|
+
run_callbacks(:after_action, action) unless filtered
|
29
29
|
respond
|
30
30
|
end
|
31
31
|
|
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'volt/reactive/reactive_accessors'
|
2
|
-
require 'volt/
|
2
|
+
require 'volt/utils/lifecycle_callbacks'
|
3
3
|
require 'volt/controllers/template_helpers'
|
4
4
|
require 'volt/controllers/collection_helpers'
|
5
5
|
|
6
6
|
module Volt
|
7
7
|
class ModelController
|
8
8
|
include ReactiveAccessors
|
9
|
-
include
|
9
|
+
include LifecycleCallbacks
|
10
10
|
include CollectionHelpers
|
11
11
|
|
12
12
|
# A model controller will have its
|
@@ -94,40 +94,50 @@ module Volt
|
|
94
94
|
model = wrap_values([model]).first
|
95
95
|
end
|
96
96
|
|
97
|
-
if model.is_a?(Model) && !model.can_create?
|
98
|
-
fail "permissions did not allow create for #{model.inspect}"
|
99
|
-
end
|
100
97
|
|
101
|
-
|
102
|
-
|
98
|
+
if model.is_a?(Model)
|
99
|
+
if !model.can_create?
|
100
|
+
fail "permissions did not allow create for #{model.inspect}"
|
101
|
+
end
|
103
102
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
103
|
+
# Add it to the array and trigger any watches or on events.
|
104
|
+
super(model)
|
105
|
+
|
106
|
+
@persistor.added(model, @array.size - 1)
|
107
|
+
|
108
|
+
# Validate and save
|
109
|
+
promise = model.run_changed.then do
|
110
|
+
# Mark the model as not new
|
111
|
+
model.instance_variable_set('@new', false)
|
112
|
+
|
113
|
+
# Mark the model as loaded
|
114
|
+
model.change_state_to(:loaded_state, :loaded)
|
115
|
+
|
116
|
+
end.fail do |err|
|
117
|
+
# remove from the collection because it failed to save on the server
|
118
|
+
# we don't need to call delete on the server.
|
119
|
+
index = @array.index(model)
|
120
|
+
delete_at(index, true)
|
121
|
+
|
122
|
+
# remove from the id list
|
123
|
+
@persistor.try(:remove_tracking_id, model)
|
124
|
+
|
125
|
+
# re-raise, err might not be an Error object, so we use a rejected promise to re-raise
|
126
|
+
Promise.new.reject(err)
|
127
|
+
end
|
128
|
+
else
|
129
|
+
promise = nil.then do
|
130
|
+
# Add it to the array and trigger any watches or on events.
|
131
|
+
super(model)
|
132
|
+
|
133
|
+
@persistor.added(model, @array.size - 1)
|
126
134
|
end
|
127
135
|
end
|
128
136
|
|
129
|
-
|
130
|
-
|
137
|
+
promise.then do
|
138
|
+
# resolve the model
|
139
|
+
model
|
140
|
+
end
|
131
141
|
end
|
132
142
|
|
133
143
|
# Works like << except it always returns a promise
|
@@ -16,6 +16,13 @@ module Volt
|
|
16
16
|
root.get(method_name.pluralize).where(id: lookup_key).first
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
define_method(:"#{method_name}=") do |obj|
|
21
|
+
id = obj.is_a?(Fixnum) ? obj : obj.id
|
22
|
+
|
23
|
+
# Assign the current model's something_id to the object's id
|
24
|
+
set("#{method_name}_id", id)
|
25
|
+
end
|
19
26
|
end
|
20
27
|
|
21
28
|
def has_many(method_name, remote_key_name = nil)
|
data/lib/volt/models/buffer.rb
CHANGED
@@ -18,7 +18,7 @@ module Volt
|
|
18
18
|
if save_to
|
19
19
|
if save_to.is_a?(ArrayModel)
|
20
20
|
# Add to the collection
|
21
|
-
promise = save_to.
|
21
|
+
promise = save_to.create(attributes)
|
22
22
|
else
|
23
23
|
# We have a saved model
|
24
24
|
promise = save_to.assign_attributes(attributes)
|
@@ -33,11 +33,13 @@ module Volt
|
|
33
33
|
new_model.change_state_to(:loaded_state, :loaded)
|
34
34
|
|
35
35
|
# Set the buffer's id to track the main model's id
|
36
|
-
|
37
|
-
options[:save_to] = new_model
|
36
|
+
options[:save_to] = new_model
|
38
37
|
end
|
39
38
|
|
40
|
-
|
39
|
+
# Copy attributes back from save_to model
|
40
|
+
@attributes = new_model.attributes
|
41
|
+
|
42
|
+
new_model
|
41
43
|
end.fail do |errors|
|
42
44
|
if errors.is_a?(Hash)
|
43
45
|
server_errors.replace(errors)
|
@@ -11,8 +11,10 @@ module FieldHelpers
|
|
11
11
|
end
|
12
12
|
|
13
13
|
if klass
|
14
|
-
# Add type validation
|
15
|
-
|
14
|
+
# Add type validation, execpt for String, since anything can be a string.
|
15
|
+
unless klass == String
|
16
|
+
validate name, type: klass
|
17
|
+
end
|
16
18
|
end
|
17
19
|
|
18
20
|
define_method(name) do
|
data/lib/volt/models/model.rb
CHANGED
@@ -18,6 +18,7 @@ require 'volt/models/associations'
|
|
18
18
|
require 'volt/reactive/class_eventable'
|
19
19
|
require 'volt/utils/event_counter'
|
20
20
|
require 'volt/reactive/reactive_accessors'
|
21
|
+
require 'volt/utils/lifecycle_callbacks'
|
21
22
|
require 'thread'
|
22
23
|
|
23
24
|
module Volt
|
@@ -30,6 +31,7 @@ module Volt
|
|
30
31
|
end
|
31
32
|
|
32
33
|
class Model
|
34
|
+
include LifecycleCallbacks
|
33
35
|
include ModelWrapper
|
34
36
|
include ModelHelpers
|
35
37
|
include ModelHashBehaviour
|
@@ -357,14 +359,14 @@ module Volt
|
|
357
359
|
if initial_setup
|
358
360
|
# Run initial validation
|
359
361
|
if Volt.in_mode?(:no_validate)
|
360
|
-
# No validate, resolve
|
361
|
-
Promise.new.resolve(
|
362
|
+
# No validate, resolve self
|
363
|
+
Promise.new.resolve(self)
|
362
364
|
else
|
363
365
|
return validate!.then do |errs|
|
364
366
|
if errs && errs.size > 0
|
365
367
|
Promise.new.reject(errs)
|
366
368
|
else
|
367
|
-
Promise.new.resolve(
|
369
|
+
Promise.new.resolve(self)
|
368
370
|
end
|
369
371
|
end
|
370
372
|
end
|
@@ -3,7 +3,9 @@
|
|
3
3
|
|
4
4
|
module Volt
|
5
5
|
module ModelChangeHelpers
|
6
|
-
|
6
|
+
def self.included(base)
|
7
|
+
base.setup_action_helpers_in_class(:before_save, :before_validate)
|
8
|
+
end
|
7
9
|
|
8
10
|
# Called when something in the model changes. Saves
|
9
11
|
# the model if there is a persistor, and changes the
|
@@ -38,14 +40,16 @@ module Volt
|
|
38
40
|
end
|
39
41
|
|
40
42
|
# Return result inside of the validate! promise
|
41
|
-
result
|
43
|
+
result.then { self }
|
42
44
|
end
|
43
45
|
end
|
44
46
|
|
45
47
|
# Didn't run validations
|
46
|
-
|
48
|
+
self.then
|
47
49
|
end
|
48
50
|
|
51
|
+
|
52
|
+
private
|
49
53
|
# Should only be called from run_changed. Saves the changes back to the persistor
|
50
54
|
# and clears the tracked changes.
|
51
55
|
def persist_changes(attribute_name)
|
@@ -53,6 +57,14 @@ module Volt
|
|
53
57
|
|
54
58
|
# Don't save right now if we're in a nosave block
|
55
59
|
unless Volt.in_mode?(:no_save)
|
60
|
+
# Call the before_save callback
|
61
|
+
# skip validations when running before_save, this prevents n+1, and allows
|
62
|
+
# the before_save to put the model into an invalid state, which you want
|
63
|
+
# sometimes.
|
64
|
+
Volt::Model.no_validate do
|
65
|
+
run_callbacks(:before_save)
|
66
|
+
end
|
67
|
+
|
56
68
|
# the changed method on a persistor should return a promise that will
|
57
69
|
# be resolved when the save is complete, or fail with a hash of errors.
|
58
70
|
if @persistor
|
@@ -58,6 +58,17 @@ module Volt
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
def store
|
62
|
+
# TODO: Move away from $page
|
63
|
+
$page.store
|
64
|
+
end
|
65
|
+
|
66
|
+
# returns the root model for the collection the model is currently on. So
|
67
|
+
# if the model is persisted somewhere on store, it will return ```store```
|
68
|
+
def root
|
69
|
+
persistor.try(:root_model)
|
70
|
+
end
|
71
|
+
|
61
72
|
|
62
73
|
|
63
74
|
|
@@ -287,24 +287,14 @@ module Volt
|
|
287
287
|
# Called when the client adds an item.
|
288
288
|
def added(model, index)
|
289
289
|
if model.persistor
|
290
|
-
# Tell the persistor it was added, return the promise
|
291
|
-
promise = model.persistor.add_to_collection
|
292
|
-
|
293
290
|
# Track the the model got added
|
294
291
|
@ids[model.id] = true
|
295
|
-
|
296
|
-
promise
|
297
292
|
end
|
298
293
|
end
|
299
294
|
|
300
295
|
# Called when the client removes an item
|
301
296
|
def removed(model)
|
302
|
-
|
303
|
-
# Tell the persistor it was removed
|
304
|
-
model.persistor.remove_from_collection
|
305
|
-
|
306
|
-
@ids.delete(model.id)
|
307
|
-
end
|
297
|
+
remove_tracking_id(model)
|
308
298
|
|
309
299
|
if defined?($loading_models) && $loading_models
|
310
300
|
return
|
@@ -312,6 +302,13 @@ module Volt
|
|
312
302
|
StoreTasks.delete(channel_name, model.attributes[:id])
|
313
303
|
end
|
314
304
|
end
|
305
|
+
|
306
|
+
def remove_tracking_id(model)
|
307
|
+
if model.persistor
|
308
|
+
# Tell the persistor it was removed
|
309
|
+
@ids.delete(model.id)
|
310
|
+
end
|
311
|
+
end
|
315
312
|
end
|
316
313
|
end
|
317
314
|
end
|
@@ -21,18 +21,6 @@ module Volt
|
|
21
21
|
model.change_state_to(:loaded_state, initial_state)
|
22
22
|
end
|
23
23
|
|
24
|
-
def add_to_collection
|
25
|
-
@in_collection = true
|
26
|
-
ensure_setup
|
27
|
-
|
28
|
-
# Call changed, return the promise
|
29
|
-
changed
|
30
|
-
end
|
31
|
-
|
32
|
-
def remove_from_collection
|
33
|
-
@in_collection = false
|
34
|
-
end
|
35
|
-
|
36
24
|
def auto_generate_id
|
37
25
|
true
|
38
26
|
end
|
@@ -68,8 +56,10 @@ module Volt
|
|
68
56
|
|
69
57
|
path_size = path.size
|
70
58
|
if save_changes? && path_size > 0 && !@model.nil?
|
71
|
-
if path_size > 3 && (parent = @model.parent)
|
72
|
-
|
59
|
+
if path_size > 3 && (parent = @model.parent)
|
60
|
+
# If we have a collection, go up one more.
|
61
|
+
parent = parent.parent unless parent.is_a?(Volt::Model)
|
62
|
+
@model.attributes[:"#{path[-4].singularize}_id"] = parent.id
|
73
63
|
end
|
74
64
|
|
75
65
|
if !collection
|
data/lib/volt/models/url.rb
CHANGED
@@ -31,7 +31,17 @@ module Volt
|
|
31
31
|
|
32
32
|
def initialize(volt_app, target, context, binding_name, event_name, call_proc)
|
33
33
|
super(volt_app, target, context, binding_name)
|
34
|
-
|
34
|
+
|
35
|
+
# Map blur/focus to focusout/focusin
|
36
|
+
@event_name = case event_name
|
37
|
+
when 'blur'
|
38
|
+
'focusout'
|
39
|
+
when 'focus'
|
40
|
+
'focusin'
|
41
|
+
else
|
42
|
+
event_name
|
43
|
+
end
|
44
|
+
|
35
45
|
|
36
46
|
handler = proc do |js_event|
|
37
47
|
event = JSEvent.new(js_event)
|
@@ -55,8 +65,7 @@ module Volt
|
|
55
65
|
# end
|
56
66
|
|
57
67
|
end
|
58
|
-
|
59
|
-
@listener = page.events.add(event_name, self, handler)
|
68
|
+
@listener = page.events.add(@event_name, self, handler)
|
60
69
|
end
|
61
70
|
|
62
71
|
# Remove the event binding
|
@@ -25,7 +25,7 @@ module Volt
|
|
25
25
|
# If no stage, then we are calling the main action method,
|
26
26
|
# so we should call the before/after actions
|
27
27
|
unless has_stage
|
28
|
-
if @controller.
|
28
|
+
if @controller.run_callbacks(:before_action, @action)
|
29
29
|
# stop_chain was called
|
30
30
|
return true
|
31
31
|
end
|
@@ -33,7 +33,7 @@ module Volt
|
|
33
33
|
|
34
34
|
@controller.send(method_name) if @controller.respond_to?(method_name)
|
35
35
|
|
36
|
-
@controller.
|
36
|
+
@controller.run_callbacks(:after_action, @action) unless has_stage
|
37
37
|
|
38
38
|
# before_action chain was not stopped
|
39
39
|
false
|
@@ -200,11 +200,16 @@ module Volt
|
|
200
200
|
end
|
201
201
|
|
202
202
|
def generate_initializers_code
|
203
|
-
|
204
|
-
|
203
|
+
paths = Dir["#{@component_path}/config/initializers/*.rb"]
|
204
|
+
paths += Dir["#{@component_path}/config/initializers/client/*.rb"]
|
205
|
+
|
206
|
+
cpath_size = @component_path.size
|
207
|
+
paths.map! {|path| @component_name + path[cpath_size..-1]}
|
208
|
+
|
209
|
+
code = "\n" + paths.map { |path| "require '#{path}'" }.join("\n")
|
205
210
|
|
206
211
|
code
|
207
212
|
end
|
208
213
|
|
209
214
|
end
|
210
|
-
end
|
215
|
+
end
|
@@ -9,23 +9,24 @@
|
|
9
9
|
#
|
10
10
|
# before_action :require_login
|
11
11
|
module Volt
|
12
|
-
module
|
12
|
+
module LifecycleCallbacks
|
13
13
|
# StopChainException inherits from Exception directly so it will not be handled by a
|
14
14
|
# default rescue.
|
15
15
|
class StopChainException < Exception; end
|
16
16
|
|
17
17
|
module ClassMethods
|
18
|
-
# Takes a list of
|
19
|
-
# can be used anytime you have
|
20
|
-
#
|
21
|
-
|
22
|
-
|
18
|
+
# Takes a list of callbacks (as symbols). A callback is typically used
|
19
|
+
# for before/after actions, but can be used anytime you have callbacks
|
20
|
+
# that may be filtered by action. The method will create an callback
|
21
|
+
# method for each callback name passed in.
|
22
|
+
def setup_action_helpers_in_class(*callback_names)
|
23
|
+
callback_names.each do |callback_name|
|
23
24
|
# Setup a class attribute to track the
|
24
|
-
callbacks_var_name = :"#{
|
25
|
+
callbacks_var_name = :"#{callback_name}_callbacks"
|
25
26
|
class_attribute(callbacks_var_name)
|
26
27
|
|
27
28
|
# Create the method on the class
|
28
|
-
define_singleton_method(
|
29
|
+
define_singleton_method(callback_name) do |*args, &block|
|
29
30
|
# Add the block in place of the symbol
|
30
31
|
args.unshift(block) if block
|
31
32
|
|
@@ -52,16 +53,19 @@ module Volt
|
|
52
53
|
end
|
53
54
|
end
|
54
55
|
|
55
|
-
# To run the
|
56
|
-
# and the action
|
57
|
-
# #stop_chain, it will return true, otherwise false.
|
58
|
-
def
|
59
|
-
callbacks = self.class.send(:"#{
|
56
|
+
# To run the callbacks on a class, call #run_callbacks passing in the
|
57
|
+
# callback_name and the action it runs with. If the callback chain was
|
58
|
+
# stopped with #stop_chain, it will return true, otherwise false.
|
59
|
+
def run_callbacks(callback_name, action=nil)
|
60
|
+
callbacks = self.class.send(:"#{callback_name}_callbacks")
|
60
61
|
|
61
|
-
|
62
|
+
callbacks ||= []
|
63
|
+
if action
|
64
|
+
callbacks = filter_actions_by_only_exclude(callbacks || [], action)
|
65
|
+
end
|
62
66
|
|
63
67
|
begin
|
64
|
-
|
68
|
+
callbacks.map { |v| v[0] }.each do |callback|
|
65
69
|
case callback
|
66
70
|
when Symbol
|
67
71
|
send(callback)
|
@@ -100,7 +104,7 @@ module Volt
|
|
100
104
|
# If no only, include it
|
101
105
|
true
|
102
106
|
end
|
103
|
-
end
|
107
|
+
end
|
104
108
|
end
|
105
109
|
end
|
106
110
|
end
|
data/lib/volt/version.rb
CHANGED
data/lib/volt/volt/users.rb
CHANGED
@@ -39,8 +39,11 @@ module Volt
|
|
39
39
|
|
40
40
|
# as_user lets you run a block as another user
|
41
41
|
#
|
42
|
-
# @param
|
43
|
-
def as_user(
|
42
|
+
# @param user_or_user_id [Integer|Volt::Model]
|
43
|
+
def as_user(user_or_id)
|
44
|
+
# if we have a user, get the id
|
45
|
+
user_id = user_or_id.is_a?(Volt::Model) ? user_or_id.id : user_or_id
|
46
|
+
|
44
47
|
previous_id = Thread.current['with_user_id']
|
45
48
|
Thread.current['with_user_id'] = user_id
|
46
49
|
|
@@ -49,6 +52,22 @@ module Volt
|
|
49
52
|
Thread.current['with_user_id'] = previous_id
|
50
53
|
end
|
51
54
|
|
55
|
+
unless RUBY_PLATFORM == 'opal'
|
56
|
+
# Takes a user and returns a signed string that can be used for the
|
57
|
+
# user_id cookie to login a user.
|
58
|
+
def user_login_signature(user)
|
59
|
+
fail 'app_secret is not configured' unless Volt.config.app_secret
|
60
|
+
|
61
|
+
# TODO: returning here should be possible, but causes some issues
|
62
|
+
# Salt the user id with the app_secret so the end user can't
|
63
|
+
# tamper with the cookie
|
64
|
+
signature = Digest::SHA256.hexdigest(salty_user_id(user.id))
|
65
|
+
|
66
|
+
# Return user_id:hash on user id
|
67
|
+
"#{user.id}:#{signature}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
52
71
|
def skip_permissions
|
53
72
|
Volt.run_in_mode(:skip_permissions) do
|
54
73
|
yield
|
@@ -115,5 +134,13 @@ module Volt
|
|
115
134
|
|
116
135
|
user_id_signature
|
117
136
|
end
|
137
|
+
|
138
|
+
|
139
|
+
private
|
140
|
+
unless RUBY_PLATFORM == 'opal'
|
141
|
+
def salty_user_id(user_id)
|
142
|
+
"#{Volt.config.app_secret}::#{user_id}"
|
143
|
+
end
|
144
|
+
end
|
118
145
|
end
|
119
146
|
end
|
@@ -5,6 +5,8 @@ module Main
|
|
5
5
|
class MainController < Volt::ModelController
|
6
6
|
model :page
|
7
7
|
|
8
|
+
reactive_accessor :blur_count, :focus_count
|
9
|
+
|
8
10
|
def index
|
9
11
|
a = {}
|
10
12
|
a[{}] = 5
|
@@ -76,6 +78,16 @@ module Main
|
|
76
78
|
page._items = changes
|
77
79
|
end
|
78
80
|
|
81
|
+
def blur
|
82
|
+
self.blur_count ||= 0
|
83
|
+
self.blur_count += 1
|
84
|
+
end
|
85
|
+
|
86
|
+
def focus
|
87
|
+
self.focus_count ||= 0
|
88
|
+
self.focus_count += 1
|
89
|
+
end
|
90
|
+
|
79
91
|
private
|
80
92
|
|
81
93
|
# the main template contains a #template binding that shows another
|
@@ -148,4 +148,10 @@
|
|
148
148
|
|
149
149
|
<p id="escapeContent">{{{this is {{escaped}}}}}</p>
|
150
150
|
|
151
|
+
<h2>Event</h2>
|
152
|
+
|
153
|
+
<input e-blur="blur" e-focus="focus" id="blurFocusField" />
|
154
|
+
<div id="blurCount">{{ blur_count || 0 }}</div>
|
155
|
+
<div id="focusCount">{{ focus_count || 0 }}</div>
|
156
|
+
|
151
157
|
|
@@ -243,6 +243,25 @@ describe 'bindings test', type: :feature, sauce: true do
|
|
243
243
|
end
|
244
244
|
end
|
245
245
|
|
246
|
+
# NOTE: For some reason this spec fails randomly (capybara issue I think)
|
247
|
+
# describe "events" do
|
248
|
+
# it 'should handle focus and blur' do
|
249
|
+
# visit '/'
|
250
|
+
# click_link 'Bindings'
|
251
|
+
|
252
|
+
# expect(find('#focusCount')).to have_content('0')
|
253
|
+
# expect(find('#blurCount')).to have_content('0')
|
254
|
+
|
255
|
+
# page.execute_script("$('#blurFocusField').focus()")
|
256
|
+
# sleep 0.1
|
257
|
+
# expect(find('#focusCount')).to have_content('1')
|
258
|
+
|
259
|
+
# page.execute_script("$('#blurFocusField').blur()")
|
260
|
+
# expect(find('#blurCount')).to have_content('1')
|
261
|
+
|
262
|
+
# end
|
263
|
+
# end
|
264
|
+
|
246
265
|
if ENV['BROWSER'] != 'phantom'
|
247
266
|
describe 'input hidden and select' do
|
248
267
|
it 'should display binding value' do
|
@@ -17,14 +17,14 @@ describe Volt::Associations do
|
|
17
17
|
if RUBY_PLATFORM != 'opal'
|
18
18
|
describe "with samples" do
|
19
19
|
before do
|
20
|
-
|
21
|
-
@person
|
22
|
-
@person.
|
23
|
-
@person.
|
20
|
+
@person = Person.new(name: 'Jimmy')
|
21
|
+
store.people << @person
|
22
|
+
@person.addresses << Address.new(city: 'Bozeman')
|
23
|
+
@person.addresses << Address.new(city: 'Portland')
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'should associate via belongs_to' do
|
27
|
-
address = store.
|
27
|
+
address = store.addresses.first.sync
|
28
28
|
|
29
29
|
expect(address.person.sync.id).to eq(@person.id)
|
30
30
|
end
|
@@ -64,7 +64,7 @@ describe Volt::Associations do
|
|
64
64
|
|
65
65
|
it 'should assign the reference_id for has_many' do
|
66
66
|
bob = store.people.create.sync
|
67
|
-
bob.addresses.create({:street => '1234 awesome street'})
|
67
|
+
address = bob.addresses.create({:street => '1234 awesome street'})
|
68
68
|
expect(bob.addresses[0].sync.person_id).to eq(bob.id)
|
69
69
|
expect(bob.id).to_not eq(nil)
|
70
70
|
end
|
data/spec/models/buffer_spec.rb
CHANGED
@@ -4,9 +4,18 @@ class ::TestSaveFailure < Volt::Model
|
|
4
4
|
validate :name, length: 5
|
5
5
|
end
|
6
6
|
|
7
|
+
class ::TestChangedAttribute < Volt::Model
|
8
|
+
before_save :change_attributes
|
9
|
+
|
10
|
+
def change_attributes
|
11
|
+
set('one', 1)
|
12
|
+
set('two', 2)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
7
16
|
describe Volt::Buffer do
|
8
17
|
it 'should let you pass a block that evaluates to the then of the promise' do
|
9
|
-
buffer = the_page._items
|
18
|
+
buffer = the_page._items.buffer
|
10
19
|
|
11
20
|
count = 0
|
12
21
|
result = buffer.save! do
|
@@ -18,6 +27,15 @@ describe Volt::Buffer do
|
|
18
27
|
end
|
19
28
|
|
20
29
|
if RUBY_PLATFORM != 'opal'
|
30
|
+
it 'should copy attributes back from the save_to model incase it changes them during save' do
|
31
|
+
buffer = the_page._test_changed_attributes.buffer
|
32
|
+
|
33
|
+
buffer.save!.sync
|
34
|
+
expect(buffer.save_to.attributes.without(:id)).to eq({one: 1, two: 2})
|
35
|
+
expect(buffer.attributes.without(:id)).to eq({one: 1, two: 2})
|
36
|
+
expect(buffer.id).to eq(buffer.save_to.id)
|
37
|
+
end
|
38
|
+
|
21
39
|
it 'should reject a failed save! with the errors object' do
|
22
40
|
buffer = the_page._test_save_failures.buffer
|
23
41
|
|
data/spec/models/url_spec.rb
CHANGED
@@ -63,4 +63,20 @@ describe Volt::URL do
|
|
63
63
|
expect(subject.url_for params).to eq uri
|
64
64
|
end
|
65
65
|
end
|
66
|
+
|
67
|
+
describe '#url_with' do
|
68
|
+
let(:uri) { 'http://voltframework.com:8888/path/1?query=val&page=1#fragment' }
|
69
|
+
let(:fake_router) do
|
70
|
+
router = Volt::Routes.new
|
71
|
+
|
72
|
+
router.define do
|
73
|
+
client '/path/{{ id }}', view: 'blog/show'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'regenerates the URL and merges the given params' do
|
78
|
+
params = { page: 1 }
|
79
|
+
expect(subject.url_with params).to eq uri
|
80
|
+
end
|
81
|
+
end
|
66
82
|
end
|
data/spec/models/user_spec.rb
CHANGED
@@ -37,9 +37,7 @@ describe Volt::User do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
describe '#password=' do
|
40
|
-
|
41
|
-
|
42
|
-
subject { user.password = 'test' }
|
40
|
+
subject { Volt::User.new(password: 'test') }
|
43
41
|
|
44
42
|
if RUBY_PLATFORM != 'opal'
|
45
43
|
describe 'when it is a Volt server' do
|
@@ -49,34 +47,37 @@ describe Volt::User do
|
|
49
47
|
end
|
50
48
|
|
51
49
|
it 'encrypts password' do
|
52
|
-
subject
|
50
|
+
the_page._users << subject
|
53
51
|
|
54
52
|
expect(BCrypt::Password).to have_received :create
|
55
53
|
end
|
56
54
|
|
57
55
|
it 'sets _hashed_password to passed value' do
|
58
|
-
subject
|
56
|
+
the_page._users << subject
|
59
57
|
|
60
|
-
expect(
|
58
|
+
expect(subject.get('hashed_password')).to eq 'hashed-password'
|
61
59
|
end
|
62
60
|
end
|
63
61
|
|
64
62
|
it 'should allow updates without validating the password' do
|
65
63
|
bob = store._users.buffer(name: 'Bob', email: 'bob@bob.com', password: '39sdjkdf932jklsd')
|
66
|
-
bob.save
|
64
|
+
bob.save!.sync
|
67
65
|
|
68
|
-
|
66
|
+
Volt.as_user(bob) do
|
69
67
|
|
70
|
-
|
68
|
+
expect(bob.password).to eq(nil)
|
71
69
|
|
72
|
-
|
70
|
+
bob_buf = bob.buffer
|
73
71
|
|
74
|
-
|
75
|
-
|
76
|
-
saved =
|
77
|
-
|
72
|
+
bob_buf.name = 'Jimmy'
|
73
|
+
|
74
|
+
saved = false
|
75
|
+
bob_buf.save! do
|
76
|
+
saved = true
|
77
|
+
end
|
78
78
|
|
79
|
-
|
79
|
+
expect(saved).to eq(true)
|
80
|
+
end
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
@@ -87,12 +88,10 @@ describe Volt::User do
|
|
87
88
|
allow(Volt).to receive(:server?).and_return false
|
88
89
|
end
|
89
90
|
|
90
|
-
subject {
|
91
|
-
|
92
|
-
it 'sets _password to passed value' do
|
93
|
-
subject
|
91
|
+
subject { Volt::User.new(password: 'a valid test password') }
|
94
92
|
|
95
|
-
|
93
|
+
it 'sets password to passed value' do
|
94
|
+
expect(subject.password).to eq('a valid test password')
|
96
95
|
end
|
97
96
|
end
|
98
97
|
end
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
require 'volt/controllers/model_controller'
|
3
3
|
|
4
4
|
class BaseTestActions
|
5
|
-
include Volt::
|
5
|
+
include Volt::LifecycleCallbacks
|
6
6
|
|
7
7
|
setup_action_helpers_in_class(:before_action, :after_action)
|
8
8
|
end
|
@@ -70,14 +70,14 @@ class TestOnlyCallbacks < TestActionsSymbolsBase
|
|
70
70
|
before_action :run_one, :run_two, only: [:new]
|
71
71
|
end
|
72
72
|
|
73
|
-
describe Volt::
|
73
|
+
describe Volt::LifecycleCallbacks do
|
74
74
|
it 'should trigger before actions via blocks' do
|
75
75
|
test_class = TestActionsBlocks.new
|
76
76
|
|
77
77
|
expect(test_class.ran_before1).to eq(nil)
|
78
78
|
expect(test_class.ran_before2).to eq(nil)
|
79
79
|
|
80
|
-
test_class.
|
80
|
+
test_class.run_callbacks(:before_action, :index)
|
81
81
|
|
82
82
|
expect(test_class.ran_before1).to eq(true)
|
83
83
|
expect(test_class.ran_before2).to eq(true)
|
@@ -89,7 +89,7 @@ describe Volt::Actions do
|
|
89
89
|
expect(test_class.ran_one).to eq(nil)
|
90
90
|
expect(test_class.ran_two).to eq(nil)
|
91
91
|
|
92
|
-
test_class.
|
92
|
+
test_class.run_callbacks(:before_action, :index)
|
93
93
|
|
94
94
|
expect(test_class.ran_one).to eq(true)
|
95
95
|
expect(test_class.ran_two).to eq(true)
|
@@ -107,17 +107,17 @@ describe Volt::Actions do
|
|
107
107
|
expect(test_class.ran_one).to eq(nil)
|
108
108
|
expect(test_class.ran_two).to eq(nil)
|
109
109
|
|
110
|
-
result = test_class.
|
110
|
+
result = test_class.run_callbacks(:before_action, :index)
|
111
111
|
expect(result).to eq(false)
|
112
112
|
|
113
113
|
expect(test_class.ran_one).to eq(true)
|
114
114
|
expect(test_class.ran_two).to eq(true)
|
115
115
|
end
|
116
116
|
|
117
|
-
it 'should stop the chain when #stop_chain is called and return false from #
|
117
|
+
it 'should stop the chain when #stop_chain is called and return false from #run_callbacks' do
|
118
118
|
test_class = TestStopCallbacks.new
|
119
119
|
|
120
|
-
result = test_class.
|
120
|
+
result = test_class.run_callbacks(:before_action, :index)
|
121
121
|
expect(result).to eq(true)
|
122
122
|
|
123
123
|
expect(test_class.ran_one).to eq(true)
|
@@ -129,18 +129,18 @@ describe Volt::Actions do
|
|
129
129
|
it 'should call without any callbacks' do
|
130
130
|
test_class = TestNoCallbacks.new
|
131
131
|
|
132
|
-
result = test_class.
|
132
|
+
result = test_class.run_callbacks(:before_action, :index)
|
133
133
|
expect(result).to eq(false)
|
134
134
|
end
|
135
135
|
|
136
136
|
it 'should follow only limitations' do
|
137
137
|
test_only = TestOnlyCallbacks.new
|
138
138
|
|
139
|
-
test_only.
|
139
|
+
test_only.run_callbacks(:before_action, :index)
|
140
140
|
expect(test_only.ran_one).to eq(nil)
|
141
141
|
expect(test_only.ran_two).to eq(nil)
|
142
142
|
|
143
|
-
test_only.
|
143
|
+
test_only.run_callbacks(:before_action, :new)
|
144
144
|
expect(test_only.ran_one).to eq(true)
|
145
145
|
expect(test_only.ran_two).to eq(true)
|
146
146
|
end
|
@@ -1,4 +1,12 @@
|
|
1
1
|
# By default Volt generates this User model which inherits from Volt::User,
|
2
2
|
# you can rename this if you want.
|
3
3
|
class User < Volt::User
|
4
|
+
# login_field is set to :email by default and can be changed to :username
|
5
|
+
# in config/app.rb
|
6
|
+
field login_field
|
7
|
+
field :name
|
8
|
+
|
9
|
+
validate login_field, unique: true, length: 8
|
10
|
+
validate :email, email: true
|
11
|
+
|
4
12
|
end
|
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.4.
|
4
|
+
version: 0.9.4.pre2
|
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-06-
|
11
|
+
date: 2015-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -409,7 +409,6 @@ files:
|
|
409
409
|
- lib/volt/cli/new_gem.rb
|
410
410
|
- lib/volt/cli/runner.rb
|
411
411
|
- lib/volt/config.rb
|
412
|
-
- lib/volt/controllers/actions.rb
|
413
412
|
- lib/volt/controllers/collection_helpers.rb
|
414
413
|
- lib/volt/controllers/http_controller.rb
|
415
414
|
- lib/volt/controllers/model_controller.rb
|
@@ -576,6 +575,7 @@ files:
|
|
576
575
|
- lib/volt/utils/event_counter.rb
|
577
576
|
- lib/volt/utils/generic_counting_pool.rb
|
578
577
|
- lib/volt/utils/generic_pool.rb
|
578
|
+
- lib/volt/utils/lifecycle_callbacks.rb
|
579
579
|
- lib/volt/utils/local_storage.rb
|
580
580
|
- lib/volt/utils/logging/task_argument_filterer.rb
|
581
581
|
- lib/volt/utils/logging/task_logger.rb
|
@@ -631,7 +631,6 @@ files:
|
|
631
631
|
- spec/apps/kitchen_sink/config.ru
|
632
632
|
- spec/apps/kitchen_sink/config/app.rb
|
633
633
|
- spec/apps/kitchen_sink/config/base/index.html
|
634
|
-
- spec/controllers/actions_spec.rb
|
635
634
|
- spec/controllers/http_controller_spec.rb
|
636
635
|
- spec/controllers/model_controller_spec.rb
|
637
636
|
- spec/controllers/reactive_accessors_spec.rb
|
@@ -664,6 +663,7 @@ files:
|
|
664
663
|
- spec/models/buffer_spec.rb
|
665
664
|
- spec/models/dirty_spec.rb
|
666
665
|
- spec/models/field_helpers_spec.rb
|
666
|
+
- spec/models/model_helpers/model_helpers_spec.rb
|
667
667
|
- spec/models/model_spec.rb
|
668
668
|
- spec/models/model_state_spec.rb
|
669
669
|
- spec/models/permissions_spec.rb
|
@@ -726,6 +726,7 @@ files:
|
|
726
726
|
- spec/utils/ejson_spec.rb
|
727
727
|
- spec/utils/generic_counting_pool_spec.rb
|
728
728
|
- spec/utils/generic_pool_spec.rb
|
729
|
+
- spec/utils/lifecycle_callbacks_spec.rb
|
729
730
|
- spec/utils/parsing_spec.rb
|
730
731
|
- spec/utils/promise_extensions_spec.rb
|
731
732
|
- spec/utils/task_argument_filtererer_spec.rb
|
@@ -877,7 +878,6 @@ test_files:
|
|
877
878
|
- spec/apps/kitchen_sink/config.ru
|
878
879
|
- spec/apps/kitchen_sink/config/app.rb
|
879
880
|
- spec/apps/kitchen_sink/config/base/index.html
|
880
|
-
- spec/controllers/actions_spec.rb
|
881
881
|
- spec/controllers/http_controller_spec.rb
|
882
882
|
- spec/controllers/model_controller_spec.rb
|
883
883
|
- spec/controllers/reactive_accessors_spec.rb
|
@@ -910,6 +910,7 @@ test_files:
|
|
910
910
|
- spec/models/buffer_spec.rb
|
911
911
|
- spec/models/dirty_spec.rb
|
912
912
|
- spec/models/field_helpers_spec.rb
|
913
|
+
- spec/models/model_helpers/model_helpers_spec.rb
|
913
914
|
- spec/models/model_spec.rb
|
914
915
|
- spec/models/model_state_spec.rb
|
915
916
|
- spec/models/permissions_spec.rb
|
@@ -972,6 +973,7 @@ test_files:
|
|
972
973
|
- spec/utils/ejson_spec.rb
|
973
974
|
- spec/utils/generic_counting_pool_spec.rb
|
974
975
|
- spec/utils/generic_pool_spec.rb
|
976
|
+
- spec/utils/lifecycle_callbacks_spec.rb
|
975
977
|
- spec/utils/parsing_spec.rb
|
976
978
|
- spec/utils/promise_extensions_spec.rb
|
977
979
|
- spec/utils/task_argument_filtererer_spec.rb
|