volt 0.7.23 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +8 -1
- data/CHANGELOG.md +22 -0
- data/Gemfile +8 -0
- data/Guardfile +2 -2
- data/Readme.md +139 -136
- data/VERSION +1 -1
- data/app/volt/assets/js/setImmediate.js +175 -0
- data/app/volt/tasks/live_query/data_store.rb +0 -2
- data/app/volt/tasks/live_query/live_query.rb +4 -4
- data/docs/GETTING_STARTED.md +24 -3
- data/docs/WHY.md +1 -22
- data/lib/volt.rb +20 -1
- data/lib/volt/console.rb +20 -0
- data/lib/volt/controllers/model_controller.rb +25 -11
- data/lib/volt/extra_core/object.rb +2 -14
- data/lib/volt/extra_core/string.rb +4 -0
- data/lib/volt/models.rb +0 -1
- data/lib/volt/models/array_model.rb +8 -16
- data/lib/volt/models/cursor.rb +1 -1
- data/lib/volt/models/model.rb +40 -60
- data/lib/volt/models/model_hash_behaviour.rb +10 -24
- data/lib/volt/models/model_helpers.rb +2 -2
- data/lib/volt/models/model_state.rb +1 -1
- data/lib/volt/models/model_wrapper.rb +4 -4
- data/lib/volt/models/persistors/array_store.rb +44 -28
- data/lib/volt/models/persistors/base.rb +1 -1
- data/lib/volt/models/persistors/model_store.rb +1 -1
- data/lib/volt/models/persistors/params.rb +5 -1
- data/lib/volt/models/persistors/query/query_listener.rb +2 -0
- data/lib/volt/models/persistors/store.rb +3 -2
- data/lib/volt/models/persistors/store_state.rb +7 -2
- data/lib/volt/models/url.rb +35 -29
- data/lib/volt/models/validations.rb +7 -17
- data/lib/volt/page/bindings/attribute_binding.rb +57 -39
- data/lib/volt/page/bindings/base_binding.rb +0 -14
- data/lib/volt/page/bindings/content_binding.rb +15 -18
- data/lib/volt/page/bindings/each_binding.rb +67 -34
- data/lib/volt/page/bindings/if_binding.rb +15 -12
- data/lib/volt/page/bindings/template_binding.rb +77 -59
- data/lib/volt/page/bindings/template_binding/grouped_controllers.rb +19 -4
- data/lib/volt/page/channel.rb +22 -38
- data/lib/volt/page/channel_stub.rb +3 -6
- data/lib/volt/page/page.rb +24 -26
- data/lib/volt/page/string_template_renderer.rb +46 -0
- data/lib/volt/page/sub_context.rb +7 -1
- data/lib/volt/page/targets/binding_document/component_node.rb +11 -9
- data/lib/volt/page/tasks.rb +3 -2
- data/lib/volt/page/url_tracker.rb +4 -3
- data/lib/volt/reactive/computation.rb +131 -0
- data/lib/volt/reactive/dependency.rb +71 -0
- data/lib/volt/reactive/eventable.rb +82 -0
- data/lib/volt/reactive/hash_dependency.rb +36 -0
- data/lib/volt/{controllers → reactive}/reactive_accessors.rb +8 -11
- data/lib/volt/reactive/reactive_array.rb +100 -193
- data/lib/volt/reactive/reactive_hash.rb +49 -0
- data/lib/volt/server/html_parser/attribute_scope.rb +24 -4
- data/lib/volt/server/html_parser/if_view_scope.rb +15 -15
- data/lib/volt/server/html_parser/view_scope.rb +31 -1
- data/spec/apps/kitchen_sink/Gemfile +4 -8
- data/spec/apps/kitchen_sink/app/main/config/dependencies.rb +8 -0
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +8 -1
- data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +8 -0
- data/spec/apps/kitchen_sink/app/main/views/main/bindings.html +73 -0
- data/spec/apps/kitchen_sink/app/main/views/main/index.html +6 -1
- data/spec/apps/kitchen_sink/app/main/views/main/main.html +26 -6
- data/spec/apps/kitchen_sink/app/main/views/main/store.html +6 -0
- data/spec/controllers/reactive_accessors_spec.rb +13 -15
- data/spec/integration/bindings_spec.rb +159 -0
- data/spec/integration/templates_spec.rb +15 -0
- data/spec/models/model_spec.rb +130 -228
- data/spec/reactive/computation_spec.rb +63 -0
- data/spec/reactive/dependency_spec.rb +5 -0
- data/spec/reactive/eventable_spec.rb +48 -0
- data/spec/reactive/reactive_array_spec.rb +97 -0
- data/spec/router/routes_spec.rb +26 -27
- data/spec/server/html_parser/view_parser_spec.rb +3 -21
- data/spec/server/rack/asset_files_spec.rb +1 -1
- data/templates/project/app/main/views/main/main.html +2 -2
- metadata +29 -41
- data/lib/volt/extra_core/time.rb +0 -16
- data/lib/volt/page/draw_cycle.rb +0 -31
- data/lib/volt/page/memory_test.rb +0 -26
- data/lib/volt/page/reactive_template.rb +0 -32
- data/lib/volt/reactive/array_extensions.rb +0 -12
- data/lib/volt/reactive/destructive_methods.rb +0 -19
- data/lib/volt/reactive/event_chain.rb +0 -125
- data/lib/volt/reactive/events.rb +0 -216
- data/lib/volt/reactive/object_tracking.rb +0 -14
- data/lib/volt/reactive/reactive_block.rb +0 -88
- data/lib/volt/reactive/reactive_generator.rb +0 -44
- data/lib/volt/reactive/reactive_tags.rb +0 -71
- data/lib/volt/reactive/reactive_value.rb +0 -427
- data/lib/volt/reactive/string_extensions.rb +0 -31
- data/spec/integration/test_integration_spec.rb +0 -14
- data/spec/models/event_chain_spec.rb +0 -150
- data/spec/models/model_buffers_spec.rb +0 -9
- data/spec/models/old_model_spec.rb +0 -67
- data/spec/models/reactive_array_spec.rb +0 -364
- data/spec/models/reactive_block_spec.rb +0 -13
- data/spec/models/reactive_call_times_spec.rb +0 -28
- data/spec/models/reactive_generator_spec.rb +0 -58
- data/spec/models/reactive_tags_spec.rb +0 -35
- data/spec/models/reactive_value_spec.rb +0 -370
- data/spec/models/store_spec.rb +0 -16
- data/spec/models/string_extensions_spec.rb +0 -57
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'volt/reactive/hash_dependency'
|
2
|
+
|
3
|
+
class ReactiveHash
|
4
|
+
def initialize(values={})
|
5
|
+
@hash = values
|
6
|
+
@deps = HashDependency.new
|
7
|
+
@all_deps = Dependency.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def ==(val)
|
11
|
+
@all_deps.depend
|
12
|
+
@hash == val
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO: We should finish off this class for reactivity
|
16
|
+
def method_missing(method_name, *args, &block)
|
17
|
+
@all_deps.depend
|
18
|
+
|
19
|
+
return @hash.send(method_name, *args, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def [](key)
|
23
|
+
@deps.depend(key)
|
24
|
+
|
25
|
+
return @hash[key]
|
26
|
+
end
|
27
|
+
|
28
|
+
def []=(key, value)
|
29
|
+
@deps.changed!(key)
|
30
|
+
@all_deps.changed!
|
31
|
+
|
32
|
+
@hash[key] = value
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete(key)
|
36
|
+
@deps.delete(key)
|
37
|
+
@hash.delete(key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def clear
|
41
|
+
@hash.each_pair do |key,_|
|
42
|
+
delete(key)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def inspect
|
47
|
+
"#<ReactiveHash #{@hash.inspect}>"
|
48
|
+
end
|
49
|
+
end
|
@@ -53,11 +53,31 @@ module AttributeScope
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
# TODO: We should use a real parser for this
|
57
|
+
def getter_to_setter(getter)
|
58
|
+
getter = getter.strip
|
59
|
+
|
60
|
+
# Convert a getter into a setter
|
61
|
+
if getter.index('.') || getter.index('@')
|
62
|
+
prefix = ''
|
63
|
+
else
|
64
|
+
prefix = 'self.'
|
65
|
+
end
|
66
|
+
|
67
|
+
return "#{prefix}#{getter}=(val)"
|
68
|
+
end
|
69
|
+
|
56
70
|
# Add an attribute binding on the tag, bind directly to the getter in the binding
|
57
71
|
def add_single_attribute(id, attribute_name, parts)
|
58
72
|
getter = parts[0][1..-2]
|
59
73
|
|
60
|
-
|
74
|
+
# if getter.index('@')
|
75
|
+
# raise "Bindings currently do not support instance variables"
|
76
|
+
# end
|
77
|
+
|
78
|
+
setter = getter_to_setter(getter)
|
79
|
+
|
80
|
+
save_binding(id, "lambda { |__p, __t, __c, __id| AttributeBinding.new(__p, __t, __c, __id, #{attribute_name.inspect}, Proc.new { #{getter} }, Proc.new { |val| #{setter} }) }")
|
61
81
|
end
|
62
82
|
|
63
83
|
|
@@ -74,12 +94,12 @@ module AttributeScope
|
|
74
94
|
end
|
75
95
|
end
|
76
96
|
|
77
|
-
|
97
|
+
string_template_renderer_path = add_string_template_renderer(content)
|
78
98
|
|
79
|
-
save_binding(id, "lambda { |__p, __t, __c, __id| AttributeBinding.new(__p, __t, __c, __id, #{attribute_name.inspect}, Proc.new {
|
99
|
+
save_binding(id, "lambda { |__p, __t, __c, __id| AttributeBinding.new(__p, __t, __c, __id, #{attribute_name.inspect}, Proc.new { StringTemplateRender.new(__p, __c, #{string_template_renderer_path.inspect}) }) }")
|
80
100
|
end
|
81
101
|
|
82
|
-
def
|
102
|
+
def add_string_template_renderer(content)
|
83
103
|
path = @path + "/_rv#{@binding_number}"
|
84
104
|
new_handler = ViewHandler.new(path, false)
|
85
105
|
@binding_number += 1
|
@@ -1,21 +1,21 @@
|
|
1
1
|
class IfViewScope < ViewScope
|
2
2
|
def initialize(handler, path, content)
|
3
3
|
super(handler, path)
|
4
|
-
|
4
|
+
|
5
5
|
@original_path = @path
|
6
|
-
|
6
|
+
|
7
7
|
@last_content = content
|
8
8
|
@branches = []
|
9
|
-
|
9
|
+
|
10
10
|
# We haven't added the if yet
|
11
11
|
@if_binding_number = @handler.last.binding_number
|
12
12
|
@handler.last.binding_number += 1
|
13
|
-
|
13
|
+
|
14
14
|
@path_number = 0
|
15
|
-
|
15
|
+
|
16
16
|
new_path
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def new_path
|
20
20
|
@path = @original_path + "/__if#{@path_number}"
|
21
21
|
@path_number += 1
|
@@ -27,26 +27,26 @@ class IfViewScope < ViewScope
|
|
27
27
|
close_scope(false)
|
28
28
|
|
29
29
|
@last_content = content
|
30
|
-
|
30
|
+
|
31
31
|
# Clear existing
|
32
32
|
@html = ''
|
33
33
|
@bindings = {}
|
34
|
-
|
34
|
+
|
35
35
|
# Close scope removes us, so lets add it back.
|
36
36
|
@handler.scope << self
|
37
|
-
|
37
|
+
|
38
38
|
@binding_number = 0
|
39
39
|
|
40
40
|
# Generate a new template path for this section.
|
41
41
|
new_path
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def close_scope(final=true)
|
45
|
-
@branches << [@last_content, path]
|
45
|
+
@branches << [@last_content, path]
|
46
46
|
|
47
47
|
super()
|
48
48
|
|
49
|
-
if final
|
49
|
+
if final
|
50
50
|
# Add the binding to the parent
|
51
51
|
branches = @branches.map do |branch|
|
52
52
|
content = branch[0]
|
@@ -55,16 +55,16 @@ class IfViewScope < ViewScope
|
|
55
55
|
else
|
56
56
|
content = "Proc.new { #{branch[0]} }"
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
"[#{content}, #{branch[1].inspect}]"
|
60
60
|
end.join(', ')
|
61
|
-
|
61
|
+
|
62
62
|
new_scope = @handler.last
|
63
63
|
|
64
64
|
# variables are captured for branches, so we must prefix them so they don't conflict.
|
65
65
|
# page, target, context, id
|
66
66
|
new_scope.save_binding(@if_binding_number, "lambda { |__p, __t, __c, __id| IfBinding.new(__p, __t, __c, __id, [#{branches}]) }")
|
67
|
-
|
67
|
+
|
68
68
|
new_scope.html << "<!-- $#{@if_binding_number} --><!-- $/#{@if_binding_number} -->"
|
69
69
|
end
|
70
70
|
end
|
@@ -77,6 +77,22 @@ class ViewScope
|
|
77
77
|
@binding_number += 1
|
78
78
|
end
|
79
79
|
|
80
|
+
# Returns ruby code to fetch the parent. (by removing the last fetch)
|
81
|
+
# TODO: Probably want to do this with AST transforms with the parser/unparser gems
|
82
|
+
def parent_fetcher(getter)
|
83
|
+
parent = getter.strip.gsub(/[.][^.]+$/, '')
|
84
|
+
|
85
|
+
if parent.blank? || !getter.index('.')
|
86
|
+
parent = 'self'
|
87
|
+
end
|
88
|
+
|
89
|
+
return parent
|
90
|
+
end
|
91
|
+
|
92
|
+
def last_method_name(getter)
|
93
|
+
return getter.strip[/[^.]+$/]
|
94
|
+
end
|
95
|
+
|
80
96
|
def add_component(tag_name, attributes, unary)
|
81
97
|
component_name = tag_name[1..-1].gsub(':', '/')
|
82
98
|
|
@@ -93,7 +109,21 @@ class ViewScope
|
|
93
109
|
# Multiple bindings
|
94
110
|
elsif parts.size == 1 && binding_count == 1
|
95
111
|
# A single binding
|
96
|
-
|
112
|
+
getter = value[1..-2]
|
113
|
+
data_hash << "#{name.inspect} => Proc.new { #{getter} }"
|
114
|
+
|
115
|
+
setter = getter_to_setter(getter)
|
116
|
+
data_hash << "#{(name + "=").inspect} => Proc.new { |val| #{setter} }"
|
117
|
+
|
118
|
+
# Add an _parent fetcher. Useful for things like volt-fields to get the parent model.
|
119
|
+
parent = parent_fetcher(getter)
|
120
|
+
|
121
|
+
# TODO: This adds some overhead, perhaps there is a way to compute this dynamically on the
|
122
|
+
# front-end.
|
123
|
+
data_hash << "#{(name + "_parent").inspect} => Proc.new { #{parent} }"
|
124
|
+
|
125
|
+
# Add a _last_method property. This is useful
|
126
|
+
data_hash << "#{(name + "_last_method").inspect} => #{last_method_name(getter).inspect}"
|
97
127
|
end
|
98
128
|
else
|
99
129
|
# String
|
@@ -1,7 +1,6 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
gem 'volt', path: '
|
4
|
-
|
3
|
+
gem 'volt', path: '../../../'
|
5
4
|
|
6
5
|
# The following gem's are optional for themeing
|
7
6
|
|
@@ -12,12 +11,10 @@ gem 'volt-bootstrap'
|
|
12
11
|
gem 'volt-bootstrap-jumbotron-theme'
|
13
12
|
|
14
13
|
|
15
|
-
gem 'volt-fields', path: '/Users/ryanstout/Sites/volt/apps/volt-fields'
|
16
|
-
|
17
14
|
# Server for MRI
|
18
15
|
platform :mri do
|
19
16
|
gem 'thin', '~> 1.6.0'
|
20
|
-
gem 'bson_ext'
|
17
|
+
gem 'bson_ext', '~> 1.9.0'
|
21
18
|
end
|
22
19
|
|
23
20
|
# Server for jruby
|
@@ -25,8 +22,7 @@ platform :jruby do
|
|
25
22
|
gem 'jubilee'
|
26
23
|
end
|
27
24
|
|
25
|
+
|
28
26
|
#---------------------
|
29
27
|
# Needed at the moment
|
30
|
-
gem '
|
31
|
-
gem 'opal-jquery', :git => 'https://github.com/opal/opal-jquery.git'
|
32
|
-
gem 'sockjs', git: 'https://github.com/kacperk/sockjs-ruby.git', require: false, platforms: :mri
|
28
|
+
gem 'volt-sockjs', require: false, platforms: :mri
|
@@ -1 +1,8 @@
|
|
1
|
-
|
1
|
+
# See https://github.com/voltrb/volt#routes for more info on routes
|
2
|
+
|
3
|
+
get "/bindings/{_route_test}", _action: 'bindings'
|
4
|
+
get "/bindings", _action: 'bindings'
|
5
|
+
get "/store", _action: 'store'
|
6
|
+
|
7
|
+
# The main route, this should be last. It will match any params not previously matched.
|
8
|
+
get '/', {}
|
@@ -1,3 +1,11 @@
|
|
1
1
|
class MainController < ModelController
|
2
2
|
model :page
|
3
|
+
|
4
|
+
private
|
5
|
+
# the main template contains a #template binding that shows another
|
6
|
+
# template. This is the path to that template. It may change based
|
7
|
+
# on the params._controller and params._action values.
|
8
|
+
def main_path
|
9
|
+
params._controller.or('main') + "/" + params._action.or('index')
|
10
|
+
end
|
3
11
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
<:Title>
|
2
|
+
Bindings
|
3
|
+
|
4
|
+
<:Body>
|
5
|
+
<h1>Bindings</h1>
|
6
|
+
|
7
|
+
|
8
|
+
<h2>Text</h2>
|
9
|
+
<table class="table">
|
10
|
+
<tr>
|
11
|
+
<td>Page</td>
|
12
|
+
<td><input type="text" id="pageName1" value="{page._name}"></td>
|
13
|
+
<td><input type="text" id="pageName2" value="{page._name}"></td>
|
14
|
+
<td id="pageName3">{page._name}</td>
|
15
|
+
</tr>
|
16
|
+
<tr>
|
17
|
+
<td>Params</td>
|
18
|
+
<td><input type="text" id="paramsName1" value="{params._name}"></td>
|
19
|
+
<td><input type="text" id="paramsName2" value="{params._name}"></td>
|
20
|
+
<td id="paramsName3">{params._name}</td>
|
21
|
+
</tr>
|
22
|
+
<tr>
|
23
|
+
<td>Routes</td>
|
24
|
+
<td><input type="text" id="routesName1" value="{params._route_test}"></td>
|
25
|
+
<td><input type="text" id="routesName2" value="{params._route_test}"></td>
|
26
|
+
<td id="routesName3">{params._route_test}</td>
|
27
|
+
</tr>
|
28
|
+
</table>
|
29
|
+
|
30
|
+
<h2>Checkbox</h2>
|
31
|
+
|
32
|
+
<table class="table">
|
33
|
+
<tr>
|
34
|
+
<td>Page</td>
|
35
|
+
<td><input type="checkbox" id="pageCheck1" checked="{page._check}" /></td>
|
36
|
+
<td><input type="checkbox" id="pageCheck2" checked="{page._check}" /></td>
|
37
|
+
<td id="pageCheck3">{page._check}</td>
|
38
|
+
</tr>
|
39
|
+
<tr>
|
40
|
+
<td>Params</td>
|
41
|
+
<td><input type="checkbox" id="paramsCheck1" checked="{params._check}" /></td>
|
42
|
+
<td><input type="checkbox" id="paramsCheck2" checked="{params._check}" /></td>
|
43
|
+
<td id="paramsCheck3">{params._check}</td>
|
44
|
+
</tr>
|
45
|
+
</table>
|
46
|
+
|
47
|
+
<h2>Radio</h2>
|
48
|
+
|
49
|
+
<table class="table">
|
50
|
+
<tr>
|
51
|
+
<td>Page</td>
|
52
|
+
<td><input type="radio" id="pageRadio1" checked="{page._radio}" value="one" /></td>
|
53
|
+
<td><input type="radio" id="pageRadio2" checked="{page._radio}" value="two" /></td>
|
54
|
+
<td id="pageRadio3">{page._radio}</td>
|
55
|
+
</tr>
|
56
|
+
<tr>
|
57
|
+
<td></td>
|
58
|
+
<td><input type="radio" checked="{page._radio}" value="one" /></td>
|
59
|
+
<td><input type="radio" checked="{page._radio}" value="two" /></td>
|
60
|
+
<td></td>
|
61
|
+
</tr>
|
62
|
+
</table>
|
63
|
+
|
64
|
+
<h2>Textarea</h2>
|
65
|
+
<table class="table">
|
66
|
+
<tr>
|
67
|
+
<td>Page</td>
|
68
|
+
<td><textarea id="textareaName1">{page._textarea_name}</textarea></td>
|
69
|
+
<td><textarea id="textareaName2">{page._textarea_name}</textarea></td>
|
70
|
+
<td id="textareaName3">{page._textarea_name}</td>
|
71
|
+
</tr>
|
72
|
+
</table>
|
73
|
+
|
@@ -1,9 +1,29 @@
|
|
1
1
|
<:Title>
|
2
|
-
|
2
|
+
{#template main_path, "title", {controller_group: 'main'}} - KitchenSink
|
3
3
|
|
4
4
|
<:Body>
|
5
|
-
<
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
<div class="container">
|
6
|
+
<div class="header">
|
7
|
+
<ul class="nav nav-pills pull-right">
|
8
|
+
<:nav href="/" text="Home" />
|
9
|
+
<:nav href="/bindings" text="Bindings" />
|
10
|
+
<:nav href="/store" text="Store" />
|
11
|
+
</ul>
|
12
|
+
<h3 class="text-muted">Project name</h3>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<:volt:notices />
|
16
|
+
|
17
|
+
{#template main_path, 'body', {controller_group: 'main'}}
|
18
|
+
|
19
|
+
<div class="footer">
|
20
|
+
<p>© Company 2014</p>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<:Nav>
|
26
|
+
<li class="{#if url.path.split('/')[1] == attrs.href.split('/')[1]}active{/}">
|
27
|
+
<a href="{attrs.href}">{attrs.text}</a>
|
28
|
+
</li>
|
29
|
+
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'volt/
|
2
|
+
require 'volt/reactive/reactive_accessors'
|
3
3
|
|
4
4
|
class TestReactiveAccessors
|
5
5
|
include ReactiveAccessors
|
@@ -8,12 +8,6 @@ class TestReactiveAccessors
|
|
8
8
|
end
|
9
9
|
|
10
10
|
describe ReactiveAccessors do
|
11
|
-
it "should return the same reactive value after each read" do
|
12
|
-
inst = TestReactiveAccessors.new
|
13
|
-
|
14
|
-
expect(inst._name.reactive_manager.object_id).to eq(inst._name.reactive_manager.object_id)
|
15
|
-
end
|
16
|
-
|
17
11
|
it "should assign a reactive value" do
|
18
12
|
inst = TestReactiveAccessors.new
|
19
13
|
|
@@ -24,19 +18,23 @@ describe ReactiveAccessors do
|
|
24
18
|
it "should start nil" do
|
25
19
|
inst = TestReactiveAccessors.new
|
26
20
|
|
27
|
-
expect(inst._name
|
21
|
+
expect(inst._name).to eq(nil)
|
28
22
|
end
|
29
23
|
|
30
|
-
it
|
24
|
+
it 'should trigger changed when assigning a new value' do
|
31
25
|
inst = TestReactiveAccessors.new
|
26
|
+
values = []
|
32
27
|
|
33
|
-
inst._name
|
34
|
-
rv1_id = inst._name.reactive_manager.object_id
|
28
|
+
-> { values << inst._name }.watch!
|
35
29
|
|
36
|
-
|
37
|
-
rv2_id = inst._name.reactive_manager.object_id
|
30
|
+
expect(values).to eq([nil])
|
38
31
|
|
39
|
-
|
40
|
-
|
32
|
+
inst._name = 'Ryan'
|
33
|
+
Computation.flush!
|
34
|
+
expect(values).to eq([nil,'Ryan'])
|
41
35
|
|
36
|
+
inst._name = 'Stout'
|
37
|
+
Computation.flush!
|
38
|
+
expect(values).to eq([nil,'Ryan','Stout'])
|
39
|
+
end
|
42
40
|
end
|