volt 0.9.3 → 0.9.4.pre1
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 +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +12 -0
- data/docs/UPGRADE_GUIDE.md +13 -1
- data/lib/volt/cli.rb +10 -0
- data/lib/volt/config.rb +5 -1
- data/lib/volt/controllers/actions.rb +4 -4
- data/lib/volt/controllers/http_controller.rb +3 -3
- data/lib/volt/controllers/model_controller.rb +1 -1
- data/lib/volt/models/field_helpers.rb +19 -1
- data/lib/volt/models/model.rb +1 -1
- data/lib/volt/models/root_models/root_models.rb +5 -0
- data/lib/volt/models/root_models/store_root.rb +0 -2
- data/lib/volt/models/validations/validations.rb +1 -0
- data/lib/volt/models/validators/type_validator.rb +23 -0
- data/lib/volt/page/bindings/view_binding/controller_handler.rb +2 -2
- data/lib/volt/reactive/reactive_hash.rb +4 -0
- data/lib/volt/server/message_bus/peer_to_peer/peer_connection.rb +3 -3
- data/lib/volt/server/middleware/middleware_stack.rb +9 -12
- data/lib/volt/server/websocket/websocket_handler.rb +9 -1
- data/lib/volt/version.rb +1 -1
- data/lib/volt/volt/users.rb +4 -0
- data/spec/controllers/actions_spec.rb +8 -8
- data/spec/models/field_helpers_spec.rb +17 -1
- data/spec/models/validators/type_validator_spec.rb +46 -0
- data/spec/reactive/reactive_hash_spec.rb +5 -0
- data/templates/project/Gemfile.tt +2 -2
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 390291d6628b74ad144ac393109c5beab7ed1184
|
4
|
+
data.tar.gz: c4cf1d8701aeddbcda38c2e87f03db1b3a4c9db9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d31cb4efd187cb590793c53fb23bae2a9a3f53d4ab86090b22c4c611a97bdfb06444b43c630c19ecb266cd59e41a0e8655542de52f5377ea7b981412b914235a
|
7
|
+
data.tar.gz: 8b5eca835a00949d4107b6257e8d18ffd34cf41514e94087e0a3e6aa2a0c04533861b318d2fed09ce7b20b2fe7930a8d5037bc59ad5da124c9ed16a6a885a02c
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.9.4.pre1
|
4
|
+
### Added
|
5
|
+
|
6
|
+
### Changed
|
7
|
+
- fixed bug with ReactiveHash#to_json
|
8
|
+
- fixed bug with field Numeric coersion
|
9
|
+
|
3
10
|
## 0.9.3
|
11
|
+
[0.9.3 Update Blog Post](http://blog.voltframework.com/post/121128931859/0-9-3-stuff-you-asked-for)
|
12
|
+
[Upgrade Guide](https://github.com/voltrb/volt/blob/master/docs/UPGRADE_GUIDE.md)
|
4
13
|
|
5
14
|
### Added
|
6
15
|
- Added validations block for conditional validation runs
|
data/README.md
CHANGED
@@ -33,6 +33,18 @@ Read the [full docs on Volt here](http://voltframework.com/docs)
|
|
33
33
|
|
34
34
|
There is also a [work in progress tutorial](https://github.com/rhgraysonii/volt_tutorial) by @rhgraysonii
|
35
35
|
|
36
|
+
# More Videos
|
37
|
+
|
38
|
+
Rick Carlino has been putting together some great volt tutorial videos also.
|
39
|
+
|
40
|
+
- [Volt Tasks](http://datamelon.io/blog/2015/creating-volt-task-objects.html)
|
41
|
+
- [Build a Realtime Chat App with Volt](http://datamelon.io/blog/2015/building-a-chat-app-in-volt.html)
|
42
|
+
- [Understanding Volt Views](http://datamelon.io/blog/2015/understanding-views-in-volt-with-a-card-game.html)
|
43
|
+
|
44
|
+
# Getting Help
|
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 need to discuss, drop into our [gitter room](gitter.im/voltrb/volt).
|
47
|
+
|
36
48
|
# Contributing
|
37
49
|
|
38
50
|
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.
|
data/docs/UPGRADE_GUIDE.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# 0.9.2 to 0.9.3
|
2
2
|
|
3
|
+
Upgrading from 0.9.2 should be fairly simple, just implement the following:
|
4
|
+
|
5
|
+
## Gemfile
|
6
|
+
|
3
7
|
Add the following to your gemfile:
|
4
8
|
|
5
9
|
```ruby
|
@@ -13,4 +17,12 @@ gem 'csso-rails', '~> 0.3.4', require: false
|
|
13
17
|
gem 'uglifier', '>= 2.4.0', require: false
|
14
18
|
|
15
19
|
gem 'volt-mongo'
|
16
|
-
```
|
20
|
+
```
|
21
|
+
|
22
|
+
## Store Promises
|
23
|
+
|
24
|
+
The api for accessing the store collection has changed, to better understand the changes, watch [this explainer video](https://www.youtube.com/watch?v=1RX9i8ivtWI).
|
25
|
+
|
26
|
+
## id vs _id
|
27
|
+
|
28
|
+
Everywhere you were using ```_id```, you should now just use ```id```. Volt's mongo adaptor will map ```id``` to ```_id``` when saving or querying. This change will make moving between databases easier.
|
data/lib/volt/cli.rb
CHANGED
@@ -36,6 +36,16 @@ module Volt
|
|
36
36
|
method_option :bind, type: :string, aliases: '-b', banner: 'the ip the server should bind to'
|
37
37
|
|
38
38
|
def server
|
39
|
+
if ENV['PROFILE_BOOT']
|
40
|
+
begin
|
41
|
+
require 'ruby-prof'
|
42
|
+
|
43
|
+
RubyProf.start
|
44
|
+
rescue LoadError => e
|
45
|
+
puts "To run volt in a profile mode, you must add ruby-prof gem to the app's Gemfile"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
39
49
|
require 'fileutils'
|
40
50
|
require 'volt/server'
|
41
51
|
|
data/lib/volt/config.rb
CHANGED
@@ -48,7 +48,7 @@ else
|
|
48
48
|
class << self
|
49
49
|
def defaults
|
50
50
|
app_name = File.basename(Dir.pwd)
|
51
|
-
{
|
51
|
+
opts = {
|
52
52
|
app_name: app_name,
|
53
53
|
db_name: (ENV['DB_NAME'] || (app_name + '_' + Volt.env.to_s)).gsub('.', '_'),
|
54
54
|
db_host: ENV['DB_HOST'] || 'localhost',
|
@@ -66,6 +66,10 @@ else
|
|
66
66
|
max_worker_threads: 10,
|
67
67
|
worker_timeout: 60
|
68
68
|
}
|
69
|
+
|
70
|
+
opts[:db_uri] = ENV['DB_URI'] if ENV['DB_URI']
|
71
|
+
|
72
|
+
opts
|
69
73
|
end
|
70
74
|
|
71
75
|
# Resets the configuration to the default (empty hash)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# The Actions module adds helpers for setting up and using
|
2
2
|
# actions on a class. You can setup helpers for an action with
|
3
3
|
#
|
4
|
-
# setup_action_helpers_in_class(:
|
4
|
+
# setup_action_helpers_in_class(:before_action, :after_action)
|
5
5
|
#
|
6
6
|
# The above will setup before_action and after_action methods on
|
7
7
|
# the class. Typically setup_action_helpers_in_class will be run
|
@@ -21,11 +21,11 @@ module Volt
|
|
21
21
|
def setup_action_helpers_in_class(*groups)
|
22
22
|
groups.each do |group|
|
23
23
|
# Setup a class attribute to track the
|
24
|
-
callbacks_var_name = :"#{group}
|
24
|
+
callbacks_var_name = :"#{group}_callbacks"
|
25
25
|
class_attribute(callbacks_var_name)
|
26
26
|
|
27
27
|
# Create the method on the class
|
28
|
-
define_singleton_method(
|
28
|
+
define_singleton_method(group) do |*args, &block|
|
29
29
|
# Add the block in place of the symbol
|
30
30
|
args.unshift(block) if block
|
31
31
|
|
@@ -56,7 +56,7 @@ module Volt
|
|
56
56
|
# and the action being called on. If the callback chain was stopped with
|
57
57
|
# #stop_chain, it will return true, otherwise false.
|
58
58
|
def run_actions(group, action)
|
59
|
-
callbacks = self.class.send(:"#{group}
|
59
|
+
callbacks = self.class.send(:"#{group}_callbacks")
|
60
60
|
|
61
61
|
filtered_callbacks = filter_actions_by_only_exclude(callbacks || [], action)
|
62
62
|
|
@@ -11,7 +11,7 @@ module Volt
|
|
11
11
|
attr_accessor :params
|
12
12
|
|
13
13
|
# Setup before_action and after_action
|
14
|
-
setup_action_helpers_in_class(:
|
14
|
+
setup_action_helpers_in_class(:before_action, :after_action)
|
15
15
|
|
16
16
|
# Initialzed with the params parsed from the route and the HttpRequest
|
17
17
|
def initialize(volt_app, params, request)
|
@@ -23,9 +23,9 @@ module Volt
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def perform(action='index')
|
26
|
-
filtered = run_actions(:
|
26
|
+
filtered = run_actions(:before_action, action)
|
27
27
|
send(action.to_sym) unless filtered
|
28
|
-
run_actions(:
|
28
|
+
run_actions(:after_action, action) unless filtered
|
29
29
|
respond
|
30
30
|
end
|
31
31
|
|
@@ -23,7 +23,7 @@ module Volt
|
|
23
23
|
attr_accessor :section
|
24
24
|
|
25
25
|
# Setup before_action and after_action
|
26
|
-
setup_action_helpers_in_class(:
|
26
|
+
setup_action_helpers_in_class(:before_action, :after_action)
|
27
27
|
|
28
28
|
# Container returns the node that is parent to all nodes in the section.
|
29
29
|
def container
|
@@ -10,6 +10,11 @@ module FieldHelpers
|
|
10
10
|
fail FieldHelpers::InvalidFieldClass, 'valid field types is currently limited to String or Numeric'
|
11
11
|
end
|
12
12
|
|
13
|
+
if klass
|
14
|
+
# Add type validation
|
15
|
+
validate name, type: klass
|
16
|
+
end
|
17
|
+
|
13
18
|
define_method(name) do
|
14
19
|
get(name)
|
15
20
|
end
|
@@ -21,7 +26,20 @@ module FieldHelpers
|
|
21
26
|
if klass == String
|
22
27
|
val = val.to_s
|
23
28
|
elsif klass == Numeric
|
24
|
-
|
29
|
+
begin
|
30
|
+
orig = val
|
31
|
+
unless val.is_a?(Numeric)
|
32
|
+
val = Float(val)
|
33
|
+
end
|
34
|
+
|
35
|
+
if RUBY_PLATFORM == 'opal'
|
36
|
+
# Opal has a bug in 0.7.2 that gives us back NaN without an
|
37
|
+
# error sometimes.
|
38
|
+
val = orig if val.nan?
|
39
|
+
end
|
40
|
+
rescue TypeError, ArgumentError => e
|
41
|
+
# ignore, unmatched types will be caught below.
|
42
|
+
end
|
25
43
|
end
|
26
44
|
end
|
27
45
|
|
data/lib/volt/models/model.rb
CHANGED
@@ -19,7 +19,12 @@ end
|
|
19
19
|
|
20
20
|
module Volt
|
21
21
|
class RootModels
|
22
|
+
class_attribute :model_classes
|
23
|
+
self.model_classes = []
|
24
|
+
|
22
25
|
def self.add_model_class(klass)
|
26
|
+
self.model_classes << klass
|
27
|
+
|
23
28
|
method_name = klass.to_s.underscore.pluralize
|
24
29
|
|
25
30
|
# Create a getter for each model class off of root.
|
@@ -20,7 +20,6 @@ module Volt
|
|
20
20
|
|
21
21
|
def get(attr_name, expand = false)
|
22
22
|
res = if attr_name.singular? && attr_name.to_sym != :id
|
23
|
-
puts "GET: #{attr_name}"
|
24
23
|
model_for_root.get(attr_name, expand)
|
25
24
|
else
|
26
25
|
super
|
@@ -32,7 +31,6 @@ module Volt
|
|
32
31
|
|
33
32
|
def set(attr_name, value, &block)
|
34
33
|
if attr_name.singular? && attr_name.to_sym != :id
|
35
|
-
puts "SET ATTR NAME: #{attr_name.inspect}: #{value.inspect}"
|
36
34
|
Volt::Computation.run_without_tracking do
|
37
35
|
model_for_root.then do |model|
|
38
36
|
model.set(attr_name, value, &block)
|
@@ -6,6 +6,7 @@ require 'volt/models/validators/numericality_validator'
|
|
6
6
|
require 'volt/models/validators/phone_number_validator'
|
7
7
|
require 'volt/models/validators/presence_validator'
|
8
8
|
require 'volt/models/validators/unique_validator'
|
9
|
+
require 'volt/models/validators/type_validator'
|
9
10
|
|
10
11
|
module Volt
|
11
12
|
# Include in any class to get validation logic
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Enforces a type on a field. Typically setup from ```field :name, Type```
|
2
|
+
module Volt
|
3
|
+
class TypeValidator
|
4
|
+
def self.validate(model, field_name, args)
|
5
|
+
errors = {}
|
6
|
+
value = model.get(field_name)
|
7
|
+
|
8
|
+
type_restriction = args.is_a?(Hash) ? args[:type] : args
|
9
|
+
|
10
|
+
unless value.is_a?(type_restriction)
|
11
|
+
if args.is_a?(Hash) && args[:message]
|
12
|
+
message = args[:message]
|
13
|
+
else
|
14
|
+
message = "must be of type #{type_restriction.to_s}"
|
15
|
+
end
|
16
|
+
|
17
|
+
errors[field_name] = [message]
|
18
|
+
end
|
19
|
+
|
20
|
+
errors
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -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.run_actions(:
|
28
|
+
if @controller.run_actions(: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.run_actions(:
|
36
|
+
@controller.run_actions(:after_action, @action) unless has_stage
|
37
37
|
|
38
38
|
# before_action chain was not stopped
|
39
39
|
false
|
@@ -91,7 +91,7 @@ module Volt
|
|
91
91
|
begin
|
92
92
|
@message_encoder.send_message(@socket, message)
|
93
93
|
# 'Error: closed stream' comes in sometimes
|
94
|
-
rescue Errno::ECONNREFUSED, Errno::EPIPE, IOError => e # was also rescuing Error
|
94
|
+
rescue Errno::ECONNREFUSED, Errno::ENETUNREACH, Errno::EPIPE, IOError => e # was also rescuing Error
|
95
95
|
if reconnect!
|
96
96
|
retry
|
97
97
|
else
|
@@ -113,7 +113,7 @@ module Volt
|
|
113
113
|
end
|
114
114
|
|
115
115
|
# Got nil from socket
|
116
|
-
rescue Errno::ECONNRESET, Errno::EPIPE, IOError => e
|
116
|
+
rescue Errno::ECONNRESET, Errno::ENETUNREACH, Errno::EPIPE, IOError => e
|
117
117
|
# handle below
|
118
118
|
end
|
119
119
|
|
@@ -138,7 +138,7 @@ module Volt
|
|
138
138
|
begin
|
139
139
|
socket = SocketWithTimeout.new(ip, port, CONNECT_TIMEOUT)
|
140
140
|
return PeerConnection.new(socket, ip, port, message_bus)
|
141
|
-
rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT => e
|
141
|
+
rescue Errno::ECONNREFUSED, Errno::ENETUNREACH, Errno::ETIMEDOUT => e
|
142
142
|
# Unable to connect, next
|
143
143
|
next
|
144
144
|
end
|
@@ -9,14 +9,8 @@ module Volt
|
|
9
9
|
def initialize
|
10
10
|
# Setup the next app
|
11
11
|
@middlewares = []
|
12
|
-
@maps = []
|
13
12
|
end
|
14
13
|
|
15
|
-
# Set the app that gets called after the middleware runs
|
16
|
-
# def set_app(app)
|
17
|
-
# @app = app
|
18
|
-
# end
|
19
|
-
|
20
14
|
def use(*args, &block)
|
21
15
|
@middlewares << [args, block]
|
22
16
|
|
@@ -25,7 +19,10 @@ module Volt
|
|
25
19
|
end
|
26
20
|
|
27
21
|
def map(path, &block)
|
28
|
-
@
|
22
|
+
@middlewares << [:map, path, block]
|
23
|
+
|
24
|
+
# invalidate builder
|
25
|
+
@builder = nil
|
29
26
|
end
|
30
27
|
|
31
28
|
def run(app)
|
@@ -36,12 +33,12 @@ module Volt
|
|
36
33
|
def build
|
37
34
|
@builder = Rack::Builder.new
|
38
35
|
|
39
|
-
@maps.each do |path, block|
|
40
|
-
@builder.map(path, &block)
|
41
|
-
end
|
42
|
-
|
43
36
|
@middlewares.each do |middleware|
|
44
|
-
|
37
|
+
if middleware[0] == :map
|
38
|
+
@builder.map(middleware[1], &middleware[2])
|
39
|
+
else
|
40
|
+
@builder.use(*middleware[0], &middleware[1])
|
41
|
+
end
|
45
42
|
end
|
46
43
|
|
47
44
|
@builder.run(@app)
|
@@ -1,6 +1,14 @@
|
|
1
1
|
require 'faye/websocket'
|
2
2
|
require 'volt/server/socket_connection_handler'
|
3
3
|
|
4
|
+
# Load websocket options once at boot
|
5
|
+
# The ENV['DYNO'] option lets it kick in automatically if we're on heroku.
|
6
|
+
WEBSOCKET_OPTIONS = if !ENV['NO_WEBSOCKET_PING'] &&
|
7
|
+
(ENV['WEBSOCKET_PING_TIME'] || ENV['DYNO'])
|
8
|
+
{ping: (ENV['WEBSOCKET_PING_TIME'] || 30).to_i}
|
9
|
+
else
|
10
|
+
{}
|
11
|
+
end
|
4
12
|
|
5
13
|
module Volt
|
6
14
|
class WebsocketHandler
|
@@ -10,7 +18,7 @@ module Volt
|
|
10
18
|
|
11
19
|
def call(env)
|
12
20
|
if Faye::WebSocket.websocket?(env)
|
13
|
-
ws = Faye::WebSocket.new(env)
|
21
|
+
ws = Faye::WebSocket.new(env, nil, WEBSOCKET_OPTIONS)
|
14
22
|
|
15
23
|
socket_connection_handler = SocketConnectionHandler.new(ws)
|
16
24
|
|
data/lib/volt/version.rb
CHANGED
data/lib/volt/volt/users.rb
CHANGED
@@ -4,7 +4,7 @@ require 'volt/controllers/model_controller'
|
|
4
4
|
class BaseTestActions
|
5
5
|
include Volt::Actions
|
6
6
|
|
7
|
-
setup_action_helpers_in_class(:
|
7
|
+
setup_action_helpers_in_class(:before_action, :after_action)
|
8
8
|
end
|
9
9
|
|
10
10
|
class TestActionsBlocks < BaseTestActions
|
@@ -77,7 +77,7 @@ describe Volt::Actions do
|
|
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.run_actions(:
|
80
|
+
test_class.run_actions(: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.run_actions(:
|
92
|
+
test_class.run_actions(: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,7 +107,7 @@ 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.run_actions(:
|
110
|
+
result = test_class.run_actions(:before_action, :index)
|
111
111
|
expect(result).to eq(false)
|
112
112
|
|
113
113
|
expect(test_class.ran_one).to eq(true)
|
@@ -117,7 +117,7 @@ describe Volt::Actions do
|
|
117
117
|
it 'should stop the chain when #stop_chain is called and return false from #run_actions' do
|
118
118
|
test_class = TestStopCallbacks.new
|
119
119
|
|
120
|
-
result = test_class.run_actions(:
|
120
|
+
result = test_class.run_actions(: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.run_actions(:
|
132
|
+
result = test_class.run_actions(: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.run_actions(:
|
139
|
+
test_only.run_actions(: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.run_actions(:
|
143
|
+
test_only.run_actions(: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
|
@@ -7,8 +7,8 @@ class ExampleModelWithField < Volt::Model
|
|
7
7
|
end
|
8
8
|
|
9
9
|
describe 'field helpers' do
|
10
|
+
let(:model) { ExampleModelWithField.new }
|
10
11
|
it 'should allow a user to setup a field that can be written to and read' do
|
11
|
-
model = ExampleModelWithField.new
|
12
12
|
|
13
13
|
expect(model.name).to eq(nil)
|
14
14
|
model.name = 'jimmy'
|
@@ -26,4 +26,20 @@ describe 'field helpers' do
|
|
26
26
|
ExampleModelWithField.field :awesome, Array
|
27
27
|
end.to raise_error(FieldHelpers::InvalidFieldClass)
|
28
28
|
end
|
29
|
+
|
30
|
+
it 'should convert numeric strings to Fixnum when Fixnum is specified as a type restriction' do
|
31
|
+
model.value = '22'
|
32
|
+
expect(model.value).to eq(22)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should not convert non-numeric strings (and have a validation error)' do
|
36
|
+
# use a buffer, so we can put the model into an invalid state
|
37
|
+
buf = model.buffer
|
38
|
+
buf.value = 'cats'
|
39
|
+
expect(buf.value).to eq('cats')
|
40
|
+
|
41
|
+
buf.validate!.fail do |error|
|
42
|
+
expect(error).to eq({})
|
43
|
+
end
|
44
|
+
end
|
29
45
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Volt::TypeValidator do
|
4
|
+
subject { Volt::TypeValidator.validate(*use_params) }
|
5
|
+
let(:use_params) { [model, field_name, options] }
|
6
|
+
|
7
|
+
let(:model) { Volt::Model.new count: count }
|
8
|
+
let(:field_name) { :count }
|
9
|
+
let(:name) { 'John Doe' }
|
10
|
+
|
11
|
+
describe '.validate' do
|
12
|
+
describe 'when options is a Numeric' do
|
13
|
+
let(:options) { Numeric }
|
14
|
+
|
15
|
+
describe 'when count is a Numeric' do
|
16
|
+
let(:count) { 5 }
|
17
|
+
it { expect(subject).to eq({}) }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'when count is a string' do
|
21
|
+
let(:count) { 'Cats' }
|
22
|
+
it do
|
23
|
+
expect(subject).to eq({count: ['must be of type Numeric']})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'when options is a Hash' do
|
29
|
+
let(:options) do
|
30
|
+
{ type: Numeric, message: 'must be a number' }
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'when count is a Numeric' do
|
34
|
+
let(:count) { 5 }
|
35
|
+
it { expect(subject).to eq({}) }
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'when count is a string' do
|
39
|
+
let(:count) { 'Cats' }
|
40
|
+
it do
|
41
|
+
expect(subject).to eq(count: ['must be a number'])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -42,11 +42,11 @@ group :test do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
# Server for MRI
|
45
|
-
platform :mri do
|
45
|
+
platform :mri, :mingw do
|
46
46
|
# The implementation of ReadWriteLock in Volt uses concurrent ruby and ext helps performance.
|
47
47
|
gem 'concurrent-ruby-ext', '~> 0.8.0'
|
48
48
|
|
49
|
-
# Thin is the default volt server,
|
49
|
+
# Thin is the default volt server, Puma is also supported
|
50
50
|
gem 'thin', '~> 1.6.0'
|
51
51
|
gem 'bson_ext', '~> 1.9.0'
|
52
52
|
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
|
+
version: 0.9.4.pre1
|
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-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -475,6 +475,7 @@ files:
|
|
475
475
|
- lib/volt/models/validators/numericality_validator.rb
|
476
476
|
- lib/volt/models/validators/phone_number_validator.rb
|
477
477
|
- lib/volt/models/validators/presence_validator.rb
|
478
|
+
- lib/volt/models/validators/type_validator.rb
|
478
479
|
- lib/volt/models/validators/unique_validator.rb
|
479
480
|
- lib/volt/models/validators/user_validation.rb
|
480
481
|
- lib/volt/page/bindings/attribute_binding.rb
|
@@ -679,6 +680,7 @@ files:
|
|
679
680
|
- spec/models/validators/length_validator_spec.rb
|
680
681
|
- spec/models/validators/phone_number_validator_spec.rb
|
681
682
|
- spec/models/validators/shared_examples_for_validators.rb
|
683
|
+
- spec/models/validators/type_validator_spec.rb
|
682
684
|
- spec/models/validators/unique_validator_spec.rb
|
683
685
|
- spec/page/bindings/content_binding_spec.rb
|
684
686
|
- spec/page/bindings/each_binding_spec.rb
|
@@ -828,9 +830,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
828
830
|
version: '2.1'
|
829
831
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
830
832
|
requirements:
|
831
|
-
- - "
|
833
|
+
- - ">"
|
832
834
|
- !ruby/object:Gem::Version
|
833
|
-
version:
|
835
|
+
version: 1.3.1
|
834
836
|
requirements: []
|
835
837
|
rubyforge_project:
|
836
838
|
rubygems_version: 2.4.5
|
@@ -924,6 +926,7 @@ test_files:
|
|
924
926
|
- spec/models/validators/length_validator_spec.rb
|
925
927
|
- spec/models/validators/phone_number_validator_spec.rb
|
926
928
|
- spec/models/validators/shared_examples_for_validators.rb
|
929
|
+
- spec/models/validators/type_validator_spec.rb
|
927
930
|
- spec/models/validators/unique_validator_spec.rb
|
928
931
|
- spec/page/bindings/content_binding_spec.rb
|
929
932
|
- spec/page/bindings/each_binding_spec.rb
|