volt 0.9.6 → 0.9.7.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/CHANGELOG.md +26 -0
- data/Gemfile +6 -1
- data/README.md +2 -0
- data/Rakefile +1 -0
- data/app/volt/models/active_volt_instance.rb +8 -6
- data/app/volt/models/user.rb +11 -2
- data/app/volt/models/volt_app_property.rb +8 -0
- data/app/volt/tasks/query_tasks.rb +23 -31
- data/app/volt/tasks/store_tasks.rb +2 -2
- data/app/volt/tasks/volt_admin_tasks.rb +24 -0
- data/docs/UPGRADE_GUIDE.md +6 -0
- data/lib/volt.rb +19 -12
- data/lib/volt/boot.rb +1 -0
- data/lib/volt/cli.rb +19 -8
- data/lib/volt/cli/console.rb +0 -1
- data/lib/volt/cli/generators.rb +14 -3
- data/lib/volt/cli/migrate.rb +26 -0
- data/lib/volt/config.rb +17 -4
- data/lib/volt/controllers/http_controller.rb +12 -0
- data/lib/volt/data_stores/base_adaptor_client.rb +2 -2
- data/lib/volt/data_stores/base_adaptor_server.rb +2 -0
- data/lib/volt/data_stores/data_store.rb +20 -14
- data/lib/volt/extra_core/class.rb +28 -14
- data/lib/volt/extra_core/hash.rb +5 -0
- data/lib/volt/extra_core/string.rb +3 -1
- data/lib/volt/helpers/time.rb +9 -43
- data/lib/volt/helpers/time/calculations.rb +204 -0
- data/lib/volt/helpers/time/distance.rb +63 -0
- data/lib/volt/helpers/time/duration.rb +71 -0
- data/lib/volt/helpers/time/local_calculations.rb +49 -0
- data/lib/volt/helpers/time/local_volt_time.rb +23 -0
- data/lib/volt/helpers/time/numeric.rb +59 -0
- data/lib/volt/helpers/time/volt_time.rb +170 -0
- data/lib/volt/models.rb +5 -0
- data/lib/volt/models/array_model.rb +33 -6
- data/lib/volt/models/associations.rb +146 -23
- data/lib/volt/models/buffer.rb +38 -41
- data/lib/volt/models/cursor.rb +15 -0
- data/lib/volt/models/errors.rb +11 -0
- data/lib/volt/models/field_helpers.rb +108 -68
- data/lib/volt/models/helpers/array_model.rb +4 -0
- data/lib/volt/models/helpers/base.rb +8 -1
- data/lib/volt/models/helpers/change_helpers.rb +31 -12
- data/lib/volt/models/helpers/defaults.rb +15 -0
- data/lib/volt/models/location.rb +20 -6
- data/lib/volt/models/migrations/migration.rb +23 -0
- data/lib/volt/models/migrations/migration_runner.rb +146 -0
- data/lib/volt/models/model.rb +38 -1
- data/lib/volt/models/permissions.rb +8 -1
- data/lib/volt/models/persistors/array_store.rb +87 -8
- data/lib/volt/models/persistors/base.rb +19 -0
- data/lib/volt/models/persistors/model_store.rb +1 -1
- data/lib/volt/models/persistors/page.rb +4 -1
- data/lib/volt/models/persistors/query/query_identifier.rb +102 -0
- data/lib/volt/models/persistors/query/query_listener.rb +57 -12
- data/lib/volt/models/root_models/root_models.rb +19 -0
- data/lib/volt/models/url.rb +11 -2
- data/lib/volt/models/validations/validations.rb +5 -2
- data/lib/volt/models/validators/type_validator.rb +11 -0
- data/lib/volt/models/validators/unique_validator.rb +2 -2
- data/lib/volt/page/bindings/attribute_binding.rb +23 -1
- data/lib/volt/page/targets/attribute_section.rb +7 -0
- data/lib/volt/page/targets/binding_document/component_node.rb +44 -18
- data/lib/volt/page/targets/binding_document/tag_node.rb +41 -0
- data/lib/volt/page/tasks.rb +16 -8
- data/lib/volt/queries/live_query.rb +109 -0
- data/lib/volt/queries/live_query_pool.rb +58 -0
- data/lib/volt/queries/live_subquery.rb +0 -0
- data/lib/volt/queries/query_association_splitter.rb +31 -0
- data/lib/volt/queries/query_diff.rb +100 -0
- data/lib/volt/queries/query_runner.rb +110 -0
- data/lib/volt/queries/query_subscription.rb +80 -0
- data/lib/volt/queries/query_subscription_pool.rb +37 -0
- data/lib/volt/reactive/eventable.rb +8 -0
- data/lib/volt/reactive/reactive_array.rb +0 -4
- data/lib/volt/router/routes.rb +81 -31
- data/lib/volt/server/message_bus/base_message_bus.rb +9 -3
- data/lib/volt/server/message_bus/peer_to_peer.rb +6 -6
- data/lib/volt/server/message_bus/peer_to_peer/server_tracker.rb +1 -1
- data/lib/volt/server/middleware/default_middleware_stack.rb +12 -8
- data/lib/volt/server/rack/component_paths.rb +31 -4
- data/lib/volt/server/rack/http_content_types.rb +62 -0
- data/lib/volt/server/rack/http_resource.rb +1 -1
- data/lib/volt/server/rack/index_files.rb +8 -1
- data/lib/volt/server/rack/opal_files.rb +16 -1
- data/lib/volt/server/rack/sprockets_helpers_setup.rb +32 -1
- data/lib/volt/server/socket_connection_handler.rb +16 -7
- data/lib/volt/server/template_handlers/sprockets_component_handler.rb +5 -3
- data/lib/volt/spec/capybara.rb +4 -3
- data/lib/volt/spec/setup.rb +5 -0
- data/lib/volt/tasks/dispatcher.rb +3 -1
- data/lib/volt/utils/data_transformer.rb +4 -4
- data/lib/volt/utils/ejson.rb +19 -6
- data/lib/volt/utils/promise_extensions.rb +1 -1
- data/lib/volt/utils/time_opal_patch.rb +749 -0
- data/lib/volt/utils/time_patch.rb +11 -4
- data/lib/volt/version.rb +1 -1
- data/lib/volt/volt/app.rb +19 -11
- data/lib/volt/volt/properties.rb +24 -0
- data/lib/volt/volt/server_setup/app.rb +30 -7
- data/lib/volt/volt/users.rb +15 -3
- data/spec/apps/kitchen_sink/Gemfile +5 -1
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +1 -0
- data/spec/apps/kitchen_sink/app/main/controllers/save_controller.rb +1 -1
- data/spec/apps/kitchen_sink/app/main/controllers/server/simple_http_controller.rb +4 -0
- data/spec/apps/kitchen_sink/app/main/controllers/todos_controller.rb +4 -2
- data/spec/apps/kitchen_sink/app/main/models/post.rb +0 -1
- data/spec/apps/kitchen_sink/app/main/models/todo.rb +4 -0
- data/spec/apps/kitchen_sink/app/main/views/mailers/reset_password.html +10 -0
- data/spec/apps/kitchen_sink/app/main/views/todos/index.html +2 -0
- data/spec/apps/kitchen_sink/config/app.rb +2 -0
- data/spec/apps/migrations/config/db/migrations/1445111704_migration1.rb +7 -0
- data/spec/apps/migrations/config/db/migrations/1445113517_migration2.rb +7 -0
- data/spec/apps/migrations/config/db/migrations/1445115200_migration3.rb +7 -0
- data/spec/extra_core/class_spec.rb +10 -0
- data/spec/helpers/distance_spec.rb +35 -0
- data/spec/helpers/duration_spec.rb +160 -0
- data/spec/helpers/volt_time_spec.rb +275 -0
- data/spec/integration/callbacks_spec.rb +2 -1
- data/spec/integration/http_endpoints_spec.rb +4 -0
- data/spec/integration/save_spec.rb +1 -1
- data/spec/integration/todos_spec.rb +7 -5
- data/spec/models/array_model_spec.rb +17 -3
- data/spec/models/associations_spec.rb +48 -1
- data/spec/models/field_helpers_spec.rb +7 -3
- data/spec/models/migrations/migration_runner_spec.rb +69 -0
- data/spec/models/model_spec.rb +42 -8
- data/spec/models/permissions_spec.rb +20 -8
- data/spec/models/persistors/array_store_spec.rb +18 -0
- data/spec/models/persistors/page_spec.rb +15 -10
- data/spec/models/persistors/store_spec.rb +13 -3
- data/spec/models/url_spec.rb +4 -3
- data/spec/models/user_spec.rb +6 -3
- data/spec/models/user_validation_spec.rb +3 -3
- data/spec/models/validations_spec.rb +4 -0
- data/spec/models/validators/block_validations_spec.rb +9 -5
- data/spec/models/validators/email_validator_spec.rb +2 -0
- data/spec/models/validators/lifecycle_callbacks_spec.rb +86 -0
- data/spec/models/validators/unique_validator_spec.rb +1 -0
- data/spec/page/path_string_renderer_spec.rb +5 -0
- data/spec/queries/live_query_spec.rb +16 -0
- data/spec/queries/query_association_splitter_spec.rb +14 -0
- data/spec/queries/query_diff_spec.rb +132 -0
- data/spec/queries/query_identifier_spec.rb +98 -0
- data/spec/queries/query_runner_spec.rb +63 -0
- data/spec/queries/query_tracker_spec.rb +141 -0
- data/spec/router/routes_spec.rb +52 -21
- data/spec/server/middleware/rack_content_types_spec.rb +78 -0
- data/spec/server/rack/asset_files_spec.rb +38 -30
- data/spec/spec_helper.rb +8 -0
- data/spec/utils/ejson_spec.rb +9 -8
- data/spec/utils/ejson_volt_time_spec.rb +65 -0
- data/templates/migration/migration.rb.tt +9 -0
- data/templates/newgem/gitignore.tt +1 -0
- data/templates/project/Gemfile.tt +19 -2
- data/templates/project/README.md.tt +6 -1
- data/templates/project/app/main/config/dependencies.rb +6 -0
- data/templates/project/config/app.rb.tt +18 -4
- data/volt.gemspec +2 -2
- metadata +73 -16
- data/app/volt/tasks/live_query/live_query_pool.rb +0 -48
- data/app/volt/tasks/live_query/query_tracker.rb +0 -92
- data/spec/tasks/live_query_spec.rb +0 -18
- data/spec/tasks/query_tasks.rb +0 -7
- data/spec/tasks/query_tracker_spec.rb +0 -145
@@ -1,48 +0,0 @@
|
|
1
|
-
require_relative 'live_query'
|
2
|
-
require 'volt/utils/generic_pool'
|
3
|
-
|
4
|
-
# LiveQueryPool runs on the server and keeps track of all outstanding
|
5
|
-
# queries.
|
6
|
-
|
7
|
-
class LiveQueryPool < Volt::GenericPool
|
8
|
-
def initialize(data_store, volt_app)
|
9
|
-
@data_store = data_store
|
10
|
-
@volt_app = volt_app
|
11
|
-
super()
|
12
|
-
end
|
13
|
-
|
14
|
-
def lookup(collection, query)
|
15
|
-
# collection = collection.to_sym
|
16
|
-
query = normalize_query(query)
|
17
|
-
|
18
|
-
super(collection, query)
|
19
|
-
end
|
20
|
-
|
21
|
-
def updated_collection(collection, skip_channel, from_message_bus=false)
|
22
|
-
# collection = collection.to_sym
|
23
|
-
lookup_all(collection).each do |live_query|
|
24
|
-
live_query.run(skip_channel)
|
25
|
-
end
|
26
|
-
|
27
|
-
msg_bus = @volt_app.message_bus
|
28
|
-
if !from_message_bus && collection != 'active_volt_instances' && msg_bus
|
29
|
-
msg_bus.publish('volt_collection_update', collection)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
# Creates the live query if it doesn't exist, and stores it so it
|
36
|
-
# can be found later.
|
37
|
-
def create(collection, query = {})
|
38
|
-
# collection = collection.to_sym
|
39
|
-
# If not already setup, create a new one for this collection/query
|
40
|
-
LiveQuery.new(self, @data_store, collection, query)
|
41
|
-
end
|
42
|
-
|
43
|
-
def normalize_query(query)
|
44
|
-
# TODO: add something to sort query properties so the queries are
|
45
|
-
# always compared the same.
|
46
|
-
query
|
47
|
-
end
|
48
|
-
end
|
@@ -1,92 +0,0 @@
|
|
1
|
-
# The query tracker runs queries and then tracks the changes
|
2
|
-
# that take place.
|
3
|
-
class QueryTracker
|
4
|
-
attr_accessor :results
|
5
|
-
|
6
|
-
def initialize(live_query, data_store)
|
7
|
-
@live_query = live_query
|
8
|
-
@data_store = data_store
|
9
|
-
|
10
|
-
# Stores the list of id's currently associated with this query
|
11
|
-
@current_ids = []
|
12
|
-
@results = []
|
13
|
-
@results_hash = {}
|
14
|
-
end
|
15
|
-
|
16
|
-
# Runs the query, stores the results and updates the current_ids
|
17
|
-
def run(skip_channel = nil)
|
18
|
-
@previous_results = @results
|
19
|
-
@previous_results_hash = @results_hash
|
20
|
-
@previous_ids = @current_ids
|
21
|
-
|
22
|
-
# Run the query again
|
23
|
-
@results = @data_store.query(@live_query.collection, @live_query.query)
|
24
|
-
|
25
|
-
# Update the current_ids
|
26
|
-
@current_ids = @results.map { |r| r[:id] }
|
27
|
-
@results_hash = Hash[@results.map { |r| [r[:id], r] }]
|
28
|
-
|
29
|
-
process_changes(skip_channel)
|
30
|
-
end
|
31
|
-
|
32
|
-
# Looks at the changes in the last run and sends out notices
|
33
|
-
# all changes.
|
34
|
-
def process_changes(skip_channel)
|
35
|
-
return unless @previous_ids
|
36
|
-
|
37
|
-
detect_removed(skip_channel)
|
38
|
-
detect_added_and_moved(skip_channel)
|
39
|
-
detect_changed(skip_channel)
|
40
|
-
end
|
41
|
-
|
42
|
-
def detect_removed(skip_channel)
|
43
|
-
# Removed models
|
44
|
-
removed_ids = @previous_ids - @current_ids
|
45
|
-
if removed_ids.size > 0
|
46
|
-
@live_query.notify_removed(removed_ids, skip_channel)
|
47
|
-
end
|
48
|
-
|
49
|
-
# Update @previous_ids to relect the removed
|
50
|
-
@previous_ids &= @current_ids
|
51
|
-
end
|
52
|
-
|
53
|
-
# Loop through the new list, tracking in the old, notifies of any that
|
54
|
-
# have been added or moved.
|
55
|
-
def detect_added_and_moved(skip_channel)
|
56
|
-
previous_index = 0
|
57
|
-
@current_ids.each_with_index do |id, index|
|
58
|
-
if (cur_previous = @previous_ids[previous_index]) && cur_previous == id
|
59
|
-
# Same in both previous and new
|
60
|
-
previous_index += 1
|
61
|
-
next
|
62
|
-
end
|
63
|
-
|
64
|
-
# We have an item that didn't match the current position's previous
|
65
|
-
# TODO: make a hash so we don't have to do include?
|
66
|
-
if @previous_ids.include?(id)
|
67
|
-
# The location from the previous has changed, move to correct location.
|
68
|
-
|
69
|
-
# Remove from previous_ids, as it will be moved and we will be past it.
|
70
|
-
@previous_ids.delete(id)
|
71
|
-
@live_query.notify_moved(id, index, skip_channel)
|
72
|
-
else
|
73
|
-
# TODO: Faster lookup
|
74
|
-
data = @results_hash[id]
|
75
|
-
@live_query.notify_added(index, data, skip_channel)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# Finds all items in the previous results that have new values, and alerts
|
81
|
-
# of changes.
|
82
|
-
def detect_changed(skip_channel)
|
83
|
-
not_added_or_removed = @previous_ids & @current_ids
|
84
|
-
|
85
|
-
not_added_or_removed.each do |id|
|
86
|
-
if @previous_results_hash[id] != (data = @results_hash[id])
|
87
|
-
# Data hash changed
|
88
|
-
@live_query.notify_changed(id, data, skip_channel)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
if RUBY_PLATFORM != 'opal'
|
2
|
-
describe 'LiveQuery' do
|
3
|
-
before do
|
4
|
-
load File.join(File.dirname(__FILE__), '../../app/volt/tasks/live_query/live_query.rb')
|
5
|
-
end
|
6
|
-
|
7
|
-
it 'should run a query' do
|
8
|
-
pool = double('volt/pool')
|
9
|
-
data_store = double('volt/data store')
|
10
|
-
|
11
|
-
expect(data_store).to receive(:query).with('_items', {}).and_return([
|
12
|
-
{ 'id' => 0, '_name' => 'one' }
|
13
|
-
])
|
14
|
-
|
15
|
-
live_query = LiveQuery.new(pool, data_store, '_items', {})
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/spec/tasks/query_tasks.rb
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
if RUBY_PLATFORM != 'opal'
|
2
|
-
describe 'LiveQuery' do
|
3
|
-
before do
|
4
|
-
load File.join(File.dirname(__FILE__), '../../app/volt/tasks/live_query/live_query.rb')
|
5
|
-
end
|
6
|
-
|
7
|
-
# LiveQueryStub behaves as the front-end would with the changes to a
|
8
|
-
# live query. Instead of passing changes to the models to the front
|
9
|
-
# end, the changes are applied locally, then can be checked to see if
|
10
|
-
# the correct transitions have taken place.
|
11
|
-
class LiveQueryStub
|
12
|
-
attr_reader :collection, :query, :items
|
13
|
-
def initialize
|
14
|
-
@collection = '_items'
|
15
|
-
@query = {}
|
16
|
-
@items = []
|
17
|
-
end
|
18
|
-
|
19
|
-
def notify_removed(ids, skip_channel)
|
20
|
-
# Remove the id's that need to be removed
|
21
|
-
@items.reject! { |item| ids.include?(item[:id]) }
|
22
|
-
end
|
23
|
-
|
24
|
-
def notify_added(index, data, skip_channel)
|
25
|
-
@items.insert(index, data)
|
26
|
-
end
|
27
|
-
|
28
|
-
def notify_moved(id, index, skip_channel)
|
29
|
-
item = @items.find { |item| item[:id] == id }
|
30
|
-
@items.delete(item)
|
31
|
-
|
32
|
-
@items.insert(index, item)
|
33
|
-
end
|
34
|
-
|
35
|
-
def notify_changed(id, data, skip_channel)
|
36
|
-
item = @items.find { |item| item[:id] == id }
|
37
|
-
idx = @items.index(item)
|
38
|
-
@items.delete(item)
|
39
|
-
@items.insert(idx, data)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
before do
|
44
|
-
# Setup a live query stub
|
45
|
-
@live_query = LiveQueryStub.new
|
46
|
-
data_store = double('volt/data store')
|
47
|
-
|
48
|
-
# return an empty collection
|
49
|
-
@items = []
|
50
|
-
expect(data_store).to receive(:query).at_least(:once) { @items.dup }
|
51
|
-
|
52
|
-
@query_tracker = QueryTracker.new(@live_query, data_store)
|
53
|
-
@query_tracker.run
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'should add items' do
|
57
|
-
@items = [
|
58
|
-
{ id: 1, name: 'one' }
|
59
|
-
]
|
60
|
-
|
61
|
-
expect(@live_query.items).to eq([])
|
62
|
-
|
63
|
-
@query_tracker.run
|
64
|
-
|
65
|
-
expect(@live_query.items).to eq(@items)
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'should remove items' do
|
69
|
-
@items = [
|
70
|
-
{ id: 1, name: 'one' },
|
71
|
-
{ id: 2, name: 'two' }
|
72
|
-
]
|
73
|
-
@query_tracker.run
|
74
|
-
expect(@live_query.items).to eq(@items)
|
75
|
-
|
76
|
-
@items = [
|
77
|
-
{ id: 2, name: 'two' }
|
78
|
-
]
|
79
|
-
@query_tracker.run
|
80
|
-
expect(@live_query.items).to eq(@items)
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'should move items' do
|
84
|
-
@items = [
|
85
|
-
{ id: 1, name: 'one' },
|
86
|
-
{ id: 2, name: 'two' },
|
87
|
-
{ id: 3, name: 'three' }
|
88
|
-
]
|
89
|
-
@query_tracker.run
|
90
|
-
expect(@live_query.items).to eq(@items)
|
91
|
-
|
92
|
-
@items = [
|
93
|
-
{ id: 2, name: 'two' },
|
94
|
-
{ id: 3, name: 'three' },
|
95
|
-
{ id: 1, name: 'one' }
|
96
|
-
]
|
97
|
-
@query_tracker.run
|
98
|
-
expect(@live_query.items).to eq(@items)
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'should handle complex transforms' do
|
102
|
-
@items = [
|
103
|
-
{ id: 1, name: 'one' },
|
104
|
-
{ id: 2, name: 'two' },
|
105
|
-
{ id: 3, name: 'three' },
|
106
|
-
{ id: 4, name: 'four' },
|
107
|
-
{ id: 5, name: 'five' }
|
108
|
-
]
|
109
|
-
@query_tracker.run
|
110
|
-
expect(@live_query.items).to eq(@items)
|
111
|
-
|
112
|
-
@items = [
|
113
|
-
{ id: 7, name: 'seven' },
|
114
|
-
{ id: 4, name: 'four' },
|
115
|
-
{ id: 1, name: 'one' },
|
116
|
-
{ id: 5, name: 'five' },
|
117
|
-
{ id: 3, name: 'three' },
|
118
|
-
{ id: 6, name: 'five' }
|
119
|
-
]
|
120
|
-
@query_tracker.run
|
121
|
-
expect(@live_query.items).to eq(@items)
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'should notify data hash has changed' do
|
125
|
-
@items = [
|
126
|
-
{ id: 1, name: 'one' },
|
127
|
-
{ id: 2, name: 'two' },
|
128
|
-
{ id: 3, name: 'three' },
|
129
|
-
{ id: 4, name: 'four' },
|
130
|
-
{ id: 5, name: 'five' }
|
131
|
-
]
|
132
|
-
@query_tracker.run
|
133
|
-
@items = [
|
134
|
-
{ id: 1, name: 'some' },
|
135
|
-
{ id: 2, name: 'values' },
|
136
|
-
{ id: 3, name: 'have' },
|
137
|
-
{ id: 4, name: 'changed' },
|
138
|
-
{ id: 5, name: 'other' }
|
139
|
-
]
|
140
|
-
expect(@live_query.items).to_not eq(@items)
|
141
|
-
@query_tracker.run
|
142
|
-
expect(@live_query.items).to eq(@items)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|