volt 0.8.4 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -1
- data/Readme.md +200 -47
- data/VERSION +1 -1
- data/app/volt/tasks/live_query/data_store.rb +5 -2
- data/app/volt/tasks/store_tasks.rb +4 -6
- data/lib/volt/models/model_helpers.rb +7 -8
- data/lib/volt/models/persistors/local_store.rb +1 -1
- data/lib/volt/page/page.rb +2 -2
- data/lib/volt/tasks/dispatcher.rb +1 -1
- data/spec/models/model_spec.rb +22 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c7f9c10d1c4c9b36bbf686d224d63b7efac606d
|
4
|
+
data.tar.gz: 3d5734b9bf49bd4bc385442fcafe8fa52a083d6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea67b035043177a2f63d14906b25a9b71e12f6bb2737b471c749947971bc170680d83d61df1a20c7a9b13a009d1bb43c3e5610a71374d79a763c7af7158431a1
|
7
|
+
data.tar.gz: 9aed66c68f300dc644f38ff84802152f3e2c4cd37780306c2a142247b6d6d71d70a89c49b307117e07b04e89db05165d1f1c86ed7472f28218d80a0078f76608
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
# 0.
|
1
|
+
# 0.8.4 - Oct 4, 2014
|
2
|
+
|
3
|
+
- Added configuration for databases.
|
4
|
+
|
5
|
+
# 0.8.0 - Oct 3, 2014
|
2
6
|
|
3
7
|
- Major change: After a bunch of research and effort, we have decided to change the way the reactive core works. Previously, all objects that maybe changed would be wrapped in a ReactiveValue object that could be updated using ```.cur=``` and accessed using ```.cur``` This had many advantages, but resulted in very complex framework code. It also had a few problems, mainly that reactive value's (sometimes) needed to be unwrapped when passed to code that wasn't aware of reactivity. Our goal is transparent reactivity. Taking infuence from meteor.js, we have switched to a simpler reactive model. See the Readme for details of the new reactive system. The new system has a few advantages. Mainly, you can for the most part write code that is reactive and it will just work.
|
4
8
|
- Radio button support has been added, see README.md
|
data/Readme.md
CHANGED
@@ -72,19 +72,28 @@ You can access the Volt console with:
|
|
72
72
|
1. [Getting Help](#getting-help)
|
73
73
|
2. [Rendering](#rendering)
|
74
74
|
1. [States and Computations](#state-and-computations)
|
75
|
-
|
75
|
+
1. [Computations](#computations)
|
76
|
+
2. [Dependencies](#dependencies)
|
76
77
|
3. [Views](#views)
|
77
78
|
1. [Bindings](#bindings)
|
78
79
|
1. [Content Binding](#content-binding)
|
79
80
|
2. [If Binding](#if-binding)
|
80
81
|
3. [Each Binding](#each-binding)
|
81
82
|
4. [Attribute Bindings](#attribute-bindings)
|
82
|
-
|
83
|
+
2. [Escaping](#escaping)
|
83
84
|
4. [Models](#models)
|
84
|
-
1. [
|
85
|
-
2. [
|
86
|
-
3. [
|
85
|
+
1. [Nil Models](#nil-models)
|
86
|
+
2. [Provided Collections](#provided-collections)
|
87
|
+
3. [Store Collection](#store-collection)
|
88
|
+
4. [Sub Collections](#sub-collections)
|
89
|
+
5. [Model Classes](#model-classes)
|
90
|
+
6. [Buffers](#buffers)
|
91
|
+
7. [Validations](#validations)
|
92
|
+
8. [Model State](#model-state)
|
93
|
+
9. [ArrayModel Events](#arraymodel-events)
|
94
|
+
10. [Automatic Model Conversion](#automatic-model-conversion)
|
87
95
|
5. [Controllers](#controllers)
|
96
|
+
1. [Reactive Accessors](#reactive-accessors)
|
88
97
|
6. [Tasks](#tasks)
|
89
98
|
7. [Components](#components)
|
90
99
|
1. [Dependencies](#dependencies)
|
@@ -97,9 +106,11 @@ You can access the Volt console with:
|
|
97
106
|
9. [Routes](#routes)
|
98
107
|
1. [Routes file](#routes-file)
|
99
108
|
10. [Testing](#testing)
|
100
|
-
11. [
|
109
|
+
11. [Debugging](#debugging)
|
110
|
+
12. [Volt Helpers](#volt-helpers)
|
101
111
|
1. [Logging](#logging)
|
102
112
|
2. [App Configuration](#app-configuration)
|
113
|
+
13. [Contributing](#contributing)
|
103
114
|
|
104
115
|
# Getting Help
|
105
116
|
|
@@ -270,7 +281,7 @@ You can do {index + 1} to correct the zero offset.
|
|
270
281
|
|
271
282
|
When items are removed or added to the array, the #each binding automatically and intelligently adds or removes the items from/to the DOM.
|
272
283
|
|
273
|
-
|
284
|
+
### Attribute Bindings
|
274
285
|
|
275
286
|
Bindings can also be placed inside of attributes.
|
276
287
|
|
@@ -327,17 +338,19 @@ When you need to use { and } outside of bindings, anything in a triple mustache
|
|
327
338
|
|
328
339
|
# Models
|
329
340
|
|
330
|
-
Volt's concept of a model is slightly different from many frameworks where a model is the name for the ORM to the database. In Volt a model is a class where you can store data easily. Models can be created with a "Persistor", which is responsible for storing the data in the model. Models created without a persistor, simply store the data in the classes instance. Lets first see how to use a model.
|
341
|
+
Volt's concept of a model is slightly different from many frameworks where a model is the name for the ORM to the database. In Volt a model is a class where you can store data easily. Models can be created with a "Persistor", which is responsible for storing the data in the model somewhere. Models created without a persistor, simply store the data in the classes instance. Lets first see how to use a model.
|
331
342
|
|
332
|
-
Volt comes with many built-in models; one is called `page`. If you call `#page` on a controller, you will get access to the model.
|
343
|
+
Volt comes with many built-in models; one is called `page`. If you call `#page` on a controller, you will get access to the model.
|
333
344
|
|
334
345
|
```ruby
|
335
346
|
page._name = 'Ryan'
|
336
347
|
page._name
|
337
|
-
# =>
|
348
|
+
# => 'Ryan'
|
338
349
|
```
|
339
350
|
|
340
|
-
Models act like a hash that you can access with getters and setters that start with an
|
351
|
+
Models act like a hash that you can access with getters and setters that start with an underscore. If an attribute is accessed that hasn't yet been assigned, you will get back a "nil model". Prefixing with an underscore makes sure we don't accidentally try to call a method that doesn't exist and get back nil model instead of raising an exception. Fields behave similarly to a hash, but with a different access and assignment syntax.
|
352
|
+
|
353
|
+
# TODO: Add docs on fields in classes
|
341
354
|
|
342
355
|
Models also let you nest data without creating the intermediate models:
|
343
356
|
|
@@ -350,23 +363,28 @@ Models also let you nest data without creating the intermediate models:
|
|
350
363
|
# => @#<Model:_settings {:_color=>"blue"}>
|
351
364
|
```
|
352
365
|
|
353
|
-
Nested data is automatically setup when assigned. In this case, page._settings is a model that is part of the page model.
|
366
|
+
Nested data is automatically setup when assigned. In this case, page._settings is a model that is part of the page model. This allows nested models to be bound to a binding without the need to setup the model before use.
|
354
367
|
|
355
|
-
|
368
|
+
In Volt models, plural properties return an ArrayModel instance. ArrayModels behave the same way as normal arrays. You can add/remove items to the array with normal array methods (#<<, push, append, delete, delete_at, etc...)
|
356
369
|
|
357
370
|
```ruby
|
358
|
-
page._items << 'item 1'
|
359
371
|
page._items
|
360
|
-
#
|
372
|
+
# #<ArrayModel:70303686333720 []>
|
373
|
+
|
374
|
+
page._items << {_name: 'Item 1'}
|
375
|
+
|
376
|
+
page._items
|
377
|
+
# #<ArrayModel:70303686333720 [<Model:70303682055800 {:_name=>"Item 1"}>]>
|
378
|
+
|
379
|
+
page._items.size
|
380
|
+
# => 1
|
361
381
|
|
362
382
|
page._items[0]
|
363
|
-
# =>
|
383
|
+
# => <Model:70303682055800 {:_name=>"Item 1"}>
|
364
384
|
```
|
365
385
|
|
366
|
-
ArrayModels can be appended to and accessed just like regular arrays.
|
367
|
-
|
368
386
|
|
369
|
-
|
387
|
+
## Nil Models
|
370
388
|
|
371
389
|
As a convience, calling something like ```page._info``` returns what's called a NilModel (assuming it isn't already initialized). NilModels are place holders for future possible Models. NilModels allow us to bind deeply nested values without initializing any intermediate values.
|
372
390
|
|
@@ -417,6 +435,160 @@ Above, I mentioned that Volt comes with many default collection models accessibl
|
|
417
435
|
|
418
436
|
**more storage locations are planned**
|
419
437
|
|
438
|
+
## Store Collection
|
439
|
+
|
440
|
+
The store collection backs data in the data store. Currently the only supported data store is Mongo. (More coming soon, RethinkDb will probably be next) You can use store very similar to the other collections.
|
441
|
+
|
442
|
+
In Volt you can access ```store``` on the front-end and the back-end. Data will automatically be synced between the front-end and the backend. Any changes to the data in store will be reflected on any clients using the data (unless a [buffer](#buffer) is in use - see below).
|
443
|
+
|
444
|
+
```ruby
|
445
|
+
store._items << {_name: 'Item 1'}
|
446
|
+
|
447
|
+
store._items[0]
|
448
|
+
# => <Model:70303681865560 {:_name=>"Item 1", :_id=>"e6029396916ed3a4fde84605"}>
|
449
|
+
```
|
450
|
+
|
451
|
+
Inserting into ```store._items``` will create a ```_items``` table and insert the model into it. An pseudo-unique _id will be automatically generated.
|
452
|
+
|
453
|
+
Currently one difference between ```store``` and other collections is ```store``` does not store properties directly. Only ArrayModels are allowed directly on ```store```
|
454
|
+
|
455
|
+
```ruby
|
456
|
+
store._something = 'yes'
|
457
|
+
# => won't be saved at the moment
|
458
|
+
```
|
459
|
+
|
460
|
+
Note: We're planning to add support for direct ```store``` properties.
|
461
|
+
|
462
|
+
## Sub Collections
|
463
|
+
|
464
|
+
Models can be nested on ```store```
|
465
|
+
|
466
|
+
```ruby
|
467
|
+
store._states << {_name: 'Montana'}
|
468
|
+
montana = store._states[0]
|
469
|
+
|
470
|
+
montana._cities << {_name: 'Bozeman'}
|
471
|
+
montana._cities << {_name: 'Helena'}
|
472
|
+
|
473
|
+
store._states << {_name: 'Idaho'}
|
474
|
+
idaho = store._states[1]
|
475
|
+
|
476
|
+
idaho._cities << {_name: 'Boise'}
|
477
|
+
idaho._cities << {_name: 'Twin Falls'}
|
478
|
+
|
479
|
+
store._states
|
480
|
+
# #<ArrayModel:70129010999880 [<Model:70129010999460 {:_name=>"Montana", :_id=>"e3aa44651ff2e705b8f8319e"}>, <Model:70128997554160 {:_name=>"Montana", :_id=>"9aaf6d2519d654878c6e60c9"}>, <Model:70128997073860 {:_name=>"Idaho", :_id=>"5238883482985760e4cb2341"}>, <Model:70128997554160 {:_name=>"Montana", :_id=>"9aaf6d2519d654878c6e60c9"}>, <Model:70128997073860 {:_name=>"Idaho", :_id=>"5238883482985760e4cb2341"}>]>
|
481
|
+
```
|
482
|
+
|
483
|
+
You can also create a Model first and then insert it.
|
484
|
+
|
485
|
+
```ruby
|
486
|
+
montana = Model.new({_name: 'Montana'})
|
487
|
+
|
488
|
+
montana._cities << {_name: 'Bozeman'}
|
489
|
+
montana._cities << {_name: 'Helena'}
|
490
|
+
|
491
|
+
store._states << montana
|
492
|
+
```
|
493
|
+
|
494
|
+
## Model Classes
|
495
|
+
|
496
|
+
By default all collections use the Model class by default.
|
497
|
+
|
498
|
+
```ruby
|
499
|
+
page._info.class
|
500
|
+
# => Model
|
501
|
+
```
|
502
|
+
|
503
|
+
You can provide classes that will be loaded in place of the standard model class. You can place these in any app/{component}/models folder. For example, you could add ```app/main/info.rb``` Model classes should inherit from ```Model```
|
504
|
+
|
505
|
+
```ruby
|
506
|
+
class Info < Model
|
507
|
+
end
|
508
|
+
```
|
509
|
+
|
510
|
+
Now when you access any sub-collection called ```_info```, it will load as an instance of ```Info```
|
511
|
+
|
512
|
+
```ruby
|
513
|
+
page._info.class
|
514
|
+
# => Info
|
515
|
+
```
|
516
|
+
|
517
|
+
This lets you set custom methods and validations within collections.
|
518
|
+
|
519
|
+
## Buffers
|
520
|
+
|
521
|
+
Because the store collection is automatically synced to the backend, any change to a model's property will result in all other clients seeing the change immediately. Often this is not the desired behavior. To facilitate building [CRUD](http://en.wikipedia.org/wiki/Create,_read,_update_and_delete) apps, Volt provides the concept of a "buffer". A buffer can be created from one model and will not save data back to its backing model until .save! is called on it. This lets you create a form thats not saved until a submit button is pressed.
|
522
|
+
|
523
|
+
```ruby
|
524
|
+
store._items << {_name: 'Item 1'}
|
525
|
+
|
526
|
+
item1 = store._items[0]
|
527
|
+
|
528
|
+
item1_buffer = item1.buffer
|
529
|
+
|
530
|
+
item1_buffer._name = 'Updated Item 1'
|
531
|
+
item1_buffer._name
|
532
|
+
# => 'Updated Item 1'
|
533
|
+
|
534
|
+
item1._name
|
535
|
+
# => 'Item 1'
|
536
|
+
|
537
|
+
item1_buffer.save!
|
538
|
+
|
539
|
+
item1_buffer._name
|
540
|
+
# => 'Updated Item 1'
|
541
|
+
|
542
|
+
item1._name
|
543
|
+
# => 'Updated Item 1'
|
544
|
+
```
|
545
|
+
|
546
|
+
```#save!``` on buffer also returns a [promise](http://opalrb.org/blog/2014/05/07/promises-in-opal/) that will resolve when the data has been saved back to the server.
|
547
|
+
|
548
|
+
```ruby
|
549
|
+
item1_buffer.save!.then do
|
550
|
+
puts "Item 1 saved"
|
551
|
+
end.fail do |err|
|
552
|
+
puts "Unable to save because #{err}"
|
553
|
+
end
|
554
|
+
```
|
555
|
+
|
556
|
+
Calling .buffer on an existing model will return a buffer for that model instance. If you call .buffer on an ArrayModel (plural sub-collection), you will get a buffer for a new item in that collection. Calling .save! will then add the item to that sub-collection as if you had done << to push the item into the collection.
|
557
|
+
|
558
|
+
## Validations
|
559
|
+
|
560
|
+
Within a model class, you can setup validations. Validations let you restrict the types of data that can be stored in a model. Validations are mostly useful for the ```store``` collection, though they can be used elsewhere.
|
561
|
+
|
562
|
+
At the moment we only have two validations implemented (length and presence). Though a lot more will be coming.
|
563
|
+
|
564
|
+
```ruby
|
565
|
+
class Info < Model
|
566
|
+
validate :_name, length: 5
|
567
|
+
validate :_state, presence: true
|
568
|
+
end
|
569
|
+
```
|
570
|
+
|
571
|
+
When calling save on a model with validations, the following occurs:
|
572
|
+
|
573
|
+
1. Client side validations are run; if they fail, the promise from ```save!``` is rejected with the error object.
|
574
|
+
2. The data is sent to the server and client and server side validations are run on the server; any failures are returned and the promise is rejected on the front-end (with the error object)
|
575
|
+
- re-running the validations on the server side makes sure that no data can be saved that doesn't pass the validations
|
576
|
+
3. If all validations pass, the data is saved to the database and the promise resolved on the client.
|
577
|
+
4. The data is synced to all other clients.
|
578
|
+
|
579
|
+
|
580
|
+
## Model State
|
581
|
+
|
582
|
+
**Work in progress**
|
583
|
+
|
584
|
+
| state | events bound | description |
|
585
|
+
|-------------|--------------|--------------------------------------------------------------|
|
586
|
+
| not_loaded | no | no events and no one has accessed the data in the model |
|
587
|
+
| loading | maybe | someone either accessed the data or bound an event |
|
588
|
+
| loaded | yes | data is loaded and there is an event bound |
|
589
|
+
| dirty | no | data was either accessed without binding an event, or an event was bound, but later unbound. |
|
590
|
+
|
591
|
+
|
420
592
|
## ArrayModel Events
|
421
593
|
|
422
594
|
Models trigger events when their data is updated. Currently, models emit two events: added and removed. For example:
|
@@ -781,16 +953,7 @@ If ```params._view``` were 'todos' and ```params._index``` were not nil, the rou
|
|
781
953
|
|
782
954
|
Routes are matched top to bottom in a routes file.
|
783
955
|
|
784
|
-
|
785
|
-
|
786
|
-
An in browser irb is in the works. We also have source maps support, but they are currently disabled by default. To enable them run:
|
787
|
-
|
788
|
-
MAPS=true volt s
|
789
|
-
|
790
|
-
This feature is disabled by default because (due to the volume of pages rendered) it slows down page rendering. We're working with the opal and sprockets teams to make it so everything is still served in one big source maps file (which would show the files as they originated on disk)
|
791
|
-
|
792
|
-
|
793
|
-
## Channel
|
956
|
+
# Channel
|
794
957
|
|
795
958
|
Controllers provide a `#channel` method, that you can use to get the status of the connection to the backend. Channel is provided in a ReactiveValue, and when the status changes, the changed events are triggered. It provides the following:
|
796
959
|
|
@@ -822,6 +985,14 @@ To run Capybara tests, you need to specify a driver. The following drivers are
|
|
822
985
|
|
823
986
|
Chrome is not supported due to [this issue](https://code.google.com/p/chromedriver/issues/detail?id=887#makechanges) with ChromeDriver. Feel free to go [here](https://code.google.com/p/chromedriver/issues/detail?id=887#makechanges) and pester the chromedriver team to fix it.
|
824
987
|
|
988
|
+
# Debugging
|
989
|
+
|
990
|
+
An in browser irb is in the works. We also have source maps support, but they are currently disabled by default. To enable them run:
|
991
|
+
|
992
|
+
MAPS=true volt s
|
993
|
+
|
994
|
+
This feature is disabled by default because (due to the volume of pages rendered) it slows down page rendering. We're working with the opal and sprockets teams to make it so everything is still served in one big source maps file (which would show the files as they originated on disk)
|
995
|
+
|
825
996
|
# Volt Helpers
|
826
997
|
|
827
998
|
## Logging
|
@@ -859,24 +1030,6 @@ Volt does its best to start with useful defaults. You can configure things like
|
|
859
1030
|
|
860
1031
|
TODO
|
861
1032
|
|
862
|
-
|
863
|
-
# Data Store
|
864
|
-
|
865
|
-
Volt provides a data store collection on the front-end and the back-end. In store, all plural names are assumed to be collections (like an array), and all singular are assumed to be a model (like a hash).
|
866
|
-
|
867
|
-
```ruby
|
868
|
-
store._things
|
869
|
-
```
|
870
|
-
|
871
|
-
**Work in progress**
|
872
|
-
|
873
|
-
| state | events bound | description |
|
874
|
-
|-------------|--------------|--------------------------------------------------------------|
|
875
|
-
| not_loaded | no | no events and no one has accessed the data in the model |
|
876
|
-
| loading | maybe | someone either accessed the data or bound an event |
|
877
|
-
| loaded | yes | data is loaded and there is an event bound |
|
878
|
-
| dirty | no | data was either accessed without binding an event, or an event was bound, but later unbound. |
|
879
|
-
|
880
1033
|
# Contributing
|
881
1034
|
|
882
1035
|
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/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.5
|
@@ -2,7 +2,10 @@ require 'mongo'
|
|
2
2
|
|
3
3
|
class DataStore
|
4
4
|
def initialize
|
5
|
-
|
5
|
+
end
|
6
|
+
|
7
|
+
def db
|
8
|
+
@@db ||= Volt::DataStore.fetch
|
6
9
|
end
|
7
10
|
|
8
11
|
def query(collection, query)
|
@@ -13,6 +16,6 @@ class DataStore
|
|
13
16
|
end
|
14
17
|
end
|
15
18
|
|
16
|
-
|
19
|
+
db[collection].find(query).to_a
|
17
20
|
end
|
18
21
|
end
|
@@ -3,14 +3,12 @@ require 'query_tasks'
|
|
3
3
|
|
4
4
|
class StoreTasks
|
5
5
|
def initialize(channel=nil, dispatcher=nil)
|
6
|
-
@@db = Volt::DataStore.fetch
|
7
|
-
|
8
6
|
@channel = channel
|
9
7
|
@dispatcher = dispatcher
|
10
8
|
end
|
11
9
|
|
12
10
|
def db
|
13
|
-
@@db
|
11
|
+
@@db ||= Volt::DataStore.fetch
|
14
12
|
end
|
15
13
|
|
16
14
|
def model_errors(collection, data)
|
@@ -43,14 +41,14 @@ class StoreTasks
|
|
43
41
|
# TODO: Seems mongo is dumb and doesn't let you upsert with custom id's
|
44
42
|
begin
|
45
43
|
# data['_id'] = BSON::ObjectId('_id') if data['_id']
|
46
|
-
|
44
|
+
db[collection].insert(data)
|
47
45
|
rescue Mongo::OperationFailure => error
|
48
46
|
# Really mongo client?
|
49
47
|
if error.message[/^11000[:]/]
|
50
48
|
# Update because the id already exists
|
51
49
|
update_data = data.dup
|
52
50
|
update_data.delete(:_id)
|
53
|
-
|
51
|
+
db[collection].update({:_id => id}, update_data)
|
54
52
|
else
|
55
53
|
return {:error => error.message}
|
56
54
|
end
|
@@ -64,7 +62,7 @@ class StoreTasks
|
|
64
62
|
end
|
65
63
|
|
66
64
|
def delete(collection, id)
|
67
|
-
|
65
|
+
db[collection].remove('_id' => id)
|
68
66
|
|
69
67
|
QueryTasks.live_query_pool.updated_collection(collection, @channel)
|
70
68
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# A place for things shared between an ArrayModel and a Model
|
2
|
-
|
3
2
|
module ModelHelpers
|
4
3
|
def deep_unwrap(value)
|
5
4
|
if value.is_a?(Model)
|
@@ -23,16 +22,16 @@ module ModelHelpers
|
|
23
22
|
|
24
23
|
# Gets the class for a model at the specified path.
|
25
24
|
def class_at_path(path)
|
26
|
-
if path
|
25
|
+
if path
|
27
26
|
begin
|
28
|
-
# TODO: SECURITY on the back-end we need to check that the model class we're loading
|
29
|
-
# is coming from the models folder.
|
30
|
-
|
31
27
|
# remove the _ and then singularize
|
32
|
-
|
28
|
+
if path.last == :[]
|
29
|
+
klass_name = path[-2][1..-1].singularize.camelize
|
30
|
+
else
|
31
|
+
klass_name = path[-1][1..-1].singularize.camelize
|
32
|
+
end
|
33
33
|
|
34
|
-
|
35
|
-
klass = Object.send(:const_get, klass_name.to_sym)
|
34
|
+
klass = $page.model_classes[klass_name] || Model
|
36
35
|
rescue NameError => e
|
37
36
|
# Ignore exception, just means the model isn't defined
|
38
37
|
klass = Model
|
data/lib/volt/page/page.rb
CHANGED
@@ -31,7 +31,7 @@ require 'volt/page/tasks'
|
|
31
31
|
|
32
32
|
|
33
33
|
class Page
|
34
|
-
attr_reader :url, :params, :page, :templates, :routes, :events
|
34
|
+
attr_reader :url, :params, :page, :templates, :routes, :events, :model_classes
|
35
35
|
|
36
36
|
def initialize
|
37
37
|
@model_classes = {}
|
@@ -138,7 +138,7 @@ class Page
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def add_model(model_name)
|
141
|
-
@model_classes[
|
141
|
+
@model_classes[model_name] = Object.const_get(model_name.camelize)
|
142
142
|
end
|
143
143
|
|
144
144
|
def add_template(name, template, bindings)
|
data/spec/models/model_spec.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
1
2
|
require 'volt/models'
|
2
|
-
require 'volt/reactive/dependency'
|
3
|
-
require 'volt/reactive/computation'
|
4
3
|
|
5
4
|
|
6
5
|
class TestItem < Model
|
6
|
+
end
|
7
7
|
|
8
|
+
class Item < Model
|
8
9
|
end
|
9
10
|
|
11
|
+
|
10
12
|
describe Model do
|
11
13
|
|
12
14
|
it "should allow _ methods to be used to store values without predefining them" do
|
@@ -413,4 +415,22 @@ describe Model do
|
|
413
415
|
@model = Model.new(nil, persistor: persistor)
|
414
416
|
end
|
415
417
|
end
|
418
|
+
|
419
|
+
if RUBY_PLATFORM != 'opal'
|
420
|
+
describe "class loading" do
|
421
|
+
it 'should load classes for models' do
|
422
|
+
$page = Page.new
|
423
|
+
$page.add_model('Item')
|
424
|
+
|
425
|
+
@model = Model.new
|
426
|
+
|
427
|
+
# Should return a buffer of the right type
|
428
|
+
expect(@model._items.buffer.class).to eq(Item)
|
429
|
+
|
430
|
+
# Should insert as the right type
|
431
|
+
@model._items << {_name: 'Item 1'}
|
432
|
+
expect(@model._items[0].class).to eq(Item)
|
433
|
+
end
|
434
|
+
end
|
435
|
+
end
|
416
436
|
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.8.
|
4
|
+
version: 0.8.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Stout
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|