volt 0.7.18 → 0.7.19

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d287b57490af57c686f9f3b8a45dda2d953a8a19
4
- data.tar.gz: 97a0201eda5adc10704ea7c689e27d596fff315b
3
+ metadata.gz: e52814d6fe0018d0ed9ff87c726b083c0d97c6d6
4
+ data.tar.gz: e45c97fe12819f7ab1abe17d9d0166379fa61a30
5
5
  SHA512:
6
- metadata.gz: 3d0c17a7964f2f2b3a1d63cb299bed4f3160f40ac595425b04788fffe88d3b7a67fc83fd418d45b53c27b449c6ba55d6a0ba5dbd058368c0ec6b0c7255baf607
7
- data.tar.gz: 6d6c453d1192cba6e277326f368d885973b5ee603d1303001a2b3b8cded4c6f82014a5006a7ed1d1b44c41ceac4dd582ec966fcf099e7548605ca91da938421c
6
+ metadata.gz: fccff09f4fe9c5ddeaf5d41a8e8fe4e284c9f1af137a11578ba08f6eafc336a6b13e27c4b3bf54665e6d6933c6c3e4f328db1b574e514a49764d188a223a64d7
7
+ data.tar.gz: ee4387876d87956bb39127f2fad009f42fc7c1078e50b409a1fa3f4c88a2e91c1ebf4b267b56acdaa711faceff03e6f8d402ceb3beeb56462247f63bbf8a1c6e
data/Readme.md CHANGED
@@ -1,26 +1,27 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/volt.png)](http://badge.fury.io/rb/volt)
2
2
  [![Code Climate](https://codeclimate.com/github/voltrb/volt.png)](https://codeclimate.com/github/voltrb/volt)
3
3
  [![Build Status](https://travis-ci.org/voltrb/volt.png?branch=master)](https://travis-ci.org/voltrb/volt)
4
+ [![Volt Chat](https://badges.gitter.im/voltrb/volt.png)](https://gitter.im/voltrb/volt)
5
+ [![Pledgie](https://pledgie.com/campaigns/26731.png?skin_name=chrome)](https://pledgie.com/campaigns/26731)
4
6
 
5
- ---
6
- > NOTE: VOLT IS STILL IN DEVELOPMENT, DON'T USE IT FOR ANYTHING SERIOUS YET
7
- ---
7
+ =======
8
+ ** For the current status of volt, read: http://voltframework.com/blog
8
9
 
9
10
  # Volt
10
11
 
11
- 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 update 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.
12
+ 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 update 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.
12
13
 
13
- Instead of syncing data between the client and server via HTTP, volt uses a persistent connection between the client and server. When data updated on one client, it is updated in the database and any other listening clients. (With almost no setup code needed)
14
+ 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).
14
15
 
15
- Pages HTML is written in a handlebars like template language. Volt uses data flow/reactive programming to automatically and intelligently propagate changes to the DOM (or anything other code wanting to know when a value updates) When something in the DOM changes, Volt intelligently updates only the nodes that need to be changed.
16
+ Pages HTML is written in a handlebars-like template language. Volt uses data flow/reactive programming to automatically and intelligently propagate changes to the DOM (or anything other code wanting to know when a value updates). When something in the DOM changes, Volt intelligently updates only the nodes that need to be changed.
16
17
 
17
18
  See some demo videos here:
18
- - [https://www.youtube.com/watch?v=6ZIvs0oKnYs](https://www.youtube.com/watch?v=6ZIvs0oKnYs)
19
- - [https://www.youtube.com/watch?v=c478sMlhx1o](https://www.youtube.com/watch?v=c478sMlhx1o)
20
- - [https://www.youtube.com/watch?v=yZIQ-2irY-Q](https://www.youtube.com/watch?v=yZIQ-2irY-Q)
19
+ - [Volt Todos Example](https://www.youtube.com/watch?v=6ZIvs0oKnYs)
20
+ - [Build a Blog with Volt](https://www.youtube.com/watch?v=c478sMlhx1o)
21
+ - [Reactive Values in Volt](https://www.youtube.com/watch?v=yZIQ-2irY-Q)
21
22
 
22
23
  Check out demo apps:
23
- - https://github.com/voltrb/todos
24
+ - https://github.com/voltrb/todos3
24
25
  - https://github.com/voltrb/blog
25
26
  - https://github.com/voltrb/contactsdemo
26
27
 
@@ -30,10 +31,10 @@ Check out demo apps:
30
31
  Volt has the following goals:
31
32
 
32
33
  1. Developer happiness
33
- 2. Write once on the client and the server
34
+ 2. Write once on the client and server
34
35
  3. Automatic data syncing between client and server
35
36
  4. Apps are built as nested components. Components can be shared (via gems)
36
- 5. Concurrent. Volt provides tools to simplify concurrency. Component rendering is done in parallel on the server.
37
+ 5. Concurrent. Volt provides tools to simplify concurrency. Component rendering is done in parallel on the server
37
38
  6. Intelligent asset management
38
39
  7. Secure (shouldn't need to be said, but it does)
39
40
  8. Be fast/light
@@ -44,18 +45,16 @@ Volt has the following goals:
44
45
 
45
46
  Many of the core Volt features are implemented. We still have a bit to go before 1.0, most of it involving models.
46
47
 
47
- 1. Database storing models
48
- 2. Model validations (client and server side)
49
- 3. Reactive model queries
50
- 4. Reactive Enumerators with Blocks (.map .count, etc...)
51
- 5. Full managed render loop (for fast rendering)
52
- 6. Fix N+1 issue with some reactive values (I know how to fix, just haven't gotten around to doing it)
48
+ 1. Reactive model queries
49
+ 2. Reactive Enumerators with Blocks (.map .count, etc…)
50
+ 3. Full managed render loop (for fast rendering)
51
+ 4. Fix N+1 issue with some reactive values (I know how to fix it, just haven't gotten around to doing it)
53
52
 
54
53
  # VOLT guide
55
54
 
56
- This guide will take you through creating a basic web application in Volt. This tutorial assumes a basic knowledge of ruby and web development.
55
+ This guide will take you through creating a basic web application in Volt. This tutorial assumes a basic knowledge of Ruby and web development.
57
56
 
58
- To get started, install volt:
57
+ To get started, install Volt:
59
58
 
60
59
  gem install volt
61
60
 
@@ -63,11 +62,11 @@ Then create a new project:
63
62
 
64
63
  volt new project_name
65
64
 
66
- This will setup a basic project. Now lets run the server.
65
+ This will setup a basic project. Now let's run the server:
67
66
 
68
67
  volt server
69
68
 
70
- You can access the volt console with:
69
+ You can access the Volt console with:
71
70
 
72
71
  volt console
73
72
 
@@ -90,15 +89,16 @@ You can access the volt console with:
90
89
  3. [Model Events](#model-events)
91
90
  4. [Automatic Model Conversion](#automatic-model-conversion)
92
91
  5. [Controllers](#controllers)
93
- 6. [Components](#components)
92
+ 6. [Tasks](#tasks)
93
+ 7. [Components](#components)
94
94
  1. [Dependencies](#dependencies)
95
95
  2. [Assets](#assets)
96
96
  3. [Component Generator](#component-generator)
97
97
  4. [Provided Components](#provided-components)
98
98
  1. [Notices](#notices)
99
99
  2. [Flash](#flash)
100
- 7. [Controls](#controls)
101
- 8. [Routes](#routes)
100
+ 8. [Controls](#controls)
101
+ 9. [Routes](#routes)
102
102
  1. [Routes file](#routes-file)
103
103
 
104
104
 
@@ -106,10 +106,10 @@ You can access the volt console with:
106
106
 
107
107
  Volt is still a work in progress, but early feedback is appreciated. Use the following to communicate with the developers, someone will get back to you very quickly:
108
108
 
109
- - **If you need help**: post on [stackoverflow.com](http://www.stackoverflow.com), be sure to tag your question with voltrb
109
+ - **If you need help**: post on [stackoverflow.com](http://www.stackoverflow.com). Be sure to tag your question with `voltrb`.
110
110
  - **If you found a bug**: post on [github issues](https://github.com/voltrb/volt/issues)
111
111
  - **If you have an idea or need a feature**: post on [github issues](https://github.com/voltrb/volt/issues)
112
- - **If you want to discuss volt**: use #voltrb on freenode.
112
+ - **If you want to discuss Volt**: use #voltrb on freenode.
113
113
 
114
114
 
115
115
  # Rendering
@@ -123,7 +123,7 @@ For example when a user clicks to add a new todo item to a todo list, we might c
123
123
 
124
124
  The idea of "reactive programming" has been used to simplify maintaining the DOM. The idea is instead of having event handlers that manage a model (or JavaScript object) and manage the DOM, we have event handlers that manage reactive data models. We describe our DOM layer in a declarative way so that it automatically knows how to render our data models.
125
125
 
126
- ## Reactive Value's
126
+ ## Reactive Values
127
127
 
128
128
  To build bindings, Volt provides the ReactiveValue class. This wraps any object in a reactive interface. To create a ReactiveValue, simply pass the object you want to wrap as the first argument to new.
129
129
 
@@ -132,9 +132,9 @@ To build bindings, Volt provides the ReactiveValue class. This wraps any object
132
132
  # => @"my object"
133
133
  ```
134
134
 
135
- When .inspect is called on a ReactiveValue (like in the console), an @ is placed in front of the value's inspect string, so you know its reactive.
135
+ When `#inspect` is called on a ReactiveValue (like in the console), an '@' is placed in front of the value's inspect string, so you know it's reactive.
136
136
 
137
- When you call a method on a ReactiveValue, you get back a new reactive value that depends on the previous one. It remembers how it was created and you can call .cur on it any time to get its current value, which will be computed based off of the first reactive value. (Keep in mind below that + is a method call, the same as a.+(b) in ruby.)
137
+ When you call a method on a ReactiveValue, you get back a new reactive value that depends on the previous one. It remembers how it was created and you can call `#cur` on it any time to get its current value, which will be computed based off of the first reactive value. (Keep in mind below that + is a method call, the same as `a.+(b)` in ruby.)
138
138
 
139
139
  ```ruby
140
140
  a = ReactiveValue.new(1)
@@ -156,9 +156,9 @@ When you call a method on a ReactiveValue, you get back a new reactive value tha
156
156
  # => 7
157
157
  ```
158
158
 
159
- This provides the backbone for reactive programming. We setup computation/flow graphs instead of doing an actual calculation. Calling .cur (or .inspect, .to_s, etc..) runs the computation and returns the current value at that time, based on all of its dependencies.
159
+ This provides the backbone for reactive programming. We setup computation/flow graphs instead of doing an actual calculation. Calling `#cur` (or `#inspect`, `#to_s`, etc..) runs the computation and returns the current value at that time, based on all of its dependencies.
160
160
 
161
- ReactiveValue's also let you setup listeners and trigger events:
161
+ ReactiveValues also let you setup listeners and trigger events:
162
162
 
163
163
  ```ruby
164
164
  a = ReactiveValue.new(0)
@@ -167,7 +167,7 @@ ReactiveValue's also let you setup listeners and trigger events:
167
167
  # => A Changed
168
168
  ```
169
169
 
170
- These events propagate to any reactive value's created off of a reactive value.
170
+ These events propagate to any reactive values created off of a reactive value:
171
171
 
172
172
  ```ruby
173
173
  a = ReactiveValue.new(1)
@@ -180,7 +180,7 @@ These events propagate to any reactive value's created off of a reactive value.
180
180
 
181
181
  This event flow lets us know when an object has changed, so we can update everything that depended on that object.
182
182
 
183
- Lastly, we can also pass in other reactive value's as arguments to methods on a reactive value. The dependencies will be tracked for both and events will propagate down from both. (Also, note that doing `.cur =` to update the current value triggers a "changed" event.)
183
+ Lastly, we can also pass in other reactive values as arguments to methods on a reactive value. The dependencies will be tracked for both and events will propagate down from both. (Also, note that calling `#cur=` to update the current value triggers a "changed" event.)
184
184
 
185
185
  ```ruby
186
186
  a = ReactiveValue.new(1)
@@ -200,27 +200,27 @@ Lastly, we can also pass in other reactive value's as arguments to methods on a
200
200
  # => C changed
201
201
  ```
202
202
 
203
- ### ReactiveValue Gotcha's
203
+ ### ReactiveValue Gotchas
204
204
 
205
- There are a few simple things to keep in mind with ReactiveValue's. In order to make them mostly compatible with other ruby objects, a two methods do not return another ReactiveValue.
205
+ There are a few simple things to keep in mind with ReactiveValues. In order to make them mostly compatible with other Ruby objects, two methods do not return another ReactiveValue.
206
206
 
207
207
  to_s and inspect
208
208
 
209
- If you want these to be used reactively, see the section on [with](#with)
209
+ If you want these to be used reactively, see the section on [with](#with).
210
210
 
211
- Also, due to a small limitation in ruby, ReactiveValue's always are truthy. See the [truthy checks](#truthy-checks-true-false-or-and-and) section on how to check for truth.
211
+ Also, due to a small limitation in ruby, ReactiveValues always are truthy. See the [truthy checks](#truthy-checks-true-false-or-and-and) section on how to check for truth.
212
212
 
213
- When passing something that may contain reactive values to a JS function, you can call ```.deep_cur``` on any object to get back a copy that will have all reactive value's turned into their current value.
213
+ When passing something that may contain reactive values to a JS function, you can call ```#deep_cur``` on any object to get back a copy that will have all reactive values turned into their current value.
214
214
 
215
215
  ### Current Status
216
216
 
217
- NOTE: currently ReactiveValue's are not complete. At the moment, they do not handle methods that are passed blocks (or procs, lambda's). This is planned, but not complete. At the moment you can use [with](#with) to accomplish similar things.
217
+ NOTE: currently ReactiveValues are not complete. At the moment, they do not handle methods that are passed blocks (or procs, lambdas). This is planned, but not complete. At the moment you can use [with](#with) to accomplish similar things.
218
218
 
219
219
  ### Truthy Checks: .true?, .false?, .or, and .and
220
220
 
221
221
  Because a method on a reactive value always returns another reactive value, and because only nil and false are false in ruby, we need a way to check if a ReactiveValue is truthy in our code. The easiest way to do this is by calling .true? on it. It will return a non-wrapped boolean. .nil? and .false? do as you would expect.
222
222
 
223
- One common place we use a truthy check is in setting up default values with || (logical or) Volt provides a convience method that does the same thing .or, but works with ReactiveValue's.
223
+ One common place we use a truthy check is in setting up default values with || (logical or) Volt provides a convenient method that does the same thing `#or`, but works with ReactiveValues.
224
224
 
225
225
  Instead of
226
226
 
@@ -234,14 +234,14 @@ Simply use:
234
234
  a.or(b)
235
235
  ```
236
236
 
237
- .and works the same way as &&. #and and #or let you maintain the reactivity all of the way through.
237
+ `#and` works the same way as &&. #and and #or let you maintain the reactivity all of the way through.
238
238
 
239
239
 
240
240
  ### With
241
241
 
242
- Normally when you want to have a value that depends on another value, but transforms it somehow, you simply call your transform method on the ReactiveValue. However sometimes the transform is not directly on the ReactiveValue's object.
242
+ Normally when you want to have a value that depends on another value, but transforms it somehow, you simply call your transform method on the ReactiveValue. However sometimes the transform is not directly on the ReactiveValues object.
243
243
 
244
- You can call .with on any ReactiveValue. .with will return a new ReactiveValue that depends on the current ReactiveValue. .with takes a block, the first argument to the block will be the cur value of the ReactiveValue you called with on. Any additional arguments to with will be passed in after the first one. If you pass another ReactiveValue as an argument to .with, the returned ReactiveValue will depend on the argument ReactiveValue as well, and the block will receive the arguments cur value.
244
+ You can call `#with` on any ReactiveValue. `#with` will return a new ReactiveValue that depends on the current ReactiveValue. `#with` takes a block, the first argument to the block will be the cur value of the ReactiveValue you called `#with` on. Any additional arguments to `#with` will be passed in after the first one. If you pass another ReactiveValue as an argument to `#with`, the returned ReactiveValue will depend on the argument ReactiveValue as well, and the block will receive the arguments cur value.
245
245
 
246
246
  ```ruby
247
247
  a = ReactiveValue.new(5)
@@ -252,7 +252,7 @@ You can call .with on any ReactiveValue. .with will return a new ReactiveValue
252
252
 
253
253
  # Views
254
254
 
255
- Views in Volt are use a templating language similar to handlebars. They can be broken up into sections, a section header looks like the following:
255
+ Views in Volt use a templating language similar to handlebars. They can be broken up into sections. A section header looks like the following:
256
256
 
257
257
  ```html
258
258
  <:Body>
@@ -260,11 +260,11 @@ Views in Volt are use a templating language similar to handlebars. They can be
260
260
 
261
261
  Section headers should start with a capital letter so as not to be confused with [controls](#controls). Section headers do not use closing tags. If section headers are not provided, the Body section is assumed.
262
262
 
263
- Section's help you split up different parts of the same content (title and body usually), but within the same file.
263
+ Sections help you split up different parts of the same content (title and body usually), but within the same file.
264
264
 
265
265
  ## Bindings
266
266
 
267
- One you understand the basics of ReactiveValue's, we can discuss bindings. In Volt, you code your views in a handlebar's like template language. Volt provides several bindings, which handle rendering of something for you. Content bindings are anything inbetween { and }
267
+ Once you understand the basics of ReactiveValues, we can discuss bindings. In Volt, you code your views in a handlebars like template language. Volt provides several bindings, which handle rendering of something for you. Content bindings are anything inbetween { and }.
268
268
 
269
269
  ### Content binding
270
270
 
@@ -274,7 +274,7 @@ The most basic binding is a content binding:
274
274
  <p>{some_method}<p>
275
275
  ```
276
276
 
277
- The content binding runs the ruby code between { and }, then renders the return value. If the returned value is a ReactiveValue, it will update the value updated whenever a 'changed' event is triggered on the reactive value.
277
+ The content binding runs the Ruby code between { and }, then renders the return value. If the returned value is a ReactiveValue, it will update the value updated whenever a 'changed' event is triggered on the reactive value.
278
278
 
279
279
  ### If binding
280
280
 
@@ -288,7 +288,7 @@ An if binding lets you provide basic flow control.
288
288
 
289
289
  Blocks are closed with a {/}
290
290
 
291
- When the #if binding is rendered, it will run the ruby code after #if. If the code is true it will render the code below. Again, if the returned value is reactive, it will update as that value changes.
291
+ When the if binding is rendered, it will run the ruby code after #if. If the code is true it will render the code below. Again, if the returned value is reactive, it will update as that value changes.
292
292
 
293
293
  If bindings can also have #elsif and #else blocks.
294
294
 
@@ -312,7 +312,7 @@ For iteration over objects, the each binding is provided.
312
312
  {/}
313
313
  ```
314
314
 
315
- Above, if _items was an array, the block would be rendered for each item, setting 'item' to the value of the array element.
315
+ Above, if _items were an array, the block would be rendered for each item, setting 'item' to the value of the array element.
316
316
 
317
317
  You can also access the position of the item in the array with the #index method.
318
318
 
@@ -330,7 +330,7 @@ For the array: ['one', 'two', 'three'] this would print:
330
330
 
331
331
  You can do {index + 1} to correct the zero offset.
332
332
 
333
- When items are removed or added to the array, the #each binding automatically and intelligently add or removes the items from/to the DOM.
333
+ When items are removed or added to the array, the #each binding automatically and intelligently adds or removes the items from/to the DOM.
334
334
 
335
335
  ## Attribute Bindings
336
336
 
@@ -340,19 +340,19 @@ Bindings can also be placed inside of attributes.
340
340
  <p class="{#if _is_cool?}cool{/}">Text</p>
341
341
  ```
342
342
 
343
- There are some special features provided to make for elements work as "two way bindings"
343
+ There are some special features provided to make elements work as "two way bindings":
344
344
 
345
345
  ```html
346
346
  <input type="text" value="{_name}" />
347
347
  ```
348
348
 
349
- In the example above, if _name changes, the field will update and if the field is updated, _name will be changed.
349
+ In the example above, if _name changes, the field will update, and if the field is updated, _name will be changed:
350
350
 
351
351
  ```html
352
352
  <input type="checkbox" checked="{_checked}" />
353
353
  ```
354
354
 
355
- If the value of a checked attribute is true, the checkbox will be shown checked. If it is checked/unchecked, the value will be updated to true or false.
355
+ If the value of a checked attribute is true, the checkbox will be shown checked. If it's checked or unchecked, the value will be updated to true or false.
356
356
 
357
357
  -- TODO: select boxes
358
358
 
@@ -360,7 +360,7 @@ If you have a controller at app/home/controller/index_controller.rb, and a view
360
360
 
361
361
  ## Escaping
362
362
 
363
- When you need to use { and } outside of bindings. Anything in a triple mustache will be escaped and not processed as a binding:
363
+ When you need to use { and } outside of bindings, anything in a triple mustache will be escaped and not processed as a binding:
364
364
 
365
365
  ```html
366
366
  {{{ bindings look like: {this} }}}
@@ -370,7 +370,7 @@ When you need to use { and } outside of bindings. Anything in a triple mustache
370
370
 
371
371
  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.
372
372
 
373
- 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. Models provided by Volt are automatically wrapped in a ReactiveValue so update events can be tracked.
373
+ 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. Models provided by Volt are automatically wrapped in a ReactiveValue so update events can be tracked.
374
374
 
375
375
  ```ruby
376
376
  page._name = 'Ryan'
@@ -378,7 +378,7 @@ Volt comes with many built-in models, one is called 'page'. If you call #page o
378
378
  # => @'Ryan'
379
379
  ```
380
380
 
381
- Models act like a hash that you can access with getters and setters that start with an _ If an underscore method is called 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. There is no need to define which fields a model has, they act similar to a hash, but with a different access and assign syntax.
381
+ Models act like a hash that you can access with getters and setters that start with an _ . If an underscore method is called 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. There is no need to define which fields a model has. Fields behave similarly to a hash, but with a different access and assignment syntax.
382
382
 
383
383
  Models also let you nest data without creating the intermediate models:
384
384
 
@@ -393,7 +393,7 @@ Models also let you nest data without creating the intermediate models:
393
393
 
394
394
  Nested data is automatically setup when assigned. In this case, page._settings is a model that is part of the page model.
395
395
 
396
- You can also append to a model if its not defined yet. In Volt models, plural properties are assumed to contain arrays (or more specifically ArrayModels)
396
+ You can also append to a model if it's not defined yet. In Volt models, plural properties are assumed to contain arrays (or more specifically, ArrayModels).
397
397
 
398
398
  ```ruby
399
399
  page._items << 'item 1'
@@ -408,7 +408,7 @@ ArrayModels can be appended to and accessed just like regular arrays.
408
408
 
409
409
  ## Provided Collections
410
410
 
411
- Above I mentioned that Volt comes with many default collection models accessible from a controller. Each stores in a different location.
411
+ Above, I mentioned that Volt comes with many default collection models accessible from a controller. Each stores in a different location.
412
412
 
413
413
  | Name | Storage Location |
414
414
  |-----------|---------------------------------------------------------------------------|
@@ -423,11 +423,11 @@ Above I mentioned that Volt comes with many default collection models accessible
423
423
 
424
424
  ## Reactive Models
425
425
 
426
- Because all models provided by Volt are wrapped in a ReactiveValue, you can register listeners on them and be updated when values change. You can also call methods on their values and get updates when the source's change. Bindings also setup listeners. Models should be the main place you store all data in Volt. While you can use ReactiveValue's manually, most of the time you will want to just use something like the controller model.
426
+ Because all models provided by Volt are wrapped in a ReactiveValue, you can register listeners on them and be updated when values change. You can also call methods on their values and get updates when the sources change. Bindings also setup listeners. Models should be the main place you store all data in Volt. While you can use ReactiveValues manually, most of the time you will want to just use something like the controller model.
427
427
 
428
428
  ## Model Events
429
429
 
430
- Models trigger events when their data is updated. Currently models emit three events: changed, added, and removed. For example:
430
+ Models trigger events when their data is updated. Currently, models emit three events: changed, added, and removed. For example:
431
431
 
432
432
  ```ruby
433
433
  model = Model.new
@@ -467,9 +467,9 @@ For convenience, when placing a hash inside of another model, it is automaticall
467
467
  # => Model
468
468
  ```
469
469
 
470
- Models are accessed differently from hashes. Instead of using model[:symbol] to access, you call a method model.method_name. This provides a dynamic unified store where setters and getters can be added without changing any access code.
470
+ Models are accessed differently from hashes. Instead of using `model[:symbol]` to access, you call a method `model.method_name`. This provides a dynamic unified store where setters and getters can be added without changing any access code.
471
471
 
472
- You can get a ruby hash back out by calling .to_h on a Model.
472
+ You can get a Ruby hash back out by calling `#to_h` on a Model.
473
473
 
474
474
  ### Array -> ArrayModel
475
475
 
@@ -487,7 +487,7 @@ Arrays inside of models are automatically converted to an instance of ArrayModel
487
487
  ```
488
488
 
489
489
 
490
- To convert a Model or an ArrayModel back to a normal hash, call .to_h or .to_a respectively. To convert them to a JavaScript Object (for passing to some JavaScript code), call .to_n (to native).
490
+ To convert a Model or an ArrayModel back to a normal hash, call .to_h or .to_a respectively. To convert them to a JavaScript Object (for passing to some JavaScript code), call `#to_n` (to native).
491
491
 
492
492
  ```ruby
493
493
  user = Model.new
@@ -520,7 +520,7 @@ A controller can be any class in Volt, however it is common to have that class i
520
520
  end
521
521
  ```
522
522
 
523
- 2. Calling self.method = in a method:
523
+ 2. Calling `self.model=` in a method:
524
524
 
525
525
  ```ruby
526
526
  class TodosController < ModelController
@@ -530,15 +530,15 @@ A controller can be any class in Volt, however it is common to have that class i
530
530
  end
531
531
  ```
532
532
 
533
- In methods, the #model method returns the current model.
533
+ In methods, the `#model` method returns the current model.
534
534
 
535
535
  See the [provided collections](#provided-collections) section for a list of the available collection models.
536
536
 
537
537
  You can also provide your own object to model.
538
538
 
539
- In the example above any methods not defined on the TodosController will fall through to the provided model. All views in views/{controller_name} will have this controller as the target for any ruby run in their bindings. This means that calls on self (implicit or with self.) will have the model as their target (after calling through the controller). This lets you add methods to the controller to control how the model is handled, or provide extra methods to the views.
539
+ In the example above, any methods not defined on the TodosController will fall through to the provided model. All views in views/{controller_name} will have this controller as the target for any Ruby run in their bindings. This means that calls on self (implicit or with self.) will have the model as their target (after calling through the controller). This lets you add methods to the controller to control how the model is handled, or provide extra methods to the views.
540
540
 
541
- Volt is more similar to an MVVM architecture than an MVC architecture. Instead of the controllers passing data off to the views, the controllers are the context for the views. When using a ModelController, the controller automatically forwards all methods it does not handle to the model. This is convienant since you can set a model in the controller and then access its properties directly with methods in bindings. This lets you do something like ```{_name}``` instead of something like ```{@model._name}```
541
+ Volt is more similar to an MVVM architecture than an MVC architecture. Instead of the controllers passing data off to the views, the controllers are the context for the views. When using a ModelController, the controller automatically forwards all methods it does not handle to the model. This is convenient since you can set a model in the controller and then access its properties directly with methods in bindings. This lets you do something like ```{_name}``` instead of something like ```{@model._name}```
542
542
 
543
543
  Controllers in the app/home component do not need to be namespaced, all other components should namespace controllers like so:
544
544
 
@@ -554,7 +554,7 @@ Here "auth" would be the component name.
554
554
 
555
555
  ## Reactive Accessors
556
556
 
557
- The default ModelController proxies any missing methods to its model. Since models are wrapped in ReactiveValue's, they return ReactiveValue's by default. Sometimes you need to store additional data reactively in the controller outside of the model. (Though often you may want to condier doing another control/controller) In this case, you can add a ```reactive_accessor```. These behave just like ```attr_accessor``` except the values assigned and returned are wrapped in a ReactiveValue. Updates update the existing ReactiveValue.
557
+ The default ModelController proxies any missing methods to its model. Since models are wrapped in ReactiveValues, they return ReactiveValues by default. Sometimes you need to store additional data reactively in the controller outside of the model. (Though often you may want to condier doing another control/controller). In this case, you can add a ```reactive_accessor```. These behave just like ```attr_accessor``` except the values assigned and returned are wrapped in a ReactiveValue. Updates update the existing ReactiveValue.
558
558
 
559
559
  ```ruby
560
560
  class Contacts < ModelController
@@ -564,6 +564,44 @@ The default ModelController proxies any missing methods to its model. Since mod
564
564
 
565
565
  Now from the view we can bind to _query while also changing in and out the model. You can also use ```reactive_reader``` and ```reactive_writer```
566
566
 
567
+ # Tasks
568
+
569
+ Sometimes you need to explicitly execute some code on the server. Volt solves this problem through *tasks*. You can define your own tasks by dropping a class into your component's ```tasks``` folder.
570
+
571
+ ```ruby
572
+ # app/main/tasks/logging_tasks.rb
573
+
574
+ class LoggingTasks
575
+ def initialize(channel=nil, dispatcher=nil)
576
+ @channel = channel
577
+ @dispatcher = dispatcher
578
+ end
579
+
580
+ def log(message)
581
+ puts message
582
+ end
583
+ end
584
+ ```
585
+
586
+ To invoke a task from a controller use ```tasks.call```.
587
+
588
+ ```ruby
589
+ class Contacts < ModelController
590
+ def hello
591
+ tasks.call('LoggingTasks', 'log', 'Hello World!')
592
+ end
593
+ end
594
+ ```
595
+
596
+ You can also pass a block to ```tasks.call``` that will receive the return value of your task as soon as it's done.
597
+
598
+ ```ruby
599
+ tasks.call('MathTasks', 'add', 23, 5) do |result|
600
+ # result should be 28
601
+ alert result
602
+ end
603
+ ```
604
+
567
605
  # Components
568
606
 
569
607
  Apps are made up of Components. Each folder under app/ is a component. When you visit a route, it loads all of the files in the component on the front end, so new pages within the component can be rendered without a new http request. If a URL is visited that routes to a different component, the request will be loaded as a normal page load and all of that components files will be loaded. You can think of components as the "reload boundary" between sections of your app.
@@ -593,7 +631,7 @@ Note above though that jquery and bootstrap are currently included by default.
593
631
 
594
632
  **Note, asset management is still early, and likely will change quite a bit**
595
633
 
596
- In volt, assets such as JavaScript and CSS (or sass) are automatically included on the page for you. Anything placed inside of a components asset/js or assets/css folder is served at /assets/{js,css} (via [Sprockets](https://github.com/sstephenson/sprockets)) Link and script tags are automatically added for each css and js file in assets/css and assets/js respectively. Files are included in their lexical order, so you can add numbers in front if you need to change the load order.
634
+ In Volt, assets such as JavaScript and CSS (or sass) are automatically included on the page for you. Anything placed inside of a components asset/js or assets/css folder is served at /assets/{js,css} (via [Sprockets](https://github.com/sstephenson/sprockets)). Link and script tags are automatically added for each css and js file in assets/css and assets/js respectively. Files are included in their lexical order, so you can add numbers in front if you need to change the load order.
597
635
 
598
636
  Any JS/CSS from an included component or component gem will be included as well. By default [bootstrap](http://getbootstrap.com/) is provided by the volt-bootstrap gem.
599
637
 
@@ -617,7 +655,7 @@ Remove the path: option in the gemfile if you wish to use the rubygems version.
617
655
 
618
656
  ## Provided Components
619
657
 
620
- Volt provides a few components to make web developers lives easier.
658
+ Volt provides a few components to make web developers' lives easier.
621
659
 
622
660
  ### Notices
623
661
 
@@ -641,7 +679,7 @@ These messages will show for 5 seconds, then disappear (both from the screen and
641
679
 
642
680
  # Controls
643
681
 
644
- Everyone wishes that we could predict the scope and required features for each part of our application, but in the real world, things we don't expect to grow large often do and things we think will be large don't end up that way. Controls let you quickly setup reusable code/views. The location of the control's code can be moved as it grows without changing the way controls are invoked.
682
+ Everyone wishes that we could predict the scope and required features for each part of our application, but in the real world, things we don't expect to grow large often do and things we think will be large don't end up that way. Controls let you quickly setup reusable code/views. The location of the controls code can be moved as it grows without changing the way controls are invoked.
645
683
 
646
684
  To render a control, simply use a tag like so:
647
685
 
@@ -675,7 +713,7 @@ Each part is explained below:
675
713
  Views are composed of sections. Sections start with a ```<:SectionName>``` and are not closed. Volt will look first for a section in the same view.
676
714
 
677
715
  2. views
678
- Next Volt will look for a view file that with the control name. If found, it will render the body section of that view.
716
+ Next Volt will look for a view file with the control name. If found, it will render the body section of that view.
679
717
 
680
718
  3. view folder
681
719
  Failing above, Volt will look for a view folder with the control name, and an index.html file within that folder. It will render the :body section of that view. If a controller exists for the view folder, it will make a new instance of that controller and render in that instance.
@@ -701,7 +739,7 @@ The above would search the following:
701
739
  | :body | index.html | comments | blog |
702
740
  | :body | index.html | comments | gems/blog |
703
741
 
704
- Once the view file for the control or template is found, it will look for a matching controller. If the control is specified as a local template, an empty ModelController will be used. If a controller is found and loaded, a corrosponding "action" method will be called on it if its exists. Action methods default to "index" unless the component or template path has two parts, in which case the last part is the action.
742
+ Once the view file for the control or template is found, it will look for a matching controller. If the control is specified as a local template, an empty ModelController will be used. If a controller is found and loaded, a corresponding "action" method will be called on it if its exists. Action methods default to "index" unless the component or template path has two parts, in which case the last part is the action.
705
743
 
706
744
  # Control Arguments/Attributes
707
745
 
@@ -739,9 +777,9 @@ Routes are specified on a per-component basis in the config/routes.rb file. Rou
739
777
 
740
778
  Routes take two arguments, a path, and a params hash. When a new URL is loaded and the path is matched on a route, the params will be set to the params provided for that route.
741
779
 
742
- When the params are changed, the URL will be set to the path for the route that's params hash matches.
780
+ When the params are changed, the URL will be set to the path for the route whose params hash matches.
743
781
 
744
- Route path's can also contain variables similar to bindings.
782
+ Route paths can also contain variables similar to bindings:
745
783
 
746
784
  ```ruby
747
785
  get "/todos/{_index}", _view: 'todos'
@@ -749,22 +787,22 @@ Route path's can also contain variables similar to bindings.
749
787
 
750
788
  In the case above, if any URL matches /todos/*, (where * is anything but a slash), it will be the active route. ```params._view``` would be set to 'todos', and ```params._index``` would be set to the value in the path.
751
789
 
752
- If ```params._view``` is 'todos' and ```params._index``` is not nil, the route would be matched.
790
+ If ```params._view``` were 'todos' and ```params._index``` were not nil, the route would be matched.
753
791
 
754
792
  Routes are matched top to bottom in a routes file.
755
793
 
756
794
  ## Debugging
757
795
 
758
- An in browser irb is in the works. We also have source maps support, but they are currently disabled due by default. To enable them run:
796
+ 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:
759
797
 
760
798
  MAPS=true volt s
761
799
 
762
- They are disabled by default because they slow down page rendering because so many files are rendered. 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)
800
+ 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)
763
801
 
764
802
 
765
803
  ## Channel
766
804
 
767
- 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:
805
+ 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:
768
806
 
769
807
  | method | description |
770
808
  |-------------|-----------------------------------------------------------|
@@ -788,7 +826,7 @@ Volt provides a data store collection on the front-end and the back-end. In sto
788
826
  store._things
789
827
  ```
790
828
 
791
- **Work in process**
829
+ **Work in progress**
792
830
 
793
831
  | state | events bound | description |
794
832
  |-------------|--------------|--------------------------------------------------------------|
@@ -799,4 +837,4 @@ store._things
799
837
 
800
838
  # Contributing
801
839
 
802
- You want to contribute? Great! Thanks for being awesome! At the moment, we have a big internal todo list, hop on #voltrb on freenode (irc) so we don't duplicate work. Pull requests are always welcome, but asking about helping on IRC should save some duplication.
840
+ 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.7.18
1
+ 0.7.19
@@ -11,7 +11,7 @@ class CLI < Thor
11
11
  directory("project", name, {version: version, name: name})
12
12
 
13
13
  say "Bundling Gems...."
14
- `cd #{name} ; bundle -j 4`
14
+ `cd #{name} && bundle`
15
15
  end
16
16
 
17
17
  desc "console", "run the console on the project in the current directory"
@@ -41,8 +41,6 @@ class ModelController
41
41
  end
42
42
 
43
43
  def initialize(*args)
44
-
45
-
46
44
  # Set the instance variable to match any passed in arguments
47
45
  if args.size > 0
48
46
  args[0].each_pair do |key, value|
@@ -65,11 +65,16 @@ module Persistors
65
65
  @model.attributes[:"#{path[-4].singularize}_id"] = source._id
66
66
  end
67
67
 
68
- @tasks.call('StoreTasks', 'save', collection, self_attributes) do |errors|
69
- if errors.size == 0
70
- promise.resolve
71
- else
72
- promise.reject(errors)
68
+ if !collection
69
+ puts "Attempting to save model directly on store."
70
+ raise "Attempting to save model directly on store."
71
+ else
72
+ @tasks.call('StoreTasks', 'save', collection, self_attributes) do |errors|
73
+ if errors.size == 0
74
+ promise.resolve
75
+ else
76
+ promise.reject(errors)
77
+ end
73
78
  end
74
79
  end
75
80
  end
@@ -73,7 +73,7 @@ module Validations
73
73
  if klass
74
74
  validate_with(merge, klass, field_name, args)
75
75
  else
76
- raise "validtion type #{validation} is not specified."
76
+ raise "validation type #{validation} is not specified."
77
77
  end
78
78
  end
79
79
  end
@@ -95,4 +95,4 @@ module Validations
95
95
  puts "Unable to find #{validation} validator"
96
96
  end
97
97
  end
98
- end
98
+ end
@@ -46,7 +46,7 @@ class Tasks
46
46
  if callback
47
47
  if error
48
48
  # TODO: full error handling
49
- puts "Error2: #{error.inspect}"
49
+ puts "Task Response: #{error.inspect}"
50
50
  else
51
51
  callback.call(result)
52
52
  end
@@ -136,10 +136,6 @@ class ReactiveValue < BasicObject
136
136
  end
137
137
  end
138
138
  end
139
- #
140
- # def respond_to?(name, include_private=false)
141
- # [:event_added, :event_removed].include?(name) || super
142
- # end
143
139
 
144
140
  def respond_to_missing?(name, include_private=false)
145
141
  cur.respond_to?(name)
@@ -428,5 +424,4 @@ class ReactiveManager
428
424
  def setter!(setter=nil, &block)
429
425
  @setter = setter || block
430
426
  end
431
-
432
427
  end
@@ -67,7 +67,7 @@ class ViewScope
67
67
  end
68
68
 
69
69
  def add_each(content)
70
- @handler.scope << EachScope.new(@handler, @path, content)
70
+ @handler.scope << EachScope.new(@handler, @path + "/__each#{@binding_number}", content)
71
71
  end
72
72
 
73
73
  def add_template(content)
@@ -1,5 +1,6 @@
1
1
  require 'json'
2
2
  require 'sockjs/session'
3
+ require File.join(File.dirname(__FILE__), "../../../app/volt/tasks/query_tasks")
3
4
 
4
5
  class SocketConnectionHandler < SockJS::Session
5
6
  # Create one instance of the dispatcher
@@ -114,7 +114,7 @@ describe ViewParser do
114
114
  view = ViewParser.new(html, "main/main/main")
115
115
 
116
116
  expect(view.templates).to eq({
117
- "main/main/main/body/__template/0" => {
117
+ "main/main/main/body/__each0/__template/0" => {
118
118
  "html" => "\n <p><!-- $0 --><!-- $/0 --></p>\n ",
119
119
  "bindings" => {
120
120
  0 => [
@@ -126,7 +126,7 @@ describe ViewParser do
126
126
  "html" => " <div class=\"main\">\n <!-- $0 --><!-- $/0 -->\n </div>\n",
127
127
  "bindings" => {
128
128
  0 => [
129
- "lambda { |__p, __t, __c, __id| EachBinding.new(__p, __t, __c, __id, Proc.new { _items }, \"item\", \"main/main/main/body/__template/0\") }"
129
+ "lambda { |__p, __t, __c, __id| EachBinding.new(__p, __t, __c, __id, Proc.new { _items }, \"item\", \"main/main/main/body/__each0/__template/0\") }"
130
130
  ]
131
131
  }
132
132
  }
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.7.18
4
+ version: 0.7.19
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-06-06 00:00:00.000000000 Z
11
+ date: 2014-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor